time 包提供了两个有用的工具:Timer 和 Ticker。
关键区别:
Timer 在触发后会“熄灭”,需要重置 (Reset) 才能再次使用。Ticker 会生成事件,直到显式调用 Stop() 方法停止它。使用特点:
Stop() 以避免资源泄露。Stop() 后,可能需要“清空”通道:如果在 Stop() 之前计时器已经触发,则必须从通道中读取。正确使用 Timer 的示例:
t := time.NewTimer(2 * time.Second) defer t.Stop() // 一定要调用! select { case <-t.C: fmt.Println("时间到!") case <-otherDone: if !t.Stop() { <-t.C // 如果需要,清空通道 } }
在从通道 t.C 获取值后,是否可以立即重新使用 Timer?如果不调用 t.Stop() 会发生什么?
答案: 计时器不应在不调用 Stop() 和可能不读取通道的情况下立刻重置。如果不调用 t.Stop(),可能会留下“死”协程或在下一个循环中出现意外触发(通道未被清空)。正确的做法是调用 Stop(),如果 Stop() 返回 false — 确保通过从 t.C 读取来清空通道。
故事
故事
Ticker 在处理程序完成时未停止。即使在删除用户后,处理程序“挂起”,仍然消耗 CPU。故事
在测试中未调用计时器的 Stop() — 测试随机挂起,因为计时器的通道未被释放,等待计时器的第二个“ping”,而这个“ping”永远不会到来。