
Go 程序中使用 robfig/cron 启动定时任务后立即退出,是因为主 goroutine 结束导致进程终止;只需在 c.Start() 后阻塞主线程(如使用 select {}),即可让 cron 持续运行。
go 程序中使用 robfig/cron 启动定时任务后立即退出,是因为主 goroutine 结束导致进程终止;只需在 `c.start()` 后阻塞主线程(如使用 `select {}`),即可让 cron 持续运行。
在 Go 中使用 github.com/robfig/cron(v2/v3)实现定时任务时,一个常见误区是:调用 c.Start() 仅启动了后台调度器(运行在独立 goroutine 中),但 main() 函数本身会继续执行并快速结束——一旦 main goroutine 退出,整个程序即终止,所有其他 goroutine(包括 cron 的调度协程)也会被强制关闭。
你原始代码的问题正在于此:
func main() {
c := cron.New()
c.AddFunc("@every 3m", func() { fmt.Println("Every 3 min") })
c.Start()
fmt.Println("Done") // ← 打印后 main 立即返回,程序退出
}✅ 正确做法是阻止 main 函数退出,最简洁、惯用的方式是添加一个永久阻塞的 select {} 语句:
package main
import (
"fmt"
"github.com/robfig/cron/v3" // 注意:推荐使用 v3(模块化、更稳定)
)
func main() {
c := cron.New()
c.AddFunc("@every 3m", func() {
fmt.Println("Every 3 min —", time.Now().Format("15:04:05"))
})
c.Start()
fmt.Println("Cron scheduler started. Press Ctrl+C to exit.")
// 阻塞主 goroutine,保持程序运行
select {}
}⚠️ 注意事项:
-
务必使用
cron/v3:github.com/robfig/cron的 v2 及更早版本已归档,v3 是当前维护分支(需go get github.com/robfig/cron/v3),API 更清晰且修复了多个竞态问题; -
select {}是 Go 中最轻量的无限阻塞方式,它不消耗 CPU,也不会退出; - 若需支持优雅退出(如响应
SIGINT),可结合signal.Notify实现:
import "os/signal"
// ... 启动 cron 后
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
<-sigChan
fmt.Println("\nShutting down...")
c.Stop()总结:CRON 在 Go 中不是“自动驻留”的服务,而是依赖主程序生命周期的库。理解 goroutine 生命周期与程序退出机制,是写出健壮定时任务的基础。

















