为什么我要在 golang 中使用 `case <-time.After(time.Second * 1):` 而不是 `time.Sleep(time.Second * 1)`

Why would I use `case <-time.After(time.Second * 1):` over `time.Sleep(time.Second * 1)` in golang

查看一些代码我发现了两种每秒做某事的方法:

for {
    fmt.Println("This is printed every second")
    time.Sleep(time.Second * 1)
}

for {
    select {
    case <-time.After(time.Second * 1):
        fmt.Println("This is printed every second")
    }
}

除了第一个更具可读性(在我看来)之外,我真的不明白一个比另一个有什么优势。有人知道吗?

您可能出于(至少)两个原因想要这样做:

  1. time.Sleep 总是阻塞你当前的 goroutine,而如果你包含一个 default 情况,等待通道可能不会:
    timeoutCh := time.After(time.Second)
LOOP:
    for {
        select {
        case <-timeoutCh:
            break LOOP
        default:
        }
        // do some work
    }
  1. 您可以使用它为长运行 操作添加超时。
    假设您的 long-运行 op 将在频道上通知您。在那种情况下,该操作的超时将像这样实现:
    opNotifyCh := op()
    select {
    case res := <-opNotifyCh:
        fmt.Println("Op finished with result:", res)
    case <-time.After(time.Second):
        fmt.Println("Op timed out")
    }
  1. time.After 给你一个频道。你可以用它做任何你想做的事——你可以把它传递给一个函数,你可以 return 它给调用者,你可以把它放在一个结构中——任何东西,真的。这给了你很大的自由度。