简言
1. 虽然golang提供了简单的定时器实现,比如time.NewTicker,但是只能功能过于简单
2. 没法做一些规则化,比如每隔多久触发,指定日期触发等等
3. 这里介绍一个第三方的定时器包,github.com/robfig/cron,功能强大,接口简单
4. 注意:linux 中的 cron 只能精确到分钟,无法精确到秒,想实现精确到秒的定时器只能自己实现
例子1(1秒触发一次的定时器):
执行结果如下图(我们是每隔一秒打印一次数字):
代码如下图:
package main
import (
"fmt"
"github.com/robfig/cron"
)
// 返回一个支持至 秒 级别的 cron
func newWithSeconds() *cron.Cron {
secondParser := cron.NewParser(cron.Second | cron.Minute |
cron.Hour | cron.Dom | cron.Month | cron.DowOptional | cron.Descriptor)
return cron.New(cron.WithParser(secondParser), cron.WithChain())
}
func main() {
i := 0
c := newWithSeconds()
spec := "0/1 * * * * ?" //一秒执行一次回调
c.AddFunc(spec, func() {
i++
fmt.Println("cron running:", i)
})
c.Start()
select {}
}
例子2(每隔两分钟执行一次,分钟里的第5秒)
代码如下
package main
import (
"fmt"
"time"
"github.com/robfig/cron"
)
// 返回一个支持至 秒 级别的 cron
func newWithSeconds() *cron.Cron {
secondParser := cron.NewParser(cron.Second | cron.Minute |
cron.Hour | cron.Dom | cron.Month | cron.DowOptional | cron.Descriptor)
return cron.New(cron.WithParser(secondParser), cron.WithChain())
}
func main() {
i := 0
c := newWithSeconds()
spec := "5 */2 * * * ?" //每隔两分钟,5秒的时候触发
c.AddFunc(spec, func() {
i++
fmt.Printf("time=%v, cron running=%v \n", time.Now(), i)
})
c.Start()
select {}
}
cron表达式的各个字段解释
字段名 | 是否必须 | 取值范围 | 特殊字符串 |
---|---|---|---|
秒(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表达式
输入 | 描述 | 等式 |
---|---|---|
@yearly (or @annually) | 每年1月1日凌晨执行一次 | 0 0 0 1 1 * |
@monthly | 每个月第一天的凌晨执行一次 | 0 0 0 1 * * |
@weekly | 每周周六的凌晨执行一次 | 0 0 0 * * 0 |
@daily (or @midnight) | 每天凌晨0点执行一次 | 0 0 0 * * * |
@hourly | 每小时执行一次 | 0 0 * * * * |