iris框架不内置定时任务功能,必须用robfig/cron/v3手动集成;需在main中独立启动cron实例,不可在mvc控制器或http handler中启停,任务函数若需访问db等依赖须提前注入全局变量或闭包。

iris MVC 里不能用 @Scheduled 或内置 cron
Iris 框架本身不提供定时任务能力,@Scheduled 是 Spring 的注解,Go 里根本不存在;iris/cron 包也不存在——任何尝试 import "github.com/kataras/iris/v12/cron" 都会报错 cannot find package。MVC 只是控制器组织方式,和调度无关。定时任务必须脱离 MVC 生命周期独立启动。
必须用 robfig/cron/v3 手动集成
最稳定、社区维护活跃的选择是 github.com/robfig/cron/v3。它不依赖 Web 框架,只管按 cron 表达式触发函数。关键点在于:任务函数若要访问 MVC 中的 service 或 db 实例,不能靠注入或 iris.Context,得提前把依赖存为全局变量或闭包捕获。
- 在
main.go初始化时创建cron.New()实例,调用c.Start() - 添加任务用
c.AddFunc("0 0 * * *", func() { ... }),表达式格式和 Linux cron 一致 - 不要在 controller 方法里调用
c.Start()或c.Stop(),否则可能被 GC 掉或并发冲突 - 若任务需 DB 连接,应在
main中初始化好*sql.DB,再传入闭包:c.AddFunc("0 */2 * * *", func() { doCleanup(db) })
MVC Controller 里调用定时任务?别这么干
有人想在某个 controller 的 Post() 里动态启停任务,这是危险操作。robfig/cron 不支持运行时增删 job(v3 版本无安全的 RemoveFunc),强行调用会导致 panic 或 goroutine 泄漏。所有调度逻辑必须在应用启动初期就注册完毕,且生命周期与主程序一致。
- 错误做法:
func (c *AdminController) StartJob() { cronInst.AddFunc(...) } - 正确做法:把开关逻辑做成配置项,在
main()启动前读取环境变量或 config,决定是否注册某任务 - 如果真需要“手动触发”,应暴露一个 HTTP 接口,内部调用普通函数(非 cron job),避免混用调度模型
注意 cron 表达式时区和 goroutine 安全
robfig/cron/v3 默认使用本地时区,但服务器部署常为 UTC。若你写 "0 0 1 * *" 期望每月 1 号 0 点执行,而服务器时区是 UTC+8,实际会在 UTC 时间 16:00 触发(即北京时间次日 0 点)。更隐蔽的问题是:任务函数若修改共享变量(如全局计数器),必须加锁,因为 cron 在独立 goroutine 中执行。
- 显式指定时区:
c := cron.New(cron.WithLocation(time.UTC)) - 避免在任务中直接操作未加锁的 map/slice/struct 字段
- 日志建议打上时间戳并标注 goroutine ID,方便排查并发问题
实际调度逻辑永远游离在 MVC 结构之外,它不关心路由、不依赖上下文、也不走任何中间件。写错位置,轻则任务不执行,重则整个服务假死。











