首頁 > 後端開發 > Golang > 如何在帶有通道的 Go Goroutine 中正確實現逾時?

如何在帶有通道的 Go Goroutine 中正確實現逾時?

DDD
發布: 2024-11-08 14:57:02
原創
328 人瀏覽過

How to Implement Timeouts Correctly in Go Goroutines with Channels?

在 Go 中使用超時和通道

Goroutines 和通道為 Go 中的並發編程提供了強大的機制。然而,處理 goroutine 中的超時可能會很棘手。

在您想要使用 goroutine 和超時檢查 URL 清單的可及性的場景中,可能存在超時不會被執行的情況,即使一些 URL 無法存取。

讓我們來分析一下提供的程式碼:

func check(u string) bool {
    time.Sleep(4 * time.Second)
    return true
}

func IsReachable(urls []string) bool {
    ch := make(chan bool, 1)
    for _, url := range urls {
        go func(u string) {
            select {
            case ch <- check(u):
            case <-time.After(time.Second):
                ch <- false
            }
        }(url)
    }
    return <-ch
}
登入後複製

問題出在 check 函數。當你在 goroutine 中使用 time.Sleep 時,它會暫停目前的 goroutine,在這個例子中是運行 check 函數的 goroutine。當 check 函數暫停時,外層 goroutine 中的 select 語句仍會嘗試執行。

在這種情況下,select 語句的兩個分支(檢查結果或逾時)將在 4 年後執行檢查返回時的秒數。然而,由於兩個分支都是可運行的,運行時可以選擇執行其中一個,這可能會導致始終返回 true。

要解決這個問題,您需要為每個檢查函數建立一個新的goroutine,如下所示更正後的程式碼如下:

func check(u string, checked chan<- bool) {
    time.Sleep(4 * time.Second)
    checked <- true
}

func IsReachable(urls []string) bool {
    ch := make(chan bool, 1)
    for _, url := range urls {
        go func(u string) {
            checked := make(chan bool)
            go check(u, checked)
            select {
            case ret := <-checked:
                ch <- ret
            case <-time.After(time.Second):
                ch <- false
            }
        }(url)
    }
    return <-ch
}
登入後複製

這種情況下,check函數是在一個單獨的goroutine中執行的,確保它不會暫停外層goroutine,並且超時可以正確執行。

以上是如何在帶有通道的 Go Goroutine 中正確實現逾時?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板