還在學習中,理解的更爲透徹了再來總結。緩存
無緩存channel每一個發送和接收操做的同步性,由於因爲無緩衝區,因此其餘goroutine的發送會被阻塞在那邊,只有接收完畢後,某個goroutine才能寫入這個channel。異步
有緩衝區channel會使得讀寫routine(或者說是收發goroutine)是異步的,只要再緩衝區沒有滿,其餘的協程就能繼續寫,緩衝區不空,其餘的協程就能繼續讀。學習
若是是unbuffered channel,那麼發送者的goroutine會被阻塞,直到被別的goroutine接收後纔會繼續往下走。以下這段代碼是錯誤的,會一直被阻塞,go run的時候報錯:spa
1 func main() { 2 ch := make(chan int) //unbuffered channel 3 a := 10 4 ch <- a //blocked here 5 b := <-ch 6 fmt.Println(b) 7 }
fatal error: all goroutines are asleep - deadlock!code
goroutine 1 [chan send]協程
有兩種方法修改,第一種改爲buffered channel:blog
1 func main() { 2 ch := make(chan int, 1) //buffered channel 3 a := 10 4 ch <- a 5 b := <-ch 6 fmt.Println(b) 7 } //正確輸出10
第二種是將發送這個動做放在一個goroutine中,這樣就不會阻塞主goroutine,主goroutine中的接收動做就得以完成:get
1 func main() { 2 ch := make(chan int) //unbuffered channel 3 a := 10 4 go func() { ch <- a }() // new a goroutine 5 b := <-ch 6 fmt.Println(b) 7 }
ubuffered channel的發送和接收goroutine之間是同步的,不是異步的。帶緩衝區的channel是異步的。同步
channel的零值是nil,注意:若是其通道是nil,它將永遠不會被選擇。it
一、若是channel已經關閉,繼續往它發送數據會致使panic: send on closed channel
二、關閉一個已經關閉的channel,會致使panic:close of closed channel
三、讀取一個已經關閉的channel,能夠讀出沒有讀完的channel。讀完後會讀到零值。能夠屢次讀取。
1 func test(){ 2 ch:=make(chan int,3) 3 ch<-3 4 ch<-2 5 ch<-1 6 close(ch) 7 fmt.Print(<-ch) 8 fmt.Print(<-ch) 9 fmt.Print(<-ch) 10 fmt.Print(<-ch) 11 fmt.Print(<-ch) 12 } 13 //right
不能經過判斷返回值是不是零值(包括nil)來判斷channel是否已經關閉,應爲nil能夠做爲值傳遞給channel:
1 func main() { 2 ch := make(chan interface{}, 10) 3 ch <- nil 4 5 a := <-ch 6 fmt.Println(a) //輸出nil,沒有close 7 }