这个问题有点坑,读到最后才会知道!

time.After 每次调用都会返回一个新的 channel,把你的 for + select 简单拆解下,加个临时变量或许比较好理解,比如变成下面这样。

timerC 每次都是重新创建的,什么意思呢?简单说来,当 select 成功监听 ch 并进入它的处理分支,下次循环 timerC 会重新创建。timerC 重新创建了,时间肯定就重置了。

是不是觉得这种方式挺适合超时处理,timerC 只对一个 select 有效,下次处理时重新计算超时时间,每个操作的处理都是独立的。

补充:

感谢评论区的 root 提醒,如果按上面这种方式处理超时可能会出现内存泄露。root 提到了这篇文章,如下:

也就是说如果定时器没有到达定时时间,gc 就不会启动垃圾回收。标准库文档中有说明:

The underlying Timer is not recovered by the garbage collector until the timer fires

文中提到了可以通过创建 timer 配合 reset 实现超时,可解决这个问题。如下:

真是防不胜防!


欢迎关注我的专栏,Golang 之旅。见证我的 Golang 学习历程。