1. 程式人生 > >理解golang中的channel

理解golang中的channel

channel是goroutine之間的通訊機制。可以類比執行緒間的通訊,執行緒間的通訊有多種方式,比如執行緒上下文、共享記憶體、IPC通訊、socket實現不同機器間的通訊。

channel用起來很簡單,繫結一個變數,一端往裡塞,一端從裡面取。我把它理解為接收端啟動了一個類似HTTP伺服器的東西,傳送端往接收端的HTTP伺服器傳送一條get請求,接收端就收到了,可以解析拿到請求的引數再做要做事情。

如何建立一個channel?

ch := make(chan int) // 建立一個channel

channel是有型別的,int型別的channel就只能傳輸int型別的資料,想傳輸string型別的資料建立的時候需要改為 ch := make(chan string)

如何向channel傳送資料?

ch <- 123  // 向int型別的channel傳送資料123

如何從接收資料?

x = <- ch

或者也可以不要接受物件

<- ch

 

可以看出,不管是傳送還是接收資料,用的都是 <- ,區別在於 <- 指向的物件是普通變數還是channel,如果是channel被指向就是給channel傳送資料,如果是普通變數被指向就是從channel中取資料。

 

channel是可以帶快取的,我們前面建立的channel是沒帶快取的。有快取和無快取有什麼區別嗎?

快取的存在是為了抹平channel傳送端和接收端速度不匹配造成的資源浪費。比方說一個人扔蘋果,一個人接蘋果,扔的人扔的速度比接的人速度快,這時候蘋果就會掉到地上了。如果沒有快取,我們該如何解決這個問題?

可以用阻塞的方式來解決。比方說我們約定,扔蘋果的人在接蘋果的人沒有接到蘋果之前,不能繼續扔蘋果了,要等到接蘋果的人接到蘋果才可以繼續。這就是阻塞。

在無快取的情況下,channel傳送端在傳送後會阻塞,直到傳送的陣列在channel裡被別人接收了才可以繼續。反過來如果接收操作先發生,那麼接收端會被阻塞,直到它等到channel裡傳來的資料才恢復。

 

可以看出,在無快取的情況下,channel之間的通訊是同步的,一個等一個。快取的出現讓channel擺脫了同步,變成了非同步的形式。

還是剛剛扔蘋果的例子,扔蘋果的速度比接蘋果的速度快,這次接蘋果的人在腳下放了一個框,說“這個框可以裝10個蘋果,你把蘋果都扔到這個框裡,我慢慢取。當然如果框裡已經有10個蘋果的時候,就不能再扔了,只能等到我取出蘋果以後再扔。”

這樣傳送者和接收者的速度差就被快取減小了一部分,我可以多來一個接收者從框裡取蘋果來加快接收端的速度。

如何建立一個待快取的channel?

ch := make(chan int, 10)  // 建立一個可以存放10個int型資料的channel

  

channnel也可以關閉,關閉以後對這個channel的任何傳送操作都會導致panic異常,但是還可以從這個channel中接收資料,如果channel裡還有之前成功傳送的資料,是可以取到的,但是如果channel已經空了,那就將返回一個零值。

關閉channel可以用

close(ch)  // 關閉channel