go:cron库包

460 阅读4分钟

0/参考网址

blog.csdn.net/qq_42887507…

1/前言

我们在项目开发中,常常会遇到定时任务的场景,比如定期执行某个函数,定期清理日志文件,定期备份数据等。
在go语言开发中,我们可以使用go语言内置的库包cron来实现定时任务。

Cron是Go中用于设置定时任务的一个库包,需要注意的是,Cron库分两个大版本,v1.2和v3.0,
其功能和go get地址都是不同的,注意区分。

2/cron1.2版本

安装该库包

go get github.com/robfig/cron

使用demo

package main

import (
	"github.com/robfig/cron"
	"log"
)

func testCornv1_2() {
    log.Println("Starting...")
    
    // 新建一个定时任务对象
    c := cron.New() 
    
    // 给对象增加定时任务
    c.AddFunc("*/5 * * * * *", func() {
            log.Println("hello world1")
    })
    c.AddFunc("*/8 * * * * *", func() {
            log.Println("hello world2")
    })

    c.Start()  // 启动定时任务

    defer c.Stop()  # 延迟关闭定时任务
}

// 主函数
func main() {
    go testCornv1_2()  // 在主函数中,去调用定时任务的函数
    select {
     //查询语句,保持程序运行
    }
}

cron表达式的设置说明

Cron的v1.2版本默认支持精确到`秒`的cron表达式,Linux系统原生支持的标准cron表达式只能精确到分钟。
具体的设置如下所示:一共是5个字段

 ┌─────────────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)
 │ │ │ │ │ │
 │ │ │ │ │ │
 * * * * * *  


匹配符号
<1>星号(*) :表示 cron 表达式能匹配该字段的所有值。如在第5个字段使用星号(month),表示每个月
<2>斜线(/):表示增长间隔,如第2个字段(minutes) 值是 3-59/15,表示每小时的第3分钟开始执行一次,之后 每隔 15 分钟执行一次(即 33+0*15)、183+1*15)、333+2*15)、483+3*15) 这些时间点执行),这里也可以表示为:3/15
<3>逗号(,):用于枚举值,如第6个字段值是 MON,WED,FRI,表示 星期一、三、五 执行
<4>连字号(-): 表示一个范围,如第3个字段的值为 9-17 表示 9am 到 5pm 直接每个小时(包括917<5>问号(?):只用于 日(Day of month) 和 星期(Day of week),表示不指定值,可以用于代替 *

//5秒执行一次:*/5 * * * * *
// 每个工作日早上945分执行一次:0 45 9 * * 1,2,3,4,5

3/cron3.0版本

安装

go get github.com/robfig/cron/v3@v3.0.0

demo

Cron的v3版本相比v1.2版本最大的变化就是支持定时任务的撤销功能:
   cron.Remove(cron.EntryID)。
   cron.EntryID这个值在添加定时任务会返回。
    package main

import (
    "github.com/robfig/cron/v3"
    "learn-go/corn/DB"
    "log"
    "time"
)

var c *cron.Cron

// InitCron 初始化并启动Cron
func InitCron() {
    // 初始化定时任务对象
    // Cron v3默认支持精确到分钟的cron表达式
    // cron.WithSeconds()表示指定支持精确到秒的表达式
    c = cron.New(cron.WithSeconds())

    // 从数据库中获取已计划的任务并运行
    for examId := range DB.DB {
        id, err := addCron(examId, DB.DB[examId].Spec)
        if err != nil {
            log.Printf("InitCron err: %v", err)
        }
        // 更新任务id
        DB.Update(examId, DB.DB[examId].Spec, id)
    }
}

// StartCron 启动Cron
func StartCron() {
    c.Start()
    defer c.Stop()
    select {}
}

// AddCron 运行一个定时任务
func AddCron(examId, spec string) int {
    id, err := addCron(examId, spec)
    if err != nil {
            log.Println(err)
            return 0
    }

    // 将定时任务添加到数据库
    DB.Insert(examId, spec, id)

    return id
}

func addCron(examId, spec string) (int, error) {
    id, err := c.AddFunc(spec, func() {
            log.Printf("推送考试提醒消息 examId: %v\n", examId)
    })
    if err != nil {
            log.Printf("err: %v\n", err)
    }

    return int(id), err
}

// DeleteCron 删除定时任务
func DeleteCron(examId string) {
    deleteCron(examId)
    // 从数据库删除该定时任务数据
    DB.Delete(examId)
}

func deleteCron(examId string) {
    // 查询数据库获取cron id
    ccron := DB.Query(examId)
    id := ccron.Id

    // 移除定时任务
    c.Remove(cron.EntryID(id))
}

// UpdateCron 修改定时任务的执行时间
func UpdateCron(examId, spec string) {
    id := updateCron(examId, spec)
    // 更新数据库cron id
    DB.Update(examId, spec, id)
}

func updateCron(examId, spec string) int {
    // 删除原定时任务
    DeleteCron(examId)
    // 添加新的定时任务
    id := AddCron(examId, spec)

    return id
}

func main() {
    InitCron()
    go StartCron()

    AddCron("6652", "*/1 * * * * *")
    log.Printf("examId :%v Cron: %v \n", "6652", DB.Query("6652"))

    AddCron("6616", "*/1 * * * * *")
    log.Printf("examId :%v Cron: %v \n", "6616", DB.Query("6616"))

    AddCron("6636", "*/3 * * * * *")
    log.Printf("examId :%v Cron: %v \n", "6636", DB.Query("6636"))

    // 获取id为1的定时任务的下一次一次运行时间
    log.Println(c.Entry(1).Next.Unix())

    time.Sleep(time.Second * 8)

    // 获取id为1的定时任务的上一次运行时间
    log.Println(c.Entry(1).Prev.Unix())

    log.Println("-------------UpdateCron-------------")
    UpdateCron("6652", "*/2 * * * * *")

    time.Sleep(time.Second * 20)

    log.Println("-------------DeleteCron-------------")
    log.Printf("DB Before DeleteCron: %v\n", DB.DB)
    DeleteCron("6616")
    log.Printf("DB After DeleteCron: %v\n", DB.DB)

    select {}  # 保持程序运行
}