Golang中的Channel詳解(一):定義與基本操作
Golang中的channel是不同goroutines之間進行通信和同步的橋梁,借助channel,可以很方便寫多協程通信程序。
如何理解channel
Channel是一個協程安全的管道,一端寫入數據,一端讀取數據,寫入和讀取都是原子操作,有點類似于消息隊列,只不過channel是內存級別的。在channel出現之前,需要手動管理共享內存,這樣會帶來一定的復雜度和不可知的問題。而channel提供了一種更簡單、更安全的方式來進行并發編程,借助channel,可以在不共享內存的情況下實現多個goroutine之間的通信。
channel的基本操作
使用make()函數來創建一個channel示例,并且需要指定channel中元素的類型和容量(可選),例如:
ch := make(chan int) // 創建一個int類型的channel
這條創建語句沒有指定容量,就是創建了一個無緩沖的channel,如果一個goroutine往這個channel發送數據,那么這個oroutine就會被阻塞住,直到有其它goroutine讀取了channel 的數據才能繼續運行。創建channel時如果指定了容量,就是有緩沖的channel,例如:
ch := make(chan int, 10) // 創建一個容量為10的int類型的channel
對于有緩沖的channel來說,只要當前channel里的元素總數不大于這個指定的容量,當前的goroutine就不會被阻塞住。
往channel寫數據使用<-操作符,例如:
ch := make(chan int)
ch <- 1 //將值1發送到通道中
從channel讀取數據也是使用<-操作符,例如:
val := <- ch //從通道中接收上一個發送的值
當不再使用channel時,使用close()方法關閉channel,例如:
close(ch)
當channel關閉后,如果繼續往里面寫數據,則會panic;如果繼續讀的話,不會產生panic,如果還有數據的話也可以讀到數據,如果沒有數據的話將得到零值(對應類型的默認值)。判斷當前channel是否被關閉,可以使用下面的寫法:
if v, ok := <-ch; !ok {
fmt.Println("channel已關閉并且數據已被讀完")
}
也可以使用for range的方式,讀取完數據后循環也隨著結束,例如:
for v := range ch {
// ...
}