channel(管道)-基本介紹
為什么需要channel?前面使用全局變量加鎖同步來解決goroutine的通訊,但不完美
1)主線程在等待所有goroutine全部完成的時間很難確定,我們這里設置10秒,僅僅是估算。
2)如果主線程休眠時間長了,會加長等待時間,如果等待時間短了,可能還有goroutine處于工作狀態,這時也會隨主線程的退出而銷毀
3)通過全局變量加鎖同步來實現通訊,也并不利用多個協程對全局變量的讀寫操作。
4)上面種種分析都在呼喚一個新的通訊機制-channel
package mainimport ("fmt""sync""time"
)var (m = make(map[int]int, 10)//聲明一個全局的互斥鎖 lock是一個全局的互斥鎖//sync是包 同步的意思 mutex是互斥的意思lock sync.Mutex
)// test函數就是計算n的階乘
func test(n int) {res := 1for i := 1; i <= n; i++ {res = res * i}//將計算結果放到map當中 加鎖lock.Lock()m[n] = reslock.Unlock()
}func main() {//這里開啟多協程完成任務for i := 1; i <= 20; i++ {go test(i)}time.Sleep(time.Second * 10)for k, v := range m {fmt.Println(k, v)}
}
?
channel的介紹
1)channle本質就是一個數據結構-隊列【示意圖】
2)數據是先進先出
3)線程安全,多goroutine訪問時,不需要加鎖,就是說channel本身就是線程安全的(管道是線程安全的,你在對管道讀取的時候不管有多少個協程在對同一個管道操作,可以放心使用,不會出現錯誤,這些是有編譯器在底層維護的)
4)channel時有類型的,一個string的channel只能存放string類型數據。(如果管道想放int或者float那么可以使用空接口interface類型)
?
定義/聲明channel
var變量名chan敞據類型
舉例:
var intChan chan int (intChan用于存放int數據)
var mapChan chan map[int]string (mapChan用于存放map[int]string類型)
var perChan chan Person
var perChan2 chan *Person
說明:
1)channel是引用類型
2)channel必須初始化才能寫入數據,即make后才能使用
3)管道是有類型的,intChan只能寫入整數int
channel初始化
說明:使用make進行初始化
var intChan chan int
intChan =make(chan int,10)
向channel中寫入(存放)數據
var intChan chan int
intChan =make(chan int,10)
num =999
intChan<-10
intChan<-num
如果將channel傳給另外一個函數,那么在這個函數里面操作的是同一個管道,因為它是引用類型。
package mainimport "fmt"func main() {var intChan chan int//創建可以存放3個int類型的管道intChan = make(chan int, 3)//看看intChan是什么fmt.Printf("initChan的值為=%v\ninitChan本身地址為%p\n", intChan, &intChan)//向管道寫入數據intChan <- 1num := 2intChan <- num//當給管道寫入數據的時候,不能超過其容量//看看管道的長度和capfmt.Println("長度:", len(intChan), "容量:", cap(intChan))num1 := <-intChanfmt.Println("取出來的第一個數據是:", num1)fmt.Println("取出之后的長度:", len(intChan), "取出之后的容量:", cap(intChan))//在沒有使用協程的情況下,如果我們的管道數據已經全部取出,再取就會報告deadlock
}initChan的值為=0xc00007a080
initChan本身地址為0xc00000a028
長度: 2 容量: 3
取出來的第一個數據是: 1
取出之后的長度: 1 取出之后的容量: 3
?
?
?
?channel使用注意事項
1.channel中只能存放指定的數據類型
2.channle的數據放滿后,就不能再放入了(會出現死鎖的錯誤)
3.如果從channel取出數據后,可以繼續放入
4.在沒有使用協程的情況下,如果channel數據取完了,再取,就會報dead lock
?管道里面可以存放很多map,每個map里面又可以有多對的key/value。這里在使用map之前要先make一把。
?管道也是可以存放結構體實例的。