项目源码
定时任务本质就是在指定的时间执行一个命令,通常我们会借助Linux系统的
crontab
去实现,或者借助第三方软件去实现配置和调用,这两种都比较麻烦,需要去服务器配置或者多部署一个应用,在golang项目中,我们可以通过直接在项目中集成的方式来实现
安装
go get github.com/robfig/cron/v3
基本使用
c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly", func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop() // Stop the scheduler (does not stop any jobs already running).
从官方文档可以看到执行的规则spec
是支持多种写法的,最低可以支持秒级运行,也兼容Linux
系统crontab
的写法
下边再看一下简单使用:
import (
"fmt"
"github.com/robfig/cron/v3"
)
func main() {
c := cron.New()
c.Start()
defer c.Stop()
_, err := c.AddFunc("@every 3s", func() {
fmt.Println("@every 3s 执行开始")
})
_, err = c.AddFunc("@every 4s", func() {
fmt.Println("@every 4s 执行开始")
})
if err != nil {
fmt.Println(err)
return
}
select {}
}
运行之后可以看到控制台定时输出内容
项目中集成
首先,创建crontab需要用到的类型和接口,创建internal/crontab/crontab.go
文件:
package crontab
import (
"github.com/robfig/cron/v3"
)
// Init 函数用于初始化一个 Crontab 实例
func Init() *Crontab {
c := &Crontab{
cron: cron.New(),
}
return c
}
// Crontab 类型
type Crontab struct {
cron *cron.Cron
}
// TaskInterface 任务接口
type TaskInterface interface {
Spec() string
Fn() func()
}
// Start 启动crontab服务
func (c *Crontab) Start() {
c.cron.Start()
}
// Stop 停止crontab服务
func (c *Crontab) Stop() {
c.cron.Stop()
}
// AddTask 添加任务
func (c *Crontab) AddTask(tasks ...TaskInterface) {
if len(tasks) == 0 {
return
}
for _, task := range tasks {
_, err := c.cron.AddFunc(task.Spec(), task.Fn())
if err != nil {
return
}
}
}
接着,定义一下全局变量,修改internal/global/global.go
文件:
package global
import (
"eve/internal/config"
"eve/internal/crontab"
"eve/internal/event"
"go.uber.org/zap"
"gorm.io/gorm"
)
var (
Config *config.Config
DB *gorm.DB
Logger *zap.Logger
EventDispatcher *event.Dispatcher
Crontab *crontab.Crontab
)
然后,创建具体的task文件,新增app/task/foo_task.go
文件:
package task
import "fmt"
type FooTask struct{}
func (f *FooTask) Spec() string {
return "@every 3s"
}
func (f *FooTask) Fn() func() {
return func() {
fmt.Println("foo task executed")
}
}
再定义一个统一返回需要注册的task的合集的方法,新增app/task/task.go
文件:
package task
import "eve/internal/crontab"
func Tasks() []crontab.TaskInterface {
return []crontab.TaskInterface{
&FooTask{},
}
}
最后,在internal/bootstrap/init.go
init方法中新增定时任务初始化逻辑:
func init() {
...
// 初始化定时任务
global.Crontab = crontab.Init()
global.Crontab.AddTask(task.Tasks()...)
global.Crontab.Start()
}
代码修改完成,启动项目就可以看到控制台有输出,foo_task被执行了
总结
cron
库安装- 基本使用
- 在项目中集成
commit-hash: 58b65281