Go使用time.Stop()不当导致的问题
Go使用time.Stop()不当导致的问题
ivansli问题
先看一段代码
1 | func main() { |
聪明的你觉得执行结果会是什么?
A. 正常结束
B. 永远无法结束
代码分析
一般来说,拿出来特别说明的例子基本都会存在一些问题。上面代码的结果是B(如果选择A的话,就要好好思考一下了)
这里重点说明两处代码
1 | // 创建timer对象,并插入时间堆中,如果时间达到触发时刻,会向timer.C中发送数据 |
上面的代码中,调用timer.Stop()
时,还未到达触发事件,所以会返回true。那么问题来了,从时间堆中移除该timer对象的话,timer.C是怎么处理的,会关闭吗?
结论是:不会关闭。
造成的问题:那么goroutine中<-timer.C
就会永久阻塞,则main函数也会因此永久阻塞。
正确的写法
针对上面有问题的代码,正确的写法是:
1 | func main() { |
timer.Stop()
改为 timer.Reset(0 * time.Second)
意味着重置timer,由于设置的超时时间为 0,则立即触发,会向timer.C发送数据。这个时候,goroutine中<-timer.C
立刻能够获得数据。
结论
这里我们要思考以下几点:
- 牵扯channel使用时,要先思考怎样才能不会阻塞在channel上
- 使用goroutine时,要先思考怎样才能正常退出
- 使用包时,需要大概了解一下内部原理
golang中泄露问题,大部分无外乎上面几种情况。只有掌握了原理,才能减少bug,事半功倍。