我正在學習 Go 語言。這是我遇到的一個例子。有人可以解釋一下這里發生了什么嗎?package mainimport "time"import "fmt"func main() { c1 := make(chan string) c2 := make(chan string) go func() { time.Sleep(time.Second * 1) c1 <- "one" }() go func() { time.Sleep(time.Second * 2) c2 <- "two" }() for i := 0; i < 2; i++ { select { case msg1 := <-c1: fmt.Println("received", msg1) case msg2 := <-c2: fmt.Println("received", msg2) default: fmt.Println("Default") } }}輸出:DefaultDefaultProgram Exited如果我注釋掉默認部分//default:// fmt.Println("Default")輸出變為:received onereceived twoProgram exited.default案例的存在如何改變通道阻塞的工作方式?
2 回答

慕的地6264312
TA貢獻1817條經驗 獲得超6個贊
這與select
語句在 Go 中的工作方式有關。
如果可以進行一個或多個通信,則通過統一偽隨機選擇選擇可以進行的單個通信。否則,如果存在默認情況,則選擇該情況。如果沒有默認情況,“select”語句會阻塞,直到至少有一個通信可以繼續。
因此,如果沒有默認情況,代碼將一直阻塞,直到任一通道中的某些數據可用。它隱式地等待其他 goroutines 喚醒并寫入它們的通道。
當您添加 default case 時,很可能select
在其他 goroutines 從睡眠中醒來之前到達該語句。
因此,由于(尚)沒有可用數據,并且存在默認情況,因此會執行默認情況。此操作進行兩次,耗時不到 1 秒。所以程序在任何 go 例程有機會喚醒并寫入通道之前終止。
請注意,這在技術上是一種競爭條件;絕對不能保證循環的 2 次迭代會在任何 go 例程喚醒之前運行,因此理論上即使在默認情況下也可能有不同的輸出,但實際上這是極不可能的。
- 2 回答
- 0 關注
- 321 瀏覽
添加回答
舉報
0/150
提交
取消