✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。
所属的专栏: Go语言开发零基础到高阶实战
景天的主页: 景天科技苑
文章目录
- Go语言中定时任务Cron
-
- 一、Cron库的安装
- 二、Cron库的基本用法
- 三、Cron表达式的详解
- 四、Cron库的高级用法
-
- [1. 使用自定义的Job类型](#1. 使用自定义的Job类型)
- [2. 动态调整任务配置](#2. 动态调整任务配置)
- [3. 预定义时间格式](#3. 预定义时间格式)
- [4. 使用带参数的函数作为任务](#4. 使用带参数的函数作为任务)
- [5. 定义带参数的Job类型](#5. 定义带参数的Job类型)
- 五、总结
Go语言中定时任务Cron
Cron是一个强大的定时任务调度库,它允许开发者在Go应用中方便地设置和管理定时任务。Cron库通过解析Cron表达式,可以精确控制任务的执行时间和频率。本文将结合具体案例,详细介绍Cron在Go语言中的用法,包括安装、基本用法、Cron表达式的详解、高级用法以及实际应用案例。
一、Cron库的安装
在使用Cron库之前,需要先将其安装到Go开发环境中,项目中创建go mod文件,配置好代理。可以使用以下命令进行安装:
bash
go get github.com/robfig/cron/v3
安装完成后,就可以在Go代码中导入Cron库并开始使用了。
二、Cron库的基本用法
Cron库的核心是使用Cron表达式来定义任务的执行时间和频率。Cron表达式由六个字段组成,分别表示秒、分、时、日、月、周几(0~6表示周日到周六)。
以下是一个简单的示例代码,展示如何使用Cron库创建一个每5秒钟执行一次的定时任务:
go
package main
import (
"fmt"
"github.com/robfig/cron/v3"
"time"
)
func main() {
// 创建一个新的Cron实例,默认是支持分钟级别的调度,加上cron.WithSeconds() 支持秒级别调度
c := cron.New(cron.WithSeconds()) //精确到秒级
// 添加一个每5秒钟执行一次的定时任务
spec := "*/5 * * * * *"
// func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error)
// AddFunc第一个参数是一个Cron表达式,表示任务的执行时间和频率;第二个参数是一个无参的函数
c.AddFunc(spec, func() {
fmt.Println("Task executed every 5 seconds", time.Now())
})
// 启动Cron实例,开始执行定时任务
c.Start()
// 为了演示效果,让主程序运行一段时间
time.Sleep(30 * time.Second)
// 停止Cron实例(在实际应用中,通常不需要手动停止Cron实例,除非程序需要退出)
c.Stop()
}
在这个示例中,我们首先创建了一个Cron实例,然后使用AddFunc
方法添加了一个每5秒钟执行一次的定时任务。AddFunc
方法接受两个参数:第一个参数是一个Cron表达式,表示任务的执行时间和频率;第二个参数是一个无参的函数,表示要执行的任务。最后,我们调用Start
方法启动Cron实例,并开始执行定时任务。为了演示效果,我们使用time.Sleep
让主程序运行了一段时间,然后调用Stop
方法停止了Cron实例。
三、Cron表达式的详解
Cron表达式是Cron库的核心,用于定义任务的执行时间和频率。Cron表达式由六个字段组成,每个字段用空格分隔,分别表示:
- 秒(0-59)
- 分(0-59)
- 时(0-23)
- 日(1-31)
- 月(1-12或JAN-DEC)
- 周几(0-6或SUN-SAT)
每个字段可以包含以下特殊字符:
*
:表示匹配任何值。例如,在月份字段中使用*
,表示每个月。/
:表示步长。例如,在小时字段中使用*/2
,表示每2小时触发一次。,
:列举一些离散的值和多个范围。例如,在周几字段中使用MON,WED,FRI
,表示周一、三和五。-
:表示范围。例如,在小时字段中使用9-17
,表示从上午9点到下午5点。?
:只能用在日和周几字段中,用来代替*
,表示每月/周的任意一天(注意:在某些Cron实现中,?
可能不被支持)。
以下是一些Cron表达式的示例及其含义:
30 * * * * *
:表示每分钟的第30秒触发。0 0/5 * * * *
:表示每5分钟的第0秒触发。0 0 1 * * *
:表示每月1日的0点触发。0 0 * * 1 *
:表示每周一的0点触发。0 0 * * * MON
:表示每周一的0点触发(与上一个表达式等价,但使用了周几的简写)。0 0/30 9-17 * * *
:表示在上午9点到下午5点之间,每30分钟触发一次。
go语言定时任务cron中的*和?
在Cron表达式中,*和"?"都是用来指定时间的通配符,但它们有一些区别:
markup
"*":星号()可以用在所有字段上,表示该字段的任何值。例如,如果你想要在每分钟的每秒钟触发任务,你可以使用"*"在秒字段上。
"?":问号(?)可以用在日和星期字段上,表示不指定值。不同于星号(*),问号不能用在其他字段上。当你在日字段上使用"?"时,意味着不关心那天是哪一天,只关心月份和星期字段。同理,在星期字段上使用"?"时,意味着不关心那天是星期几,只关心日字段和月份字段。
如果是使用 crontab := cron.New() 则只需要五个 * 。如 ***** 从分钟开始
如果使用cron.New()定义,却使用了6个* 运行将会报错
四、Cron库的高级用法
除了基本的AddFunc
方法外,Cron库还提供了一些高级用法,如使用自定义的Job类型、动态调整任务配置、获取任务执行结果等。
1. 使用自定义的Job类型
Cron库允许使用自定义的Job类型,实现更加灵活的任务调度。以下是一个示例代码,展示如何使用自定义的Job类型:
go
package main
import (
"fmt"
"github.com/robfig/cron/v3"
"time"
)
// MyJob 定义一个自定义的Job类型
type MyJob struct {
// 可以根据需要添加其他字段
}
// Run 实现cron.Job接口中的Run方法
func (j *MyJob) Run() {
fmt.Println("MyJob is running", time.Now())
}
func main() {
c := cron.New(cron.WithSeconds())
// 创建一个自定义Job的实例
myJob := &MyJob{}
// 添加自定义Job到Cron实例中。这里使用AddJob方法
_, err := c.AddJob("*/5 * * * * *", myJob)
if err != nil {
fmt.Println("Error adding job:", err)
return
}
c.Start()
time.Sleep(30 * time.Second)
c.Stop()
}
在这个示例中,我们定义了一个自定义的Job类型MyJob
,并实现了cron.Job
接口的Run
方法。然后,我们创建了一个MyJob
的实例,并将其添加到Cron实例中。这样,每当Cron表达式匹配时,就会执行MyJob
的Run
方法。
2. 动态调整任务配置
Cron库允许在运行时动态调整任务的配置。以下是一个示例代码,展示如何动态添加、删除和更新定时任务:
go
package main
import (
"fmt"
"github.com/robfig/cron/v3"
"time"
)
func main() {
c := cron.New(cron.WithSeconds())
// 添加一个每5秒钟执行一次的定时任务
entryID, err := c.AddFunc("*/5 * * * * *", func() {
fmt.Println("Task 1: Every 5 seconds", time.Now())
})
if err != nil {
fmt.Println("Error adding task 1:", err)
return
}
// 启动定时器
c.Start()
// 等待一段时间,以便观察任务1的执行
time.Sleep(10 * time.Second)
// 删除任务1
c.Remove(entryID)
// 添加一个每10秒钟执行一次的定时任务
_, err = c.AddFunc("*/10 * * * * *", func() {
fmt.Println("Task 2: Every 10 seconds", time.Now())
})
if err != nil {
fmt.Println("Error adding task 2:", err)
return
}
// 为了演示效果,让主程序运行一段时间
time.Sleep(30 * time.Second)
c.Stop()
}
在这个示例中,我们首先添加了一个每5秒钟执行一次的定时任务,并获取了其EntryID。然后,我们等待了一段时间,以便观察任务1的执行情况。接着,我们使用EntryID删除了任务1,并添加了一个每10秒钟执行一次的定时任务。最后,我们启动了Cron实例,并让主程序运行了一段时间以观察任务2的执行情况。
需要注意的是,在删除任务时,我们需要提供正确的EntryID。如果EntryID不正确或任务已经被删除,那么删除操作将失败并返回错误。
3. 预定义时间格式
go
package main
import (
"fmt"
"github.com/robfig/cron/v3"
"time"
)
func main() {
// 创建一个新的Cron实例,默认是支持分钟级别的调度,加上cron.WithSeconds() 支持秒级别调度
c := cron.New(cron.WithSeconds()) //精确到秒级
// 添加一个每3秒钟执行一次的定时任务 也可以使用预定义时间格式
spec := "@every 3s"
// func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error)
// AddFunc第一个参数是一个Cron表达式,表示任务的执行时间和频率;第二个参数是一个无参的函数
c.AddFunc(spec, func() {
fmt.Println("Task executed every 3 seconds", time.Now())
})
// 启动Cron实例,开始执行定时任务
c.Start()
// 为了演示效果,让主程序运行一段时间
time.Sleep(30 * time.Second)
// 停止Cron实例(在实际应用中,通常不需要手动停止Cron实例,除非程序需要退出)
c.Stop()
}
4. 使用带参数的函数作为任务
如果我们需要在任务函数中使用参数,可以使用闭包或者定义一个带参数的函数类型。
使用闭包传递参数
闭包是一种捕获并存储其外部作用域的引用的函数。利用闭包,我们可以轻松地将参数传递给定时任务函数。
go
package main
import (
"fmt"
"github.com/robfig/cron/v3"
)
func main() {
c := cron.New(cron.WithSeconds())
// 定义一个带参数的外部函数 外函数带有参数,返回一个函数
executeTask := func(param string) func() {
return func() {
fmt.Println("Task executed with parameter:", param)
}
}
// 使用闭包传递参数
taskParam := "Hello, Cron with Closure!"
c.AddFunc("@every 1s", executeTask(taskParam))
c.Start()
// 为了让程序运行足够长的时间以观察定时任务的执行,我们使用一个空的select语句来阻塞主goroutine
select {}
}
在这个示例中,我们定义了一个名为executeTask的外部函数,它接受一个字符串参数并返回一个无参数的函数(即闭包)。
在闭包内部,我们打印了传递进来的参数。然后,我们将这个闭包作为任务函数添加到Cron实例中。
5. 定义带参数的Job类型
除了使用闭包外,我们还可以定义一个带参数的Job类型。这需要实现cron.Job接口,该接口包含一个Run方法。
go
package main
import (
"fmt"
"github.com/robfig/cron/v3"
"time"
)
// ParamJob 定义带参数的Job类型
type ParamJob struct {
param string
}
// Run 实现cron.Job接口的Run方法
func (j *ParamJob) Run() {
fmt.Println("ParamJob executed with parameter:", j.param, time.Now())
}
func main() {
c := cron.New(cron.WithSeconds())
// 创建一个ParamJob实例并设置参数
jobParam := "Hello, Cron with ParamJob!"
//注意,这里定义对象的时候使用指针
paramJob := &ParamJob{param: jobParam}
// 将ParamJob实例添加到Cron实例中
// 注意:由于AddJob方法期望的是一个cron.Job接口,因此我们需要将ParamJob实例的指针转换为cron.Job接口
c.AddJob("@every 2s", paramJob)
c.Start()
// 使用一个空的select语句来阻塞主goroutine
select {}
}
在这个示例中,我们定义了一个名为ParamJob
的结构体类型,并为其添加了一个param
字段来存储参数。然后,我们实现了cron.Job
接口的Run
方法,在该方法中打印了参数。最后,我们创建了一个ParamJob
实例,并将其添加到Cron实例中。
需要注意的是,在调用AddJob
方法时,我们需要将ParamJob
实例的指针转换为cron.Job
接口。这是因为AddJob
方法期望的是一个实现了cron.Job
接口的对象。
五、总结
Cron库是一个功能强大且易于使用的Go语言定时任务库。它提供了灵活的Cron表达式和易于使用的API,使开发者能够方便地添加和管理定时任务。通过本文的介绍和示例代码,我们了解了Cron库的基础用法、实际案例以及高级用法(如动态添加和移除任务、使用带参数的函数作为任务)。这些知识和技巧将帮助我们更好地在Go应用中使用Cron库来实现定时任务调度。