我写了一个代码剪切,创建一个长度为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)
time.NewTimer()不保证最长等待时间.它只保证最短的等待时间.引用其文档:
NewTimer创建一个新的Timer,它将在至少持续时间d之后在其通道上发送当前时间.
因此,通过零持续时间time.NewTimer(),返回time.Timer的并不是立即"过期" 并不奇怪.
如果实现将检查传递的持续时间是否为零,则返回的计时器可以立即"过期",并且在返回之前将在计时器的通道上发送一个值,但事实并非如此.相反,它正常地启动一个内部计时器,就像它在任何给定的持续时间一样,它将负责在其通道上发送一个值,但仅在将来的某个时间.
请注意,对于多个CPU核心并且runtime.GOMAXPROCS()大于1,time在NewTimer()返回之前,另一个goroutine(包内部)在计时器的通道上发送一个值的可能性很小,但这是一个非常小的机会......也是因为这是实现细节,未来版本可能会添加此"优化"来检查0传递的持续时间,并按预期行事,但与所有实现细节一样,不要指望它.依靠记录的内容,不再期待.