Go语言定时器Timer与Ticker详解及Cron定时任务

Hazel
Hazel
发布时间:2026-10-16 | 6人浏览过
原创

掌握 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语言定时器的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表