Go 實例教學: 逾時

對於連接外部資源或需要限制執行時間的程式來說,逾時非常重要。在 Go 中使用通道和 select 進行逾時操作既輕鬆又優雅。

package main
import (
    "fmt"
    "time"
)
func main() {

在我們的範例中,假設我們執行的外部呼叫會在 2 秒後在通道 c1 上傳回結果。請注意通道有緩衝,因此 go 常式中的傳送是非封鎖的。這是一種常見模式,可以在通道未讀取時避免 go 常式洩漏。

    c1 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c1 <- "result 1"
    }()

這是實作逾時的 selectres := <-c1 等待結果而 <-time.After 在 1 秒的逾時後等待要傳送的值。由於 select 會使用準備好的第一個接收項目繼續進行,因此如果操作花費超過允許的 1 秒,我們將採用逾時情況。

    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(1 * time.Second):
        fmt.Println("timeout 1")
    }

如果我們允許 3 秒的較長逾時,則來自 c2 的接收會成功,我們會列印結果。

    c2 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "result 2"
    }()
    select {
    case res := <-c2:
        fmt.Println(res)
    case <-time.After(3 * time.Second):
        fmt.Println("timeout 2")
    }
}

執行此程式會產生第一次操作逾時而第二次操作成功的情形。

$ go run timeouts.go 
timeout 1
result 2

下一個範例:非封鎖通道操作