首頁 >後端開發 >Golang >如何使用 Go 中的通道可靠地覆蓋 Goroutine 逾時?

如何使用 Go 中的通道可靠地覆蓋 Goroutine 逾時?

Susan Sarandon
Susan Sarandon原創
2024-12-14 20:56:21216瀏覽

How Can I Reliably Override Goroutine Timeouts Using Channels in Go?

使用Channel 覆蓋Goroutine 中的超時

在Golang 中,當使用Goroutines 和Channel 執行非同步任務時,可以指定超時以確保操作不會無限期地掛起。然而,在某些場景下,超時情況可能不會如預期執行。

考慮以下程式碼片段:

package main

import (
    "fmt"
    "time"
)

func main() {
    c1 := make(chan int, 1) // Buffered channel with capacity 1

    go func() {
        for {
            time.Sleep(1500 * time.Millisecond) // Sleep for 1.5 seconds
            c1 <- 10 // Send value to channel
        }
    }()

    go func() {
        for {
            select {
            case i := <-c1:
                fmt.Println(i)
            case <-time.After(2000 * time.Millisecond):
                fmt.Println("TIMEOUT") // Not executed
            }
        }
    }()

    fmt.Scanln() // Wait for user input
}

在這段程式碼中,我們有兩個goroutine:一個定期發送一個值傳送到緩衝通道c1,另一個值從c1 中選擇,超時時間為2 秒。但是,超時情況(“TIMEOUT”)永遠不會被列印。

原因在於緩衝通道的性質以及逾時的處理方式。在這種情況下,向 c1 發送值的 goroutine 將每隔 1.5 秒不斷地重新填充通道。因此,第二個 goroutine 中的 select 語句總是會在逾時到期之前從 c1 接收到一個值。

為了解決這個問題並確保逾時情況被執行,我們需要在外部建立超時通道選擇循環。這樣可以防止每次從c1 接收到值時都將其丟棄:

timeout := time.After(2000 * time.Millisecond) // Create timeout channel only once
for {
    select {
    case i := <-c1:
        fmt.Println(i)
    case <-timeout:
        fmt.Println("TIMEOUT")
    }
}

透過此修改,select 語句將繼續從c1 中選擇,但如果在指定超時內沒有接收到值,則“TIMEOUT”情況將被執行。

以上是如何使用 Go 中的通道可靠地覆蓋 Goroutine 逾時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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