cron-github地址:
https://github.com/robfig/cron
1、安装依赖
go get github.com/robfig/cron/v3@v3.0.0
导入:
import "github.com/robfig/cron/v3"
2、代码示例
2.1、普通操作
func TestCron(t *testing.T) {
c := cron.New()
cronId, err := c.AddFunc("@every 1s", func() {
fmt.Println(time.Now(), "一秒一次")
})
fmt.Println("执行定时任务id", cronId, err)
c.Start()
time.Sleep(8 * time.Second)
}
=== RUN TestCron
执行定时任务id 1 <nil>
2022-08-23 16:47:15.0004815 +0800 CST m=+0.594273801 一秒一次
2022-08-23 16:47:16.0006382 +0800 CST m=+1.594430501 一秒一次
2022-08-23 16:47:17.0007651 +0800 CST m=+2.594557401 一秒一次
2022-08-23 16:47:18.0009394 +0800 CST m=+3.594731701 一秒一次
2022-08-23 16:47:19.0010578 +0800 CST m=+4.594850101 一秒一次
2022-08-23 16:47:20.0003283 +0800 CST m=+5.594120701 一秒一次
2022-08-23 16:47:21.0004863 +0800 CST m=+6.594278601 一秒一次
2022-08-23 16:47:22.0005673 +0800 CST m=+7.594359601 一秒一次
--- PASS: TestCron (8.00s)
PASS
ok eth2-lighthouse/test 8.002s
> 测试运行完成时间: 2022/8/23 16:47:22 <
2.2、多定时任务
func TestCrons(t *testing.T) {
c := cron.New(cron.WithChain())
cronId1, err := c.AddFunc("@every 1s", func() {
fmt.Println(time.Now(), "1秒一次")
})
cronId2, err := c.AddFunc("@every 2s", func() {
fmt.Println(time.Now(), "2秒一次")
})
fmt.Println("执行定时任务id", cronId1, err)
fmt.Println("执行定时任务id", cronId2, err)
c.Start()
defer c.Stop()
time.Sleep(8 * time.Second)
}
=== RUN TestCrons
执行定时任务id 1 <nil>
执行定时任务id 2 <nil>
2022-08-23 17:08:20.0011193 +0800 CST m=+0.390331301 1秒一次
2022-08-23 17:08:21.000471 +0800 CST m=+1.389683001 2秒一次
2022-08-23 17:08:21.0004908 +0800 CST m=+1.389702901 1秒一次
2022-08-23 17:08:22.0006538 +0800 CST m=+2.389865901 1秒一次
2022-08-23 17:08:23.0008043 +0800 CST m=+3.390016301 2秒一次
2022-08-23 17:08:23.0008207 +0800 CST m=+3.390032701 1秒一次
2022-08-23 17:08:24.0009363 +0800 CST m=+4.390148301 1秒一次
2022-08-23 17:08:25.0010462 +0800 CST m=+5.390258201 2秒一次
2022-08-23 17:08:25.0010754 +0800 CST m=+5.390287401 1秒一次
2022-08-23 17:08:26.0004696 +0800 CST m=+6.389681701 1秒一次
2022-08-23 17:08:27.0005977 +0800 CST m=+7.389809701 2秒一次
2022-08-23 17:08:27.0006388 +0800 CST m=+7.389850801 1秒一次
--- PASS: TestCrons (8.00s)
PASS
ok eth2-lighthouse/test 8.002s
2.3、多定时任务Job(也可以单独执行,可带参数执行)
func TestCronsJob(t *testing.T) {
c := cron.New(cron.WithSeconds())
//不带参
cronJob1, err := c.AddJob("@every 1s", &CronJob1{})
//带参数执行
cronJob2, err := c.AddJob("@every 2s", &CronJob2{Name: "任务2"})
fmt.Println("执行定时任务id", cronJob1, err)
fmt.Println("执行定时任务id", cronJob2, err)
c.Start()
defer c.Stop()
time.Sleep(8 * time.Second)
}
type CronJob1 struct {
}
func (t CronJob1) Run() {
fmt.Println(time.Now(), "执行定时任务: CronJob1")
}
type CronJob2 struct {
Name string
}
func (t CronJob2) Run() {
fmt.Println(time.Now(), "执行定时任务: CronJob2", t.Name)
}
=== RUN TestCronsJob
执行定时任务id 1 <nil>
执行定时任务id 2 <nil>
2022-08-23 17:15:51.0010691 +0800 CST m=+0.646762301 执行定时任务: CronJob1
2022-08-23 17:15:52.0002512 +0800 CST m=+1.645944501 执行定时任务: CronJob1
2022-08-23 17:15:52.0002304 +0800 CST m=+1.645923601 执行定时任务: CronJob2 任务2
2022-08-23 17:15:53.0005753 +0800 CST m=+2.646268601 执行定时任务: CronJob1
2022-08-23 17:15:54.0006843 +0800 CST m=+3.646377601 执行定时任务: CronJob2 任务2
2022-08-23 17:15:54.0006994 +0800 CST m=+3.646392601 执行定时任务: CronJob1
2022-08-23 17:15:55.0009107 +0800 CST m=+4.646603901 执行定时任务: CronJob1
2022-08-23 17:15:56.0010091 +0800 CST m=+5.646702301 执行定时任务: CronJob2 任务2
2022-08-23 17:15:56.0010264 +0800 CST m=+5.646719801 执行定时任务: CronJob1
2022-08-23 17:15:57.0002019 +0800 CST m=+6.645895101 执行定时任务: CronJob1
2022-08-23 17:15:58.0008982 +0800 CST m=+7.646591401 执行定时任务: CronJob2 任务2
2022-08-23 17:15:58.0009412 +0800 CST m=+7.646634601 执行定时任务: CronJob1
--- PASS: TestCronsJob (8.00s)
PASS
ok eth2-lighthouse/test 8.003s
3、一些常用类型说明和函数解释
3.1、cron.New(cron.WithLocation())
指定时区:所有时间都是基于当前时区的
- 1、在时间字符串前面添加一个CRON_TZ= + 具体时区, 比如:东京时区为Asia/Tokyo,纽约时区为America/New_York;上海时区为Asia/Shanghai;香港时区为Asia/Hong_Kong
- 2、创建cron对象时增加一个时区选项cron.WithLocation(location),location为time.LoadLocation(zone)加载的时区对象,zone为具体的时区格式。
loc, _ := time.LoadLocation("Asia/Shanghai")
c := cron.New(cron.WithLocation(loc))
或者
c := cron.New()
c.AddFunc("CRON_TZ=Asia/Shanghai * 1 * * * *", func() {
})
3.2、cron.New(cron.WithLocation())
Job 包装器可以在执行实际的Job前后添加一些逻辑:
- 捕获panic;
- 如果Job上次运行还未结束,推迟本次执行;
- 如果Job上次运行还未介绍,跳过本次执行;
- 记录每个Job的执行情况。
//跳过本次执行 log可以写自己的。。。。
c := cron.New(cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)))
//推迟本次执行
c := cron.New(cron.WithChain(cron.DelayIfStillRunning(cron.DefaultLogger)))
//捕获异常啥的
c := cron.New(cron.WithChain(cron.Recover(cron.DefaultLogger)))
3.3、cron.New(cron.WithSeconds())
让时间格式支持秒,实际上内部调用了WithParser。
c := cron.New(cron.WithSeconds())
3.4、cron.New(cron.WithLogger())
让时间格式支持秒,实际上内部调用了WithParser。
c := cron.New(cron.WithLogger(cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))))
4、Cron时间常用表达式
- @yearly:也可以写作@annually,表示每年第一天的 0 点。等价于0 0 1 1 *;
- @monthly:表示每月第一天的 0 点。等价于0 0 1 * *;
- @weekly:表示每周第一天的 0 点,注意第一天为周日,即周六结束,周日开始的那个 0 点。等价于0 0 * * 0;
- @daily:也可以写作@midnight,表示每天 0 点。等价于0 0 * * *;
- @hourly:表示每小时的开始。等价于0 * * * *。
- @every :会调用time.ParseDuration()函数解析,例如1s ,1m,1d,1h30m
"* * * * * *"
分别对应:
分 时 天 月 星期
每隔5秒执行一次:*/5 * * * * ?
每隔1分钟执行一次:0 */1 * * * ?
每天23点执行一次:0 0 23 * * ?
每天凌晨1点执行一次:0 0 1 * * ?
每月1号凌晨1点执行一次:0 0 1 1 * ?
每周一和周三晚上22:30: 00 30 22 * * 1,3
在15分、25分、35分执行一次:0 15,25,35 * * * ?