Go 定时器的使用
源代码/数据集已上传到 Github - posts
在执行定时任务的场景,每隔几秒钟就会执行一次,触发任务。
go提供了time包,用来实现延时,只需要循环执行延时,就可以实现定时器功能。
但是关于它的使用和实现,需要具体分析一下。
实现原理
go的time包里面提供了两个函数用于延时,分别是func After(d Duration) <-chan Time
和func Tick(d Duration) <-chan Time
。而他们分别调用func NewTimer(d Duration) *Timer
和func NewTicker(d Duration) *Ticker
来实现这个延时的。两个函数的实现差异只在变量t
的赋值上,NewTimer
使用Timer
实现,NewTicker
使用Ticker
实现。两个结构体的数据结构完全一样,因此他们实际实现的效果也是完全一致的。
NewTicker
的实现如下
1 | func NewTicker(d Duration) *Ticker { |
Ticker实现
1 | // A Ticker holds a channel that delivers `ticks' of a clock |
Ticker实现只有两个参数:
C: 管道,上层应用根据此管道接收事件;
r: runtime定时器,该定时器即系统管理的定时器,对上层应用不可见;
这里应该按照层次来理解Timer数据结构,Timer.C即面向Timer用户的,Timer.r是面向底层的定时器实现。
Ticker.C
管道每隔一个延时周期就会接收到一个事件,用于延时任务的触发。
实现一个延时
1 | func main() { |
实现一个定时器
1 | func main() { |
错误示例
1 | func main() { |
把time.After
内的方法实现一遍,输出每次的定时器的内存地址
1 | func main() { |
可以看到,每一次调用方法都会生成一个定时器,不断开辟内存空间。
正确示例
1 | func main() { |
结尾
重启可以解决99.9%的问题?!
微信扫一扫,阅读/分享
edit this page last updated at 2024-04-22