go channel的學習總結

2021-09-12 07:51:28 字數 3010 閱讀 6652

channel是goland中一種特殊的型別的存在,對於goland的學習來說是非常重要的。

channel是goland中goroutine間的通訊的一種方式,可以模擬成 unix 中的程序的通訊方式管道。

因為goland是乙個支援併發的程式語言,而且channel又在併發中起了關鍵作用,所以我們簡單介紹一下併發模型,傳統的併發模型主要是actor和gsp兩種,這裡我們主要介紹gsp模型,因為goland的併發模型就是參考的gsp,gsp英文全稱:communicating sequential processes,gsp模型由併發執行實體和訊息通道組成,併發執行實體就是程序,執行緒或者協程,實體之間通過訊息通道傳送訊息,接收訊息進行通訊;和actor模型不同的是,gsp模型更看重傳送訊息的載體,即訊息通道,而在goland中併發執行實體就是goroutine,訊息通道就是channel。

就像上面說的channel提供了一種通訊機制,兩個或者多個goroutine之間可以通過channel進行通訊(共享記憶體),channel本身關聯了一種資料型別,即在建立channel的時候需要指定channel所要承載的資料型別。

1,向未初始化的channel中讀寫資料,會造成永久阻塞

2,向快取區已滿的channel中寫入資料,會造成暫時阻塞

3,向沒有資料的channel中讀資料,會造成暫時阻塞

channel使用內建的make函式建立,make中包括兩個引數,第乙個即型別,然後是容量

ch:=make(chan int)
如果像上面一樣定義的話,就是無快取通道,若加乙個引數n,就代表是乙個帶有n個快取的通道

和map,slice類似,make建立了乙個對底層資料結構的引用,當賦值或者引數傳遞時是拷貝了乙個channel的引用,他們指向同乙個底層資料結構,和其他引用型別一樣,channel 的空值為 nil 。使用 == 可以對型別相同的 channel 進行比較,只有指向相同物件或同為 nil 時,才返回 true

//建立乙個channel

ch :=make(chan int)

//向channel中傳送乙個資料

ch <- x

//read

x<-ch

x:=<-ch

我們必須明確讀寫資料的格式,因為後面還會涉及到唯讀channel,和只寫channel,必須能夠區分開

我們簡單介紹一下就好,很好理解,

ch:=make(<-chan int)

ch1:=make(chan<- int)

如上定義的,ch就是乙個唯讀channel,我們不能向ch中寫資料,而ch1就是乙個只寫channel,我們只能向channel中寫資料,其實用channel就能完成他們的功能,只是有時候我們需要防止對channel的濫用

這裡不是重點介紹如何關閉channel,相信大家都知道,通過內建函式close()進行關閉,我們要介紹的是一些注意事項

有關 channel 的關閉,你需要注意以下事項:

1,關閉乙個未初始化(nil) 的 channel 會產生 panic

2,重複關閉同乙個 channel 會產生 panic

3,向乙個已關閉的 channel 中傳送訊息會產生 panic

4,從已關閉的 channel 讀取訊息不會產生 panic,且能讀出 channel 中還未被讀取的訊息,若訊息均已讀出,則會讀到型別的零值。從乙個已關閉的 channel 中讀取訊息永遠不會阻塞,並且會返回乙個為 false 的 ok-idiom,可以用它來判斷 channel 是否關閉

5,關閉 channel 會產生乙個廣播機制,所有向 channel 讀取訊息的 goroutine 都會收到訊息

func main()

k,ok:=<-ch

fmt.println(k,ok)

}

c:\users\my\go\src\hello\learn>go run test2.go12

0 false

有時候在main中發起乙個go可能還沒結束,主協程已經結束了,所以可以採用ch來阻塞main goroutine

func main()

func sum(nums int,ch chan int)

ch <-sum

}

ch := make(chan int, 10)

for x := range ch

等價於:

for 

fmt.println(x)

}

其中ok欄位是乙個bool型,讀取成功則返回true

select可以同時監聽多個channel,

select
1 select 可以同時監聽多個 channel 的寫入或讀取

2 執行 select 時,若只有乙個 case 通過(不阻塞),則執行這個 case 塊

3 若有多個 case 通過,則隨機挑選乙個 case 執行

4 若所有 case 均阻塞,且定義了 default 模組,則執行 default 模組。若未定義 default 模組,則 select 語句阻5 塞,直到有 case 被喚醒。

6 使用 break 會跳出 select 塊。

ch := make(chan struct{})

// finish task while send msg to ch

go dotask(ch)

timeout := time.after(5 * time.second)

select

time.after返回的就是乙個channel,當時間超過設定時間時,timeout中就會有值,即為超時時間

當然我們也可以設定乙個停止channel,即當滿足乙個條件時向channel中寫入乙個資訊,當讀取到這個channel中的資訊時,結束select。

3種優雅的Go channel用法

寫go的人應該都聽過rob pike的這句話 do not communicate by sharing memory instead,share memory by communicating.相信很多朋友和我一樣,在實際應用中總感覺不到好處,為了用channel而用。但以我的切身體會來說,這是寫...

你不知道的go channel

最近在開發過程當中遇到了幾個goroutine通訊的問題,我覺得這幾個問題非常具有代表性,因此拿出來和大家分享一下。開發過程當中有遇到這樣的一種情況,需要檢查channel是否關閉,如果關閉則不進行相應操作,否則會panic等現象。在golang的select語法當中,default分支可以解決上述...

go channel 有快取和無快取的區別

無緩衝的與有緩衝channel有著重大差別,那就是乙個是同步的 乙個是非同步的。比如c1 make chan int 無緩衝 c2 make chan int,1 有緩衝 c1 1 無緩衝 不僅僅是向 c1 通道放 1,而是一直要等有別的攜程 c1 接手了這個引數,那麼c1 1才會繼續下去,要不然就...