Go语言定时器Timer与Ticker详解及Cron定时任务
掌握 Go 语言中的定时器是实现后台任务调度、心跳检测及延迟操作的核心技能。本文深入解析内置的 time.Timer 和 time.Ticker 用法,包括单次触发、周期性循环、安全停止与重置,并介绍利用 robfig/cron 库处理标准 Cron 表达式的方案。
1. 精确时间调度:Cron 表达式
如果需要按照“每5秒”、“每周一9点”等特定日历规则触发任务,推荐使用 github.com/robfig/cron 库。它支持标准的 Cron 格式。
第1步:安装依赖
终端运行:
go get github.com/robfig/cron
第2步:实现每5秒执行的定时任务
通过构建 Cron 实例并添加函数来实现。注意使用 defer cron2.Stop() 防止程序退出时协程泄露。
package main
import (
"fmt"
"github.com/robfig/cron"
)
func print5() {
fmt.Println("每5s执行一次cron")
}
func main() {
cron2 := cron.New()
// */5 * * * * * 表示每秒的字段为每隔5秒匹配一次
err := cron2.AddFunc("*/5 * * * * *", print5)
if err != nil {
fmt.Println(err)
}
cron2.Start()
defer cron2.Stop()
// 阻塞主进程
select {}
}Cron 语法速查
Cron 表达式由6个空格分隔的字段组成(部分库支持5字段,省略秒),从左至右依次为:
┌───────────── second (0 - 59)
│ ┌───────────── min (0 - 59)
││ ┌────────────── hour (0 - 23)
│││ ┌─────────────── day of month (1 - 31)
││││ ┌──────────────── month (1 - 12)
│││││ ┌───────────────── day of week (0 - 6 or 1 - 7)
- 星号 (*):表示任意值(例如每月)。
- 斜线 (/):步长。如
3/15表示从第3分钟开始,每15分钟执行一次(3, 18, 33...)。 - 连字号 (-):范围。如
9-17表示9点到17点。 - 逗号 (,):列举。如
MON,WED,FRI表示周一、周三、周五。
2. Go 原生定时器:Timer vs Ticker
Go 的 time 包提供了两个核心定时器类型:
• time.Timer:只发送一次信号,适用于延时或单次超时控制。
• time.Ticker:按固定间隔重复发送信号,适用于轮询或周期处理。
第1步:Timer 的单次与延时功能
time.NewTimer(d) 会在 duration d 后向 timer.C 信道发送一个 time.Time。这常用于替代 time.Sleep 以实现可取消的延时。
基础延时示例:
当前时间: 2023-10-01 10:00:00 t = 2023-10-01 10:00:02
func main() {
// 创建2秒后触发的定时器
timer := time.NewTimer(2 * time.Second)
fmt.Println("当前时间:", time.Now())
t := <-timer.C // 阻塞直到通道有数据
fmt.Println("t = ", t)
}第2步:Ticker 的循环执行
Ticker 需要手动停止以防止内存泄漏。通常配合 sync 包或在逻辑判断后进行 Stop()。
func main() {
ticker := time.NewTicker(1 * time.Second)
i := 0
for {
<-ticker.C
i++
fmt.Println("执行次数:", i)
// 达到条件后务必停止
if i == 5 {
ticker.Stop()
break
}
}
}第3步:Stop 和 Reset 的安全使用
重要风险提示:如果在定时器尚未触发前调用 Reset,原定时器会被覆盖,但需留意若旧定时器已触发,其信道上可能仍有残留数据。最安全的做法是先 Stop 再 Reset,或直接 Reset。
重置测试:
func main() {
timer := time.NewTimer(3 * time.Second)
// 在触发前重置为1秒
ok := timer.Reset(1 * time.Second)
fmt.Println("是否被成功重置且未漏发事件:", ok) // 通常返回 true
<-timer.C
fmt.Println("1秒后触发")
}并发环境下的停止:
func main() {
timer := time.NewTimer(3 * time.Second)
// 开启协程等待
go func() {
<-timer.C
fmt.Println("定时器已到")
}()
// 立即取消
timer.Stop()
fmt.Println("定时器已取消")
}总结
在 Go 开发中,time.After 用于简单的一次性延时;Timer 提供了更精细的控制(Stop/Reset)以支持动态调整;而 Ticker 则是处理循环任务的标配,使用时必须记得在业务完成后调用 Stop 方法释放资源。对于复杂的周期性业务逻辑,接入 cron 库是更优雅的选择。
以上就是Go语言定时器Timer及Ticker的功能使用示例详解的详细内容,更多关于Go语言定时器的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









