1、cron表達式的基本格式
在linux中使用過crontab,對定時任務應該就會有所了解,linux中利用crontab -e打開crontab表來添加定時任務,但是只能精確到分鍾,go中卻可以精確到秒。表達式如下:
┌─────────────second 范圍 (0 - 60) │ ┌───────────── min (0 - 59) │ │ ┌────────────── hour (0 - 23) │ │ │ ┌─────────────── day of month (1 - 31) │ │ │ │ ┌──────────────── month (1 - 12) │ │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to │ │ │ │ │ │ Saturday) │ │ │ │ │ │ │ │ │ │ │ │ * * * * * *
2、特殊字符
星號:匹配所有值
斜線:增長間隔,*/5表示5 10 15....分鍾運行
逗號:枚舉值,1,13,21表示1 13 21分鍾運行
連字符:表示范圍,10-15表示10 11 12 13 15分鍾運行
問號:只用於日和星期,表示不指定,可用*替代
3、go中cron設計思路
//cron實體 type Cron struct { entries []*Entry stop chan struct{} //控制Cron實例暫停 add chan *Entry //當Cron已經運行了,增加新的Entity,是通過add該channel實現的 snapshot chan []*Entry //獲取當前所有entity的快照 running bool //是否正在運行中 ...... } //調度實體 type Entry struct { //負責調度當前Entity中的Job執行 Schedule Schedule //Job下一步執行的時間 Next time.Time //Job上一次執行時間 Prev time.Time //要執行的Job Job Job } //每一個運行的試題包含一個Job type Job interface { Run() } //實現Job接口 type FuncJob func() //通過簡單的run()來實現job func (f FuncJob) Run() { f() } //每個實體包含一個調度器 type Schedule interface { //返回同一Entity中的job下一次執行的時間 Next(time.Time) time.Time } type SpecSchedule struct { Second, Minute, Hour, Dom, Month, Dow uint64 } type ConstantDelaySchedule struct { Delay time.Duration //循環時間間隔,最小單位為秒 } //實例化Cron func New() *Cron { return &Cron{ entries: nil, add: make(chan *Entry), stop: make(chan struct{}), snapshot: make(chan []*Entry), running: false, } } func Parse(spec string) (_ Schedule, err error) //將job加入Cron中,該方法只是簡單的通過FuncJob類型強制轉換cmd,然后調用AddJob方法 func (c *Cron) AddFunc(spec string, cmd func()) error //將job加入Cron中,通過Parse函數解析cron表達式spec的到調度實例(Schedule),之后調用c.Schedule方法 func (c *Cron) AddJob(spec string, cmd Job) error //獲取當前Cron總所有Entities的快照 func (c *Cron) Entries() []*Entry //通過兩個參數實例化一個Entity,然后加入當前的Cron中,如果當前Cron未運行,則直接將該Entity加入Cron中 //否則通過add這個成員channel將entity加入正在運行的Cron中 func (c *Cron) Schedule(schedule Schedule, cmd Job) //新啟動一個goroutine運行當前Cron func (c *Cron) Start() //通過給stop成員發送一個struct{}{}來停止當前的Cron,同時將running置為false, //從這里可以看出來stop只是去通知Cron停止,因此往channel發一個值即可,不用關心值的大小, //所以Cron中stop是一個空結構體 func (c *Cron) Stop()
4、示例:
package main import ( "log" "github.com/robfig/cron" ) //linux中crontab只能精確到分鍾,go中支持秒級別的 func newWithSecond() *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()) } type H struct { C *cron.Cron } func (h H) Run() { entries := h.C.Entries() if len(entries) > 0 { log.Println("---------cron running entries:", len(entries), ", next time:", entries[1].Next, ", pre time:", entries[1].Prev) } } func main() { i := 0 c := newWithSecond() spec := "*/5 * * * * *" entryId, err := c.AddFunc(spec, func() { i++ log.Println("cron running:", i) if i >= 1 { entries := c.Entries() log.Println("cron running entries:", len(entries), ", next time:", entries[0].Next, ", pre time:", entries[0].Prev) } }) log.Println("entryId:", entryId, " err:", err) s, err := cron.ParseStandard("*/1 * * * * ") if err != nil { log.Println(err) } h := H{c} c.Schedule(s, h) c.Start() select {} }
參考地址:https://www.jianshu.com/p/fd3dda663953、http://www.luyixian.cn/news_show_232522.aspx
