cron 表达式的基本格式
对于cron我们比较熟知的应该是linux的crontab,但是正常来说linux中的cron 只能支持分钟级别的定时任务。而在实际运用中,我们经常需要使用到秒级别的任务,比如监控什么的。除了支持的粒度,cron 的表达式跟linux的cron基本语法是类似的。下面会介绍go 中常用到的两个cron 包的使用。

Golang 定时任务 github/robfig/cron/v3 的介绍与使用
demo实例
引用项目需要的依赖增加到go.mod文件
go mod init go_cron代码
package mainimport ("fmt""time""github.com/robfig/cron/v3")func main() {//New(): 实例化一个 cron 对象job := cron.New(cron.WithSeconds(), // 添加秒级别支持,默认支持最小粒度为分钟)i, j := 1, 1//Cron.AddFunc()向 Cron 对象中添加一个作业,接受两个参数,第一个是 cron 表达式,第二个是一个无参无返回值的函数(作业)// 每秒钟执行一次job.AddFunc("* * * * * *", func() {fmt.Printf("secondly: %v,times: %d\n", time.Now(), i)i++})//每分钟执行一次job.AddFunc("0 * * * * *", func() {fmt.Printf("minutely: %v,times: %d\n", time.Now(), j)j++})job.Run() // 启动if i >= 35 {//Cron.Stop(): 停止调度,Stop 之后不会再有未执行的作业被唤醒,但已经开始执行的作业不会受影响job.Stop()}}
ron 默认支持到分钟级别,如果需要支持到秒级别,在初始化 cron 时,记得
cron.WithSeconds()参数。
自动的包管理,有引用到的会自动下载,没有的会自动清理
go mod tidy 每小时执行一次
// 每小时执行一次job.AddFunc("0 0 * * * *", func() {fmt.Printf("hourly: %v\n", time.Now())})// 另一种写法job.AddFunc("@hourly", func() {fmt.Printf("hourly: %v\n", time.Now())})
cron 提供的解析器,可以识别 @hourly 这种写法,类似的还有 daily,weekly,monthly,yearly,annually。
固定时间间隔执行一次
cron 表达式无法直接实现,可以使用另外的方案
@every 写法
package mainimport ("fmt""time""github.com/robfig/cron/v3")func main() {//New(): 实例化一个 cron 对象job := cron.New(cron.WithSeconds(), // 添加秒级别支持,默认支持最小粒度为分钟)i, j := 1, 1//Cron.AddFunc()向 Cron 对象中添加一个作业,接受两个参数,第一个是 cron 表达式,第二个是一个无参无返回值的函数(作业)// 每秒钟执行一次job.AddFunc("* * * * * *", func() {fmt.Printf("secondly: %v,times: %d\n", time.Now(), i)i++})job.AddFunc("@every 5s", func() {fmt.Printf("every: %v,times: %d\n", time.Now(), j)j++})job.Run() // 启动// if i >= 35 {// //Cron.Stop(): 停止调度,Stop 之后不会再有未执行的作业被唤醒,但已经开始执行的作业不会受影响// job.Stop()// }}
@every 也是解析器提供的功能,60s 这个写法,其实就是一个时间区间,类似的还有 1h,1h30m 等,具体的格式可以通过 time.ParseDuration 获取。
执行效果
secondly: 2022-10-25 13:31:48.002104 +0800 CST m=+0.331528064,times: 1secondly: 2022-10-25 13:31:49.000388 +0800 CST m=+1.329810626,times: 2secondly: 2022-10-25 13:31:50.003159 +0800 CST m=+2.332579760,times: 3secondly: 2022-10-25 13:31:51.003097 +0800 CST m=+3.332515820,times: 4secondly: 2022-10-25 13:31:52.00265 +0800 CST m=+4.332067570,times: 5every: 2022-10-25 13:31:52.002645 +0800 CST m=+4.332062298,times: 1secondly: 2022-10-25 13:31:53.003482 +0800 CST m=+5.332897647,times: 6secondly: 2022-10-25 13:31:54.001821 +0800 CST m=+6.331234706,times: 7secondly: 2022-10-25 13:31:55.002277 +0800 CST m=+7.331689662,times: 8secondly: 2022-10-25 13:31:56.004013 +0800 CST m=+8.333424027,times: 9every: 2022-10-25 13:31:57.001743 +0800 CST m=+9.331152834,times: 2secondly: 2022-10-25 13:31:57.001756 +0800 CST m=+9.331165066,times: 10
github.com/jasonlvhit/gocron
goCron是一个Golang作业调度工具,可以使用简单的语法定期执行go函数,相比cron 的工具,gocron支持执行带参数的函数调用
实例:
每四秒钟跑一次
package mainimport ("log""github.com/jasonlvhit/gocron")func main() {i := 0s := gocron.NewScheduler()s.Every(4).Seconds().Do(func() {i++log.Println("execute per 4 seconds", i)})<-s.Start()// sc := s.Start()}
相比上面的cron,gocron的接口命名与使用有比较好的可读性
使用的基本用法
package mainimport ("fmt""github.com/jasonlvhit/gocron")func task() {fmt.Println("I am runnning task.")}func taskWithParams(a int, b string) {fmt.Println(a, b)}func main() {//可併發運行多個任務//注意 interval>1時調用sAPigocron.Every(2).Seconds().Do(task)gocron.Every(1).Second().Do(taskWithParams, 1, "hi")//在cron所有操作最後調用 start函數,否則start之後調用的操作無效不執行//<-gocron.Start()//在task執行過程中 禁止異常退出gocron.Every(1).Minute().DoSafely(taskWithParams, 1, "hello")// 支持在具體某一天、某天的某一時刻、每y-M-d h-m-s 執行任務gocron.Every(1).Monday().Do(task)gocron.Every(1).Thursday().Do(task)// function At() take a string like 'hour:min'gocron.Every(1).Day().At("10:30").Do(task)gocron.Every(1).Monday().At("18:30").Do(task)// 刪除某一任務// remove, clear and next_run_, time := gocron.NextRun()fmt.Println(time)gocron.Remove(task)//刪除所有任務gocron.Clear()//可同時創建一個新的任務調度 2個schedulers 同時執行s := gocron.NewScheduler()s.Every(3).Seconds().Do(task)<-s.Start()// <-gocron.Start()}