Golang计时器,长度为0

Qub*_*ert 2 timer go

我写了一个代码剪切,创建一个长度为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
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

打印

false
true
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

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

NewTimer创建一个新的Timer,它将在至少持续时间d之后在其通道上发送当前时间.

因此,通过零持续时间time.NewTimer(),返回time.Timer的并不是立即"过期" 并不奇怪.

如果实现将检查传递的持续时间是否为零,则返回的计时器可以立即"过期",并且在返回之前将在计时器的通道上发送一个值,但事实并非如此.相反,它正常地启动一个内部计时器,就像它在任何给定的持续时间一样,它将负责在其通道上发送一个值,但仅在将来的某个时间.

请注意,对于多个CPU核心并且runtime.GOMAXPROCS()大于1,time在NewTimer()返回之前,另一个goroutine(包内部)在计时器的通道上发送一个值的可能性很小,但这是一个非常小的机会......也是因为这是实现细节,未来版本可能会添加此"优化"来检查0传递的持续时间,并按预期行事,但与所有实现细节一样,不要指望它.依靠记录的内容,不再期待.