cron是golang实现定时任务比较好的库, 这个库提供了一个简单而强大的接口,用于创建和管理基于cron表达式的定时任务。cron库的主要特点有:
- 基于cron表达式的任务调度
- 多任务支持
- 容错和错误处理
- 可靠性
- 易用的API
- 灵活性
- 并发安全
安装 #
go get -u github.com/robfig/cron/v3@v3.0.0
简单使用 #
package main
import (
"fmt"
"github.com/robfig/cron/v3"
)
func main() {
// 创建一个默认的cron对象
c := cron.New()
// 添加任务
c.AddFunc("30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("30 3-6,20-23 * * *", func() { fmt.Println(".. in the range 3-6am, 8-11pm") })
c.AddFunc("@hourly", func() { fmt.Println("Every hour, starting an hour from now") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty, starting an hour thirty from now") })
c.Start()
//开始执行任务
c.Start()
//阻塞
select {}
}
预定的 Schedules #
| 条目 | 描述 | 等效于 |
|---|---|---|
@yearly (or @annually) |
Run once a year, midnight, Jan. 1st | 0 0 1 1 * |
@monthly |
Run once a month, midnight, first of month | 0 0 1 * * |
@weekly |
Run once a week, midnight between Sat/Sun | 0 0 * * 0 |
@daily (or @midnight) |
Run once a day, midnight | 0 0 * * * |
@hourly |
Run once an hour, beginning of hour | 0 * * * * |
@every <duration> |
固定间隔执行,@every 1h30m10s 表示 1小时30分钟10秒后执行,并且之后的每个时间间隔都执行。 |
精确到秒的 Cron 表达式 #
Cron v3 版本的表达式从六个参数调整为五个,取消了对秒的默认支持,需要精确到秒的控制可以使用 cron.WithSeconds() 解析器。
c := cron.New(cron.WithSeconds())
c.AddFunc("*/1 * * * * *", func() {
fmt.Println("Every 1 Second")
})
c.Start()
如果你仅仅需要每隔 N 秒运行一次 Job,可以使用 @every 这样的特殊 spec 表达式。
c := cron.New()
c.AddFunc("@every 10s", func() {
fmt.Println("Every 10 Seconds")
})
c.Start()
时区设置 #
// 本地时区早六点
cron.New().AddFunc("0 6 * * ?", ...)
// 上海时区早六点
nyc, _ := time.LoadLocation("Asia/Shanghai")
c := cron.New(cron.WithLocation(nyc))
c.AddFunc("0 6 * * ?", ...)
// 上海时区早六点
cron.New().AddFunc("CRON_TZ=Asia/Shanghai 0 6 * * ?", ...)
// 重庆时区早六点
c := cron.New(cron.WithLocation(nyc))
c.SetLocation("Asia/Tokyo")
c.AddFunc("CRON_TZ=Asia/Chongqing 0 6 * * ?", ...)
Cron 方法 #
AddFunc()- 支持传入如@every这样的 spec 表达式和标准表达式及func()函数,它封装了AddJob()。AddJob()- 支持传入 spec 和标准表达式及 Job,Job 是一个接口,实现 Run() 方法的类型即是一个 Job,它封装了Schedule()。Schedule()- 执行标准表达式和 Job,被AddJob()函数调用,只支持标准 Cron 表达式。Entries()- 获取全部 Entry,一个 Entry 即为一个定时任务条目。Entry()- 根据 EntryID 获取指定条目。Remove()- 根据 EntryID 移除指定条目。Location()- 获取 Local 时区。Start()- 使用新的 goroutine 启动,不会阻塞当前协程,已运行的调度器重复调用会被忽略。Run()- 在当前 goroutine 启动,会阻塞当前协程,已运行的调度器重复调用会被忽略。Stop()- 停止调度器,返回 Context,可根据 Context 来等待任务执行完成。
可以获取任务上次、下次运行时间。
c = cron.New()
entryId, _ := c.AddFunc("@every 15m", func() {
fmt.Println("Every 15 Minutes")
})
entry := c.Entry(entryId)
fmt.Println(entry.Next)
Job 接口 #
除了使用无参的回调方式,cron还提供了实现job接口的方式:
type Job interface {
Run()
}
示例如下:
package main
import (
"fmt"
"time"
"github.com/robfig/cron/v3"
)
func main() {
job := cron.New(cron.WithSeconds())
j := &myJob{}
job.AddJob("@every 1s", j)
job.Start()
select {}
}
type myJob struct {
i int
}
func (j *myJob) Run() {
j.i++
fmt.Println("hello world:", j.i)
}