首頁 >後端開發 >Golang >Go Channels:為什麼我的「select」語句中的逾時沒有觸發?

Go Channels:為什麼我的「select」語句中的逾時沒有觸發?

DDD
DDD原創
2024-12-26 03:37:09404瀏覽

Go Channels: Why Doesn't My Timeout in a `select` Statement Ever Trigger?

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn