robfig/cron/v3是go生态最稳的cron框架,适合日志轮转等清理任务;任务不执行主因是未调start()、表达式错误或时区加载失败;秒级需withseconds()且用6字段格式;addfunc适用于无状态轻量任务,addjob适用于需状态管理的场景。

robfig/cron/v3 是目前 Go 生态里最稳的 cron 框架,能直接用字符串表达式调度,适合清理类作业(如日志轮转、过期会话剔除、缓存刷新)。别用 v1 或 v2,它们不支持 @daily 这类语义别名,也缺上下文取消能力;更别碰 antonmedv/cron,它根本不解析表达式字符串。
为什么 cron.Start() 后任务没跑?先查这三处
90% 的“定时任务没执行”问题卡在这三个地方:
-
cron实例创建后没调c.Start()—— 它只是个调度器,不 start 就是空转 - 表达式写错,比如想写“每两小时一次”,误写成
0 0/2 * * *(非法),正确应为0 */2 * * * - 时区加载失败:Docker 容器里
/etc/localtime缺失或损坏,time.Local返回 nil,导致 panic “invalid time zone”
验证方式:调用 c.Entries(),返回空列表说明表达式根本没被解析成功。
秒级精度必须显式启用 cron.WithSeconds()
默认 cron.New() 只认 5 字段表达式(分时日月周),"* * * * *" 是每分钟一次;要每秒执行,得:
- 初始化时传
cron.WithSeconds() - 用 6 字段格式,例如
"* * * * * *"(秒 分 时 日 月 周) - 别写成
"1 * * * * *"以为是“每秒”,其实是“每分钟第 1 秒”
常见清理场景(如每 30 秒扫一次过期 session)就靠这个组合。
AddFunc 和 AddJob 怎么选?
AddFunc 适合无状态、轻量、不需错误恢复的清理动作,比如:
c.AddFunc("@hourly", func() { cleanOldLogs() })c.AddFunc("0 2 * * *", func() { pruneExpiredSessions() })
AddJob 必须实现 cron.Job 接口,适合带状态、需重试、要资源复用的清理逻辑,比如:
- 连接池健康检查(需复用 DB 连接)
- 批量删除(需事务控制 + 失败回退)
- 上报清理结果(需记录 lastRunTime、errorCount 等字段)
注意:AddFunc 里闭包捕获循环变量会全部指向最后一个值,AddJob 的 Run() 方法不能带参数,传参得靠结构体字段赋值。
清理任务最容易被忽略的坑:panic 和 data race
清理作业常涉及文件删、DB 查删、map 遍历,稍不注意就 panic 或并发冲突:
- 单个 job panic 默认会让整个
cron实例停摆 —— 必须加cron.WithChain(cron.Recover(cron.DefaultLogger)) - 多个清理 job 并发读写同一 map 或 struct 字段,极易触发 data race —— 用
go run -race测,线上别靠猜 - 耗时清理(如删百万行日志)会阻塞后续调度 —— 加
cron.DelayIfStillRunning(cron.DefaultDelay)防堆积
真正上线前,务必在容器环境里跑一次完整生命周期:启动 → 等至少两个周期 → 手动 kill → 观察是否残留 goroutine 或文件句柄未关。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











