我正在通過示例學習 Go。我剛剛實作了一個選擇來等待多個頻道,如下所示:
for i := 0; i < 2; i {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
}
}
通過一些實驗,我發現我可以天真地引入運行時錯誤,如下所示:
如果我將 i 減少到 1,則收到第一條訊息,但第二條訊息會默默丟失(沒有跡象表明我無意中忽略了它)。
如果我將 i 增加到 3,則會收到兩條訊息,但我得到
fatal error: all goroutines are asleep - deadlock!
提前閱讀并在 StackOverflow 上搜索該錯誤訊息,我可以看到 WaitGroups 解決了這些型別的問題。但它們似乎不適用于select,所以我覺得我一定錯過了一些東西。
是否有一種語言結構(如if/then/else)或軟體模式可以用來防止或減輕實際代碼中的這些錯誤?
uj5u.com熱心網友回復:
從概念上講,您可以通過正確設計軟體來緩解這種情況。如果您有兩個頻道,并且每個頻道最多會收到一條訊息,請不要嘗試從它們讀取 3 次。這與嘗試將三個專案放在一個二元素陣列中,或者嘗試將除數為 0 的兩個數字相除沒有什么不同。在所有這些情況下,語言都提供了發現錯誤并從錯誤中恢復的方法,但是如果您實際上是在生產這些錯誤,它表明存在邏輯或設計缺陷。
您需要確保您的通道具有平衡的讀寫次數,并且發送端在沒有其他內容可發送時關閉通道,以便接收者可以停止等待不會到來的訊息。否則,您最終將等待某些東西,或者緩沖區中的訊息被忽略。
在這種非常特殊的情況下,如果您想從兩個通道讀取但僅在訊息準備好時,您可以添加一個default案例,如果沒有通道準備好讀取,則將呼叫該案例,但這是針對您的通道尚未準備好的情況但最終會準備好。提供 adefault并不是一個很好的解決方案來覆寫通道永遠不會準備好但您仍在嘗試從中讀取的錯誤;這表明需要修復的邏輯級缺陷。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/443016.html
上一篇:接收未定義而不是JSON
