1 回答
TA贡献1818条经验 获得超8个赞
该软件包benbjohnson/clock提供模拟时间设施。他们的文档特别指出:
计时器和 Tickers 也由同一个模拟时钟控制。它们只会在时钟向前移动时执行
所以当你调用时mockClock.Add,它会依次执行定时器/代码。该库还添加了连续的 1 毫秒睡眠,以人为地屈服于其他 goroutines。
当计时器/自动收报机在 goroutine 外部声明时,即在调用之前mockClock.Add,到mockClock.Add被调用时,模拟时间确实有一些东西要执行。库的内部睡眠足以让子 goroutine 在程序退出之前在自动收报机上接收并打印“完成”。
当 ticker 在 goroutine 中声明时,到 timemockClock.Add被调用时,模拟时间没有要执行的 ticker,Add基本上什么都不做。内部睡眠确实给了子 goroutine 运行的机会,但是接收到 ticker 现在只会阻塞;main 然后恢复并退出。
您还可以查看存储库自述文件中的代码示例:
mock := clock.NewMock()
count := 0
// Kick off a timer to increment every 1 mock second.
go func() {
ticker := mock.Ticker(1 * time.Second)
for {
<-ticker.C
count++
}
}()
runtime.Gosched()
// Move the clock forward 10 seconds.
mock.Add(10 * time.Second)
// This prints 10.
fmt.Println(count)
这用于在调用之前runtime.Gosched()
屈服于子 goroutine 。这个程序的顺序基本上是:mock.Add
clock.NewMock()
count := 0
生成子 goroutine
runtime.Gosched()
, 让步给子 goroutineticker := mock.Ticker(1 * time.Second)
阻塞
<-ticker.C
(模拟时钟还没有向前移动)恢复主要
mock.Add
, 它将时钟向前移动并再次让步给子 goroutinefor
循环<-ticker.C
打印 10
出口
按照相同的逻辑,如果您将 a 添加runtime.Gosched()
到第二个代码段,它将按预期工作,就像存储库的示例一样。游乐场:https ://go.dev/play/p/ZitEdtx9GdL
但是,不要依赖runtime.Gosched()
生产代码,甚至可能不要依赖测试代码,除非您非常确定自己在做什么。
最后,请记住time.Sleep(1)
休眠一纳秒。
- 1 回答
- 0 关注
- 125 浏览
添加回答
举报