使用go通道,經常會遇到死鎖錯誤,根據我所遇到做了以下整理:
fatal error: all goroutines are asleep - deadlock!
看下面這段**
package main
import "fmt"
func main()
執行會丟擲錯誤,如下
fatal error: all goroutines are asleep - deadlock!
上述**中,情況是先往通道中存入資料,再從通道中讀取資料。似乎沒問題,但是對於使用 make 建立通道的時候,若不傳遞第二個引數,則你定義的是無緩衝通道,而對於無緩衝通道,在接收者(stdout)未準備好之前,傳送操作是阻塞的。因此,對於解決此問題有兩種方法:
第一種方法:使接收者**在傳送者之前執行
若要程式正常執行,需要保證接收者程式在傳送資料到通道前就進行阻塞狀態(準備好),修改**如下
package main
import "fmt"
func main()
然而執行的時候還是報同樣的錯誤。問題出在**呢?原來我們將傳送者和接收者寫在了同一協程中,雖然保證了接收者**在傳送者之前執行,但是由於前面接收者一直在等待資料 而處於阻塞狀態,所以無法執行到後面的傳送資料。還是一樣造成了死鎖。
這樣的話,我們可以將接收者**寫在另乙個協程裡,並保證在傳送者之前執行,就像這樣:
package main
import "fmt"
func hello(pipline chan string)
func main()
執行之後 ,一切正常。
第二種方法:使用緩衝通道,而不使用無緩衝通道
接收者**必須在傳送者**之前 執行,這是針對無緩衝通道才有的約束。
既然這樣,我們改使用可緩衝通道不就ok了嗎?
package main
import "fmt"
func main()
執行之後,一切正常。
每個緩衝通道,都有容量,當通道裡的資料量等於通道的容量後,此時再往通道裡傳送資料,就會造成阻塞,必須等到有人從通道中消費資料後,程式才會往下進行。
比如這段**,通道容量為 1,但是往通道中寫入兩條資料,對於乙個協程來說就會造成死鎖。
package main
import "fmt"
func main()
當程式一直在等待從通道裡讀取資料,而此時並沒有人會往通道中寫入資料。此時程式就會陷入死迴圈,造成死鎖。
比如這段**,for 迴圈接收了兩次訊息("hello world"和「hello china」)後,再也沒有人傳送資料了,接收者就會處於乙個等待永遠接收不到資料的囧境。陷入死迴圈,造成死鎖。
package main
import "fmt"
func main() ()
for data := range pipline
}
包子鋪裡的包子已經賣完了,可還有人在排隊等著買,如果不再做包子,就要告訴排隊的人:不用等了,今天的包子已經賣完了,明日請早呀。
不能讓人家死等呀,不跟客人說明一下,人家還以為你們店後面還在蒸包子呢。
所以這個問題,解決方法很簡單,只要在傳送完資料後,手動關閉通道,告訴 range 通道已經關閉,無需等待就行。
package main
import "fmt"
func main() ()
for data := range pipline
}
Go語言容易踩的坑
本文章記錄go學習過程中的一些容易忽視的地方。package main import fmt 會先把defer全部出棧,看有沒有recover defer出完之後,沒有recover,則報錯 func main1 defer func defer func panic 觸發異常 func calc ...
golang chan 踩坑 通道特性
golang 在協程中都會用到chan 用於資料同步,在併發場景下一般都會使用到這個,簡單場景就是乙個讀取,乙個寫入,所以chan都是成對出現的,現在主要來說明一下有緩衝和無緩衝的場景對比。ch1 make chan int 無緩衝 ch2 make chan int,1 有緩衝 ch1 5 無緩衝...
GO語言結構體物件轉JSON踩坑記錄
多說無益 上 第乙個需要注意的地方 響應資料 rsp writecontent,json.marshal rsp recordlog.debug string writecontent w.write writecontent 第一處需要注意 在定義結構體的時候 注意在變數後新增json xx 字串...