Go Channels:為什麼超時仍未執行
考慮使用 Goroutine 和 Channel 的場景,如下面的程式碼片段所示。為什麼超時場景永遠不會發生?
func main() { c1 := make(chan int, 1) go func() { for { time.Sleep(1500 * time.Millisecond) c1 <- 10 } }() go func() { for { select { case i := <-c1: fmt.Println(i) case <-time.After(2000 * time.Millisecond): fmt.Println("TIMEOUT") // Not Executed } } }() fmt.Scanln() }
分析
超時場景不會發生,因為 goroutine 大約每 1.5 秒不斷向 c1 通道發送值。只有在 2 秒內沒有從 c1 接收到值時,逾時才會生效。
但是,當從 c1 接收到值時,一個新的時間。在後續 select 執行中呼叫後,產生一個新的通道其中僅在另外 2 秒後才會發出值。上一次 select 執行的逾時通道將被丟棄,使其無效。
解決方案
要解決此問題,超時通道應該只創建一次,有效:
timeout := time.After(2000 * time.Millisecond) for { select { case i := <-c1: fmt.Println(i) case <-timeout: fmt.Println("TIMEOUT") // Will be printed after 2 seconds } }
輸出
修改後的程式碼隨後列印:
10 TIMEOUT 10 10 10 ...
因此,超時場景現在在2 後成功執行秒,反映預期行為。
以上是Go Channels:為什麼我的「select」語句中的逾時沒有觸發?的詳細內容。更多資訊請關注PHP中文網其他相關文章!