我编写了一段代码,创建了一个长度为0的计时器,并且它不会立即过期(这是我所期望的)。短暂的睡眠通话确实会使它过期,但是我对原因感到困惑。

我关心的原因是,使用此思想的代码包含一个代码段,该代码段在发生低概率错误时返回0,并认为应将计时器设置为立即过期,然后重试函数。我不认为这里需要的纳秒级睡眠会影响我的实现,但会困扰我。

我做错了吗,这是预期的行为吗?

谢谢!

 package main

    import (
        "fmt"
        "time"
    )

    func main() {
        testTimer := time.NewTimer(time.Duration(0) * time.Millisecond)
        fmt.Println(Expired(testTimer))
        time.Sleep(time.Nanosecond)
        fmt.Println(Expired(testTimer))
    }

    func Expired(T *time.Timer) bool {
        select {
        case <-T.C:
            return true
        default:
            return false
        }
    }

游乐场链接:https://play.golang.org/p/xLLHoR8aKq

打印
false
true

最佳答案

time.NewTimer() 不保证最长等待时间。它仅保证最短的等待时间。引用其文档:



因此,将零持续时间传递给time.NewTimer(),返回的 time.Timer 不会立即“过期”也就不足为奇了。

如果实现将检查传递的持续时间是否为零,并且在返回之前在计时器的 channel 上发送值,则返回的计时器可能立即“过期”。相反,它会像在任何给定持续时间内一样正常地启动内部计时器,该计时器将负责在其 channel 上发送值,但仅在将来的某个时间发送。

请注意,在有多个CPU内核且 runtime.GOMAXPROCS() 大于1的情况下,在time返回之前,另一个goroutine(在NewTimer()包内部)在计时器 channel 上发送值的可能性很小,但这是很小的机会...另外由于这是实现细节,因此将来的版本可能会添加此“优化”以检查传递的持续时间是否为0,并按您期望的方式运行,但是与所有实现细节一样,不要指望它。依靠记录在案的内容,别再期待了。

关于go - 长度为0的Golang计时器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43616295/

10-15 21:58