本文主要介绍 Go 定时任务包:https://github.com/robfig/cron
的使用。
快速上手
下载包,截至本文发布,版本为:v3.0.1
go get github.com/robfig/cron/v3@v3.0.1
简单示例:
每三秒打印字符串blog.mango.im
,后面死循环保证主 Goroutine 不退出
package main
import (
"github.com/robfig/cron/v3"
"log"
"time"
)
func main() {
log.Println("starting...")
c := cron.New()
c.AddFunc("@every 3s", func() {
log.Println("print blog.mango.im per 3s ")
})
c.Start()
for {
time.Sleep(10 * time.Hour)
log.Println("main goroutine")
}
}
用法
调用者可以注册要按给定计划表调用的方法。 Cron 将在它们自己的 goroutine 中运行它们。
c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("每半小时") })
c.AddFunc("@hourly", func() { fmt.Println("每小时") })
c.AddFunc("@every 1h30m", func() { fmt.Println("每小时三十分") })
c.Start()
..
// 方法异步调用自己的 goroutine
...
// 方法也可以添加到正在运行的 Cron
c.AddFunc("@daily", func() { fmt.Println("每天") })
..
// 检查 cron 作业条目的下一次和上一次运行时间。
inspect(c.Entries())
..
c.Stop() // 停止调度程序(不停止任何已经运行的作业)。
CRON 表达式格式
cron 表达式表示一组时间,使用6个空格分隔的字段。
字段名 | 是否强制? | 允许的值 | 允许的特殊字符
---------- | ---------- | -------------- | --------------------------
Seconds | Yes | 0-59 | * / , -
Minutes | Yes | 0-59 | * / , -
Hours | Yes | 0-23 | * / , -
Day of month | Yes | 1-31 | * / , - ?
Month | Yes | 1-12 or JAN-DEC | * / , -
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
注意:月份和星期几字段值不区分大小写。 “SUN”、“Sun”和“sun”同样被接受。
特殊字符
星号 ( * )
星号表示 cron 表达式将匹配字段的所有值;例如,在第 5 个字段(月)中使用星号表示每个月。
斜线 ( / )
斜线用于描述范围的增量。例如,第 1 个字段(分钟)中的 3-59/15 将表示一小时的第 3 分钟,此后每 15 分钟一次。形式“*/…”等价于形式“first-last/…”,即在字段的最大可能范围内递增。接受形式“N/…”表示“N-MAX/…”,即从 N 开始,使用增量直到该特定范围结束。它不会环绕。
逗号 ( , )
逗号用于分隔列表中的项目。例如,在第 5 个字段(星期几)中使用“MON,WED,FRI”表示星期一、星期三和星期五。
连字符 ( - )
连字符用于定义范围。例如,9-17 表示上午 9 点到下午 5 点之间的每小时。
问号(?)
可以使用问号代替“*”以将月中的某天或一周中的某天留空。
预定义计划
你可以使用多个预定义计划之一来代替 cron 表达式。
条目 | 描述 | 等同于
----- | ----------- | -------------
@yearly (or @annually) | 每年运行一次,1月1号0点 | 0 0 0 1 1 *
@monthly | 每月运行一次,每月第一天0点 | 0 0 0 1 * *
@weekly | 每周运行一次,周日0点 | 0 0 0 * * 0
@daily (or @midnight) | 每天运行一次,0点 | 0 0 0 * * *
@hourly | 每小时运行一次, | 0 0 * * * *
间隔
你还可以安排一个任务以固定的时间间隔执行,从它被添加或 cron 运行时开始。 这是通过像这样格式化 cron 规范来支持的:
@every <duration>
其中“duration”是 time.ParseDuration (http://golang.org/pkg/time/#ParseDuration) 接受的字符串。
例如,“@every 1h30m10s”表示在每 1 小时 30 分 10 秒后就开始运行任务。
注意:间隔不考虑任务运行时间。 例如,如果任务需要 3 分钟运行,并且计划每 5 分钟运行一次,则每次运行之间只有 2 分钟的空闲时间。
时区
所有的解释和调度都是在机器的本地时区完成的(由 Go 时间包(http://www.golang.org/pkg/time)提供)。
请注意,在夏令时跨越式过渡期间安排的作业将不会运行!
线程安全
由于 Cron 服务与调用代码同时运行,因此必须采取一定的措施以确保正确同步。
所有 cron 方法都被设计为正确同步,只要调用者确保调用在它们之间有明确的发生前排序。
执行
Cron 条目存储在一个数组中,按它们的下一个激活时间排序。 Cron 休眠直到下一个作业要运行。
醒来后:
- 它运行在那一秒处于活动状态的每个条目
- 它计算已运行作业的下一次运行时间
- 它按下次激活时间重新排序条目数组。
- 它进入睡眠状态,直到最快的工作。
参考:https://pkg.go.dev/github.com/robfig/cron