Go 示例: 超时

超时对于连接外部资源或需要限制执行时间的程序来说非常重要。得益于通道和select,在 Go 中实现超时既简单又优雅。

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

例如,假设我们正在执行一个外部调用,该调用在 2 秒后在通道 c1 上返回其结果。请注意,该通道是缓冲的,因此协程中的发送是非阻塞的。这是一种常见的模式,可以防止在通道从未被读取的情况下发生协程泄漏。

    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

下一个示例:非阻塞通道操作.