有没有办法在无限时间内询问time.After()?

有没有办法要求time.After()无限量的时间?

动机:我有一个服务,调用者可以从它请求消息,并有一个可选的超时。这样做的明显方法是:

func service(timeout *time.Duration) SomeType {
    var timeout_value time.Duration
    if timeout != nil {
        timeout_value = *timeout
    } else {
        timeout_value = time.Forever /* or something */
    }

    select {
    case value <- some_channel:
        return value
    case <- time.After(timeout_value):
        return nil
    }
}

除了我不知道有没有办法说time.Forever

回答

没有“永远”持续时间,但有最大持续时间:

const maxDuration time.Duration = 1<<63 - 1

maxDuration大约是 292 年。它应该足以满足单个应用程序的生命周期。但相反,我提出了以下不使用它的解决方案:

请注意,如果“永远”是预期的最大等待时间,则省略time.After()和使用简单的接收会更简单、更有效:

func service(timeout *time.Duration) SomeType {
    if timeout == nil {
        return <-some_channel
    }

    select {
    case value := <-some_channel:
        return value
    case <-time.After(*timeout):
        return nil
    }
}

您表示您的实际代码要复杂得多并且包含更多案例。

在这种情况下,我会将超时通道创建移到select语句之外,并相应地进行初始化。当timeoutis 时nil,只离开通道nil(它的零值),它永远不会提供任何值,因此从nil通道接收实际上需要“永远”:

func service(timeout *time.Duration) SomeType {
    var timeoutCh <-chan time.Time
    if timeout != nil {
        timeoutCh = time.After(*timeout)
    }

    select {
    case value := <-some_channel:
        return value
    case <-timeoutCh:
        return nil
    }
}

  • @Flimzy 是的,我担心,即使我提出的解决方案甚至不使用`maxDuration`,我相信他会回到这里并拒绝这个答案:)
  • 我预测在 2313 年,当某些应用程序的唯一显示单元停止工作时,某些博物馆馆长会诅咒您。
  • @Tom 好吧,请参阅我编辑过的答案。简而言之:只需将超时通道创建移到`select`之外,如果你想永远等待,让它保持`nil`。从“nil”频道接收永远阻塞。

回答

您可以context.Context在函数中接受 a 而不是持续时间,我认为这在 Go 代码中非常惯用。

然后调用者可以根据需要使用 aContext.Background或 a调用该函数Context.WithTimeout。该service函数选择上下文的Done(),在背景上下文的情况下永远不会结束(chan 实际上为零)。

如果此上下文永远无法取消,则 Done 可能返回 nil。[...] Done 用于选择语句

func callerNoTimeout() {
    foo := service(context.Background())
}

func callerTimeout() {
    foo := service(context.WithTimeout(context.Background(), timeOut))
}

func service(ctx context.Context) SomeType {
    select {
        case value <-some_channel:
            return value
        case <-ctx.Done():
            return nil
    }
}


以上是有没有办法在无限时间内询问time.After()?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>