Cron定时任务

在实际的应用项目中,定时任务的使用是很常见的。你是否有过 Golang 如何做定时任务的疑问,莫非是轮询?
在本文中我们将结合我们的项目讲述 Cron

介绍

我们将使用 cron 这个包,它实现了 cron 规范解析器和任务运行器,简单来讲就是包含了定时任务所需的功能

Cron表达式格式

字段名

是否必填

允许的值

允许的特殊字符

分(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

* / , - ?

Cron表达式表示一组时间,使用 5 个空格分隔的字段

Cron特殊字符

  1. 星号(*)
    星号表示将匹配字段的所有值
  2. 斜线(/)
    斜线用户 描述范围的增量,表现为 “N-MAX/x”,first-last/x 的形式,例如 3-59/15 表示此时的第三分钟和此后的每 15 分钟,到59分钟为止。即从 N 开始,使用增量直到该特定范围结束。它不会重复
  3. 逗号(,)
    逗号用于分隔列表中的项目,例如,在 Day of week 使用“MON,WED,FRI”将意味着星期一,星期三和星期五
  4. 连字符(-)
    连字符用于定义范围。例如,9 - 17 表示从上午 9 点到下午 5 点的每个小时
  5. 问号(?)
    不指定值,用于代替 “ * ”,类似 “ _ ” 的存在,不难理解

预定义的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 *

@hourly

每小时运行一次

0 0

安装

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

编写硬删除的代码

打开 models 目录下的 tag.go、article.go文件,分别添加以下代码

  1. tag.go
func CleanAllTag() bool {
	db.Unscoped().Where("deleted_at != ?", 0).Delete(&Tag{})
	return true
}
  1. article.go
func ClearAllArticle() bool {
	db.Unscoped().Where("deleted_at != ?", 0).Delete(&Article{})
	return true
}

注意硬删除要使用 Unscoped(),这是 GORM 的约定

编写Cron

在 项目根目录下新建 cron.go 文件,用于编写定时任务的代码,写入文件内容

package main

import (
	"fmt"
	"gin_log/models"
	"github.com/robfig/cron/v3"
	"log"
	"time"
)

func main() {
	log.Println("Staring...")
	c := cron.New()
	e1, err := c.AddFunc("* * * * *", func() {
		log.Println("Run models.CleanAllTag")
		models.CleanAllTag()
	})
	if err != nil {
		c.Stop()
		fmt.Println(e1, err)
	}
	e2, err := c.AddFunc("* * * * *", func() {
		log.Println("Run models.CleanAllArticle")
		models.CleanAllArticle()
	})
	if err != nil {
		c.Stop()
		fmt.Println(e2, err)
	}

	c.Start()

	timer := time.NewTicker(time.Second * 10)
	for {
		select {
		case <-timer.C:
			timer.Reset(time.Second * 10)
		}
	}
}

开启我们的定时任务:
go run cron.go

2022/09/13 14:08:00 Run models.CleanAllArticle
2022/09/13 14:08:00 Run models.CleanAllTag

2022/09/13 14:09:00 Run models.CleanAllArticle
2022/09/13 14:09:00 Run models.CleanAllTag

这两个任务就会每分钟执行一次。
检查输出日志正常,模拟已软删除的数据,定时任务工作OK

小结

定时任务很常见,本文能够熟知golang怎么实现一个简单的定时任务调度管理。
可以不依赖系统的crontab设置。