本文详解如何在 go 程序中正确使用 robfig/cron 库实现定时任务,解决因主 goroutine 过早退出导致任务不执行的问题,并提供带信号监听的健壮启动模式。
在 Go 中使用 github.com/robfig/cron(v2 及以下版本)实现定时任务时,一个常见误区是:程序启动 cron 后立即退出,导致后台任务无机会执行。这是因为 cron.Start() 启动的是一个后台 goroutine,而 main() 函数若执行完毕,整个进程就会终止——无论 cron 是否已注册任务。
原始代码存在两个关键问题:
推荐使用 os/signal 监听系统中断信号(如 Ctrl+C),让主 goroutine 阻塞等待,同时允许用户主动终止服务:
package main
import (
"fmt"
"os"
"os/signal"
"time"
"github.com/robfig/cron"
)
func main() {
c := cron.New()
// ✅ 正确的每秒执行表达式(6 字段 cron,支持秒)
c.AddFunc("* * * * * *", RunEverySecond)
// ✅ 在 goroutine 中启动 cron(非阻塞)
go c.Start()
// ✅ 主 goroutine 等待中断信号(如 Ctrl+C)
sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, os.Kill)
fmt.Println("Cron started. Press Ctrl+C to exit.")
<-sig // 阻塞至此,直到收到信号
fmt.Println("Shutting down...")
c.Stop() // 
✅ 建议显式调用 Stop() 释放资源(v2+ 支持)
}
func RunEverySecond() {
fmt.Printf("[%s] Task executed\n", time.Now().Format("15:04:05"))
}通过以上结构,你的 Go 定时任务将稳定运行、可观测、可中断,真正满足长期守护型作业需求。