We should not judge people by their peak of excellence; but by the distance they have traveled from the point where they started.
— Henry Ward Beecher
Go 1.23 includes a new implementation of the channel-based timers created by time.NewTimer, time.After, time.NewTicker, and time.Tick.
Timers 的关键改动
增强的垃圾回收
- 在以前的 Go 版本(1.23 之前)中,如果程序没有使用 Stop 方法显式停止,未停止的 time.Timers 和 time.Tickers 仍保留在内存中。这可能会导致资源泄漏,尤其是在长时间运行的程序中。
- Go 1.23 通过使未引用的 time.Timers 和 time.Tickers 有资格立即进行垃圾回收来解决这个问题。这确保了高效的内存管理,并防止不必要的资源使用。
通过 defer 等方法调用 Stop 显示释放资源显然是一个好习惯,但是在 1.23 之前,如果不小心忘了释放资源,或许会造成不可挽回的后果。
Go 对于这种粗心的行为做了进一步的防护,增强了代码的健壮性(robustness),显然是一个值得称赞的决定。如果你调用1.23中的 NewTicker
方法,将会看到其中的注释:
1 | // Before Go 1.23, the garbage collector did not recover |
src/time/tick.go - go - Git at Google
channel 的同步性
- 在 Go 1.23 之前,用于 time.Timer 和 time.Ticker 的计时器通道的缓冲区容量为 1。这可能会在使用 Reset 或 Stop 方法时带来挑战,因为调用后可能会传递过时的值。
- Go 1.23 引入了同步定时器通道(无缓冲,容量为 0)。这有效地防止了对 Reset 或 Stop 的调用后在通道上进一步发送或接收任何的信号。这简化了有关计时器行为的推理,并消除了陈旧值的潜在问题。
举个例子:
1 | package main |
对现有代码的影响
兼容性
- 仅当程序的 go.mod 文件指定 Go 1.23.0 或更高版本时,才会启用新的计时器行为。如果您使用 Go 1.23 构建较旧的代码,则以前的计时器行为仍然适用。
- 要恢复到异步通道行为(即使使用 Go 1.23 或更高版本),您可以使用 GODEBUG 设置:GODEBUG=asynctimerchan=1。
通道长度
如果您的代码依赖于检查通道长度(使用 len)来确定接收操作是否成功,则需要将其修改为使用非阻塞接收。由于通道现在是无缓冲的,len 和 cap 将始终返回 0。
举个例子,在go 1.23 你需要将以下逻辑
1 | func main() { |
改为:
1 | func main() { |
调度时延
在 Go1.23 之前,一个 timer 创建时是有调度时延的,而最新的计时器实现不再受调度时延的影响,所以该更改对已有代码也可能有影响。
举个例子:
1 | package main |
总结
- 改进了未引用 the channel-based timers 的垃圾收集。
- 异步定时器通道改为同步定时器通道。
- 消除了创建 the channel-based timers 的调度时延
总之,这些更改会改进 Go 1.23 中的计时器行为,促进更好的资源管理以及更清晰的 Reset 和 Stop 语义。
但也会带来潜在隐患,如果您遇到旧代码的兼容性问题,请考虑使用 GODEBUG 设置或更新代码以适当处理无缓冲(阻塞)通道等场景。
参考
Go Wiki: Go 1.23 Timer Channel Changes - The Go Programming Language
更多该系列文章,参考medium链接:
https://wesley-wei.medium.com/list/you-should-know-in-golang-e9491363cd9a
English post: https://programmerscareer.com/golang-timer-changes/
作者:Wesley Wei – Twitter Wesley Wei – Medium
注意:原文在 2024-07-06 23:39 时创作于 https://programmerscareer.com/golang-timer-changes/. 本文为作者原创,转载请注明出处。
评论