当前位置: 首页 > news >正文

【Golang】Go语言中如何创建Cron定时任务

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Go语言中定时任务Cron
    • 一、Cron库的安装
    • 二、Cron库的基本用法
    • 三、Cron表达式的详解
    • 四、Cron库的高级用法
      • 1. 使用自定义的Job类型
      • 2. 动态调整任务配置
      • 3. 预定义时间格式
      • 4. 使用带参数的函数作为任务
      • 5. 定义带参数的Job类型
    • 五、总结

Go语言中定时任务Cron

Cron是一个强大的定时任务调度库,它允许开发者在Go应用中方便地设置和管理定时任务。Cron库通过解析Cron表达式,可以精确控制任务的执行时间和频率。本文将结合具体案例,详细介绍Cron在Go语言中的用法,包括安装、基本用法、Cron表达式的详解、高级用法以及实际应用案例。

一、Cron库的安装

在使用Cron库之前,需要先将其安装到Go开发环境中,项目中创建go mod文件,配置好代理。可以使用以下命令进行安装:

go get github.com/robfig/cron/v3

安装完成后,就可以在Go代码中导入Cron库并开始使用了。

二、Cron库的基本用法

Cron库的核心是使用Cron表达式来定义任务的执行时间和频率。Cron表达式由六个字段组成,分别表示秒、分、时、日、月、周几(0~6表示周日到周六)。

以下是一个简单的示例代码,展示如何使用Cron库创建一个每5秒钟执行一次的定时任务:

package mainimport ("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表达式由六个字段组成,每个字段用空格分隔,分别表示:

  1. 秒(0-59)
  2. 分(0-59)
  3. 时(0-23)
  4. 日(1-31)
  5. 月(1-12或JAN-DEC)
  6. 周几(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表达式中,*和"?"都是用来指定时间的通配符,但它们有一些区别:

"*":星号()可以用在所有字段上,表示该字段的任何值。例如,如果你想要在每分钟的每秒钟触发任务,你可以使用"*"在秒字段上。"?":问号(?)可以用在日和星期字段上,表示不指定值。不同于星号(*),问号不能用在其他字段上。当你在日字段上使用"?"时,意味着不关心那天是哪一天,只关心月份和星期字段。同理,在星期字段上使用"?"时,意味着不关心那天是星期几,只关心日字段和月份字段。

如果是使用 crontab := cron.New() 则只需要五个 * 。如 ***** 从分钟开始
如果使用cron.New()定义,却使用了6个* 运行将会报错
在这里插入图片描述

四、Cron库的高级用法

除了基本的AddFunc方法外,Cron库还提供了一些高级用法,如使用自定义的Job类型、动态调整任务配置、获取任务执行结果等。

1. 使用自定义的Job类型

Cron库允许使用自定义的Job类型,实现更加灵活的任务调度。以下是一个示例代码,展示如何使用自定义的Job类型:

package mainimport ("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表达式匹配时,就会执行MyJobRun方法。

2. 动态调整任务配置

Cron库允许在运行时动态调整任务的配置。以下是一个示例代码,展示如何动态添加、删除和更新定时任务:

package mainimport ("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)// 删除任务1c.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. 预定义时间格式

在这里插入图片描述

package mainimport ("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. 使用带参数的函数作为任务

如果我们需要在任务函数中使用参数,可以使用闭包或者定义一个带参数的函数类型。
使用闭包传递参数
闭包是一种捕获并存储其外部作用域的引用的函数。利用闭包,我们可以轻松地将参数传递给定时任务函数。

package mainimport ("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语句来阻塞主goroutineselect {}
}

在这里插入图片描述
在这个示例中,我们定义了一个名为executeTask的外部函数,它接受一个字符串参数并返回一个无参数的函数(即闭包)。
在闭包内部,我们打印了传递进来的参数。然后,我们将这个闭包作为任务函数添加到Cron实例中。

5. 定义带参数的Job类型

除了使用闭包外,我们还可以定义一个带参数的Job类型。这需要实现cron.Job接口,该接口包含一个Run方法。

package mainimport ("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语句来阻塞主goroutineselect {}
}

在这里插入图片描述

在这个示例中,我们定义了一个名为ParamJob的结构体类型,并为其添加了一个param字段来存储参数。然后,我们实现了cron.Job接口的Run方法,在该方法中打印了参数。最后,我们创建了一个ParamJob实例,并将其添加到Cron实例中。

需要注意的是,在调用AddJob方法时,我们需要将ParamJob实例的指针转换为cron.Job接口。这是因为AddJob方法期望的是一个实现了cron.Job接口的对象。

五、总结

Cron库是一个功能强大且易于使用的Go语言定时任务库。它提供了灵活的Cron表达式和易于使用的API,使开发者能够方便地添加和管理定时任务。通过本文的介绍和示例代码,我们了解了Cron库的基础用法、实际案例以及高级用法(如动态添加和移除任务、使用带参数的函数作为任务)。这些知识和技巧将帮助我们更好地在Go应用中使用Cron库来实现定时任务调度。

相关文章:

【Golang】Go语言中如何创建Cron定时任务

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

Android compose 重建流程1

前言 本文是笔者学习Compose是如何自动触发UI刷新的笔记,可能缺乏一定可读性和教导性.(建议阅读参考文献更具启发性) 使用以下BOM作为研究环境. composeBom "2024.04.01" androidx-compose-bom { group "androidx.compose", name "compose-bom…...

C++:模板(2)

目录 非类型模板参数 模板的特化 概念 函数模板特化 类模板特化 全特化 偏特化 模板的分离编译 分离编译的概念 模板的分离编译 ​编辑 模板总结 非类型模板参数 模板参数分为类型形参与非类型形参。 类型形参:在模板参数列表中,跟在class…...

Golang 并发编程:Context 包的使用与并发控制

文章目录 一、简介二、Context 的基本概念1. context 包常用函数 三、Context 的基本用法1. WithCancel:取消任务的上下文 四、超时控制:WithTimeout 和 WithDeadline1. 使用 WithTimeout 控制任务超时2. 使用 WithDeadline 设定截止时间 五、传递上下文…...

QGraphics类型学习使用【Qt】【C++】

QGraphics类型学习使用 需求过程全部完整代码 首先已知,QGraphicsView,QGraphicsScene, QGraphicsItem,分别称为:视图,场景,图元,图表就是各种各样的元素,图片元素,线条元…...

迁移学习和在线学习小结

迁移学习 英文小名: transform learning 简介: 把已经训练好的模型A为基本, 在新场景中, 根据新数据建立模型B 目的: 将某个领域或任务上学习到的知识/模式, 应用到不同但相关的领域/问题中 方法: 1.结构引用 适用情况: 新数据多, 场景相似度高, 可以基于原模型重新训练 2.特征…...

克里金插值(Kriging interpolation)

原理可参考该文件:克里金(Kriging)插值的原理与公式推导 - xg1990 matlab code可参考:Ordinary Kriging - File Exchange - MATLAB Central Some notes: 采用普通克里金时,采样的密度对结果影响非常大。若采样密度不够,误差会非…...

sealed class-kotlin中的封闭类

在 Kotlin 中,sealed class(密封类)是一种特殊的类,用于限制继承的类的数量。密封类可以被用来表示一组有限的类型,通常用于状态管理或表达多种可能的错误类型。 密封类用 sealed 关键字定义,这意味着只能…...

MongoDB Shell 基本命令(一)

MongoDB Shell 基本命令(一) 1. 基本概念 SQL术语/概念MongoDB术语/概念解释/说明databasedb数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins表连接,MongoDB不支持primary keyprimary key主键,Mon…...

Flink时间语义和时间窗口

前言 在实际的流计算业务场景中,我们会发现,数据和数据的计算往往都和时间具有相关性。 举几个例子: 直播间右上角通常会显示观看直播的人数,并且这个数字每隔一段时间就会更新一次,比如10秒。电商平台的商品列表&a…...

在wpf中登录成功之后怎么设置主页布局及点击不同的菜单跳转到不同的页面,这个是我们做wpf项目必要会的一个功能

通过frame与page实现在mvvm下的页面跳转 在wpf中登录成功之后怎么设置主页布局及点击不同的菜单跳转到不同的页面_哔哩哔哩_bilibili 1、MainWindow代码 <DockPanel><StackPanel DockPanel.Dock"Top" Height"40"><Grid><Grid.ColumnD…...

基于opencv的人脸闭眼识别疲劳监测

1. 项目简介 本项目旨在实现基于眼部特征的眨眼检测&#xff0c;通过监测眼睛开闭状态来计算眨眼次数&#xff0c;从而应用于疲劳监测、注意力检测等场景。使用了面部特征点检测算法&#xff0c;以及眼部特征比率&#xff08;EAR, Eye Aspect Ratio&#xff09;来判断眼睛的闭…...

aeo认证需要什么材料

AEO&#xff08;Authorized Economic Operator&#xff09;认证&#xff0c;即经认证的经营者认证&#xff0c;是企业信用管理体系的一种高级认证。申请AEO认证时&#xff0c;企业需要准备一系列的材料以证明其符合认证标准。以下是一份详细的AEO认证申请材料清单&#xff1a; …...

【iOS】YYModel

目录 什么是YYModel &#xff1f; 如何使用YYModel &#xff1f; 最简单的Model 与网络请求结合 属性为容器类的Model 白名单和黑名单 Model的嵌套 结语 什么是YYModel &#xff1f; YYModel是一个用于 iOS 和 macOS 开发的高性能的模型框架&#xff0c;主要用于对象和…...

Cadence元件A属性和B属性相互覆盖

最近在使用第三方插件集成到Cadence,协助导出BOM到平台上&#xff0c;方便对BOM进行管理和修改&#xff0c;结果因为属性A和属性B不相同&#xff0c;导致导出的BOM错误。如下图&#xff1a; ​​ 本来我们需要导出Q12&#xff0c;结果给我们导出了Q13&#xff0c;或者反之&…...

【火山引擎】语音合成 | HTTP接口 | 一次性合成 | python

目录 一 准备工作 二 HTTP接口(一次性合成-非流式) 1 接口说明 2 身份认证 3 请求方式 三 实践 四 注意事项 火山引擎语音合成TTS(Text-to-Speech)是一种基于云计算的语音合成服务,可以将文本转化为自然、流畅的语音。以下是火山引擎TTS的主要功能和特点: ①多种语音…...

YOLOv11改进-卷积-空间和通道重构卷积SCConv

本篇文章将介绍一个新的改进模块——SCConv&#xff08;小波空间和通道重构卷积&#xff09;&#xff0c;并阐述如何将其应用于YOLOv11中&#xff0c;显著提升模型性能。为了减少YOLOv11模型的空间和通道维度上的冗余&#xff0c;我们引入空间和通道重构卷积。首先&#xff0c;…...

记录一次从nacos配置信息泄露到redis写计划任务接管主机

经典c段打点开局。使用dddd做快速的打点发现某系统存在nacos权限绕过 有点怀疑是蜜罐&#xff0c;毕竟nacos这实在是有点经典 nacos利用 老规矩见面先上nacos利用工具打一波看看什么情况 弱口令nacos以及未授权访问&#xff0c;看这记录估计被光顾挺多次了啊 手动利用Nacos-…...

Unity加载界面制作

效果 UI部分 结构 说下思路: 因为是加载界面,所以最上层是一个Panel阻止所有的UI交互,这个Panel如果有图片就加一个图片,如果没有可以把透明度调到最大,颜色设为黑色. 下面最核心的就是一个进度条了,有图片的话,将进度条的底放进来,将进度条锚点设为下中,将滑动块的尺寸设为0.…...

最好的ppt模板网站是哪个?做PPT不可错过的18个网站!

现在有很多PPT模板网站&#xff0c;但真正免费且高质量的不多&#xff0c;今天我就分享主流的国内外PPT模板下载网站&#xff0c;并且会详细分析这些网站的优缺点&#xff0c;这些网站都是基于个人实际使用经验的&#xff0c;免费站点会特别标注&#xff0c;让你可以放心下载&a…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...