網上關於channel的使用有很多介紹,這裏不在闡述,這裏主要是記錄下開發中,可能存在使用channel不當造成的問題總結下, 說道這裏,還是總結下channel的幾個特性吧:
說道這裏,還是總結下channel的幾個特性吧:
-
給一個 空 channel發送數據,會造成永遠阻塞
-
從一個 空 channel接收數據,會造成永遠阻塞
-
給一個已經關閉的channel發送數據,會引起 panic
-
從一個已經關閉的channel接收數據,如果緩衝區中爲空,則返回一個零值
-
無緩衝的channel是同步的,有緩衝的channel是異步的
廢話不多說,大家看下下面的代碼是如何執行的,輸出結果是什麼?
package main import ( "fmt" "time" ) func main() { chn := make(chan int, 1000) //定義一個1000容量的channel go func() { for i := 0; i < 10; i++ { // 向管道chn發送寫入10個數字 chn <- i } }() go func() { // 開啓一個攜程 循環從chn中獲取值 for { i, ok := <-chn if !ok { // 取值爲空或零 fmt.Println("chn已經關閉") return } fmt.Println("i = ", i) } }() close(chn) // 這裏直接關閉了chn fmt.Println("sucess") time.Sleep(time.Minute * 1) // 等待1分鐘讓攜程全部執行完畢 }
上面代碼最大的問題在哪裏? 很明顯。代碼中開啓了兩個go攜程,第一個寫數據,第二個讀取數據,開完兩個goroutine之後main主攜程直接close掉channel,
然後直接輸出打印:success。
但是往已經關閉的channel寫入數據會panic的。所以上面的結果輸出:
sucess chn已經關閉 panic: send on closed channel goroutine 6 [running]: main.main.func1() /media/uos/G/web/demo-go/main.go:12 +0x36 created by main.main /media/uos/G/web/demo-go/main.go:10 +0x6b exit status 2