go之cron使用


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/fd3dda663953http://www.luyixian.cn/news_show_232522.aspx

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM