【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库来实现定时任务调度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/57423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

拼三角问题

欢迎来到杀马特的主页:羑悻的小杀马特.-CSDN博客 目录 一题目: 二思路: 三解答代码: 一题目: 题目链接: 登录—专业IT笔试面试备考平台_牛客网 二思路: 思路:首先明白能组成三角形…

【Next.js 项目实战系列】07-分配 Issue 给用户

原文链接 CSDN 的排版/样式可能有问题,去我的博客查看原文系列吧,觉得有用的话,给我的库点个star,关注一下吧 上一篇【Next.js 项目实战系列】06-身份验证 分配 Issue 给用户 本节代码链接 Select Button​ # /app/issues/[i…

几何算法系列:空间实体体积计算公式推导

1.前言 面积和体积的计算是常见和基础的几何算法话题,面积和体积通常作为面或构件的基本信息参与相关的建模、计算、分析等过程。 有关面积的计算,可以参考博主此前的文章, 一种误差较小的轮廓面积计算算法_轮廓面积计算原理-CSDN博客文章…

设计模式——装饰者模式(8)

一、定义 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。我们先来看一个快餐店的例子。快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额…

arp代答观察

文章目录 代答和代理简述实验前提先不开启proxy代答的配置开启代答总结 代答和代理简述 ARP(地址解析协议)是在局域网中用于将IP地址映射到MAC地址的协议。在理解 ARP 代答和 ARP 代理之前,让我们先澄清一下 ARP 的基本工作原理。 ARP 代答&…

在 VS Code 中轻松绘图:Draw.io Integration 插件详解

文章目录 在 VS Code 中轻松绘图:Draw.io Integration 插件详解一、什么是 Draw.io Integration 插件?二、插件安装指南1. 安装步骤2. 配置插件 三、如何使用 Draw.io Integration 插件?1. 创建新绘图文件2. 编辑现有图表3. 常用功能与技巧 四…

中小型医院网站:Spring Boot框架详解

5 系统实现 5.1 用户功能模块的实现 用户进入本系统可查看系统信息,包括首页、门诊信息、药库信息以及系统公告信息等,系统前台主界面展示如图5-1所示。 图5-1系统前台主界面图 5.1.1用户登录界面 用户要想实现预约挂号功能,必须登录系统&a…

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

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

k8s部署Kafka集群超详细讲解

准备部署环境 Kubernetes集群信息 NAMEVERSIONk8s-masterv1.29.2k8s-node01v1.29.2k8s-node02v1.29.2 Kafka:3.7.1版本,apche版本 Zookeeper:3.6.3版本 准备StorageClass # kubectl get sc NAME PROVISIONER RECLA…

股价创52周新高,云顶新耀成为“黑马”的启示录

踏入2024年以来,创新药产业持续释放积极信号。今年本土创新药出海交易额已超200亿美元,最近医保续约和谈判也有望促进国内创新药长期放量。 市场预期转好之下,生物医药板块在新一轮牛市中进入了估值修复的阶段。HSHKBIO(恒生香港…

【LVGL快速入门(二)】LVGL开源框架入门教程之框架使用(UI界面设计)

零.前置篇章 本篇前置文章为【LVGL快速入门(一)】LVGL开源框架入门教程之框架移植 一.UI设计 介绍使用之前,我们要学习一款LVGL官方的UI设计工具SquareLine Studio,使用图形化设计方式设计出我们想要的界面,然后生成对应源文件导入工程使用…

时空智友企业流程化管控系统uploadStudioFile接口存在任意文件上传漏洞

免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 时空智友…

JMeter使用不同方式传递接口参数

1、使用 HTTP 请求中的参数: 在 JMeter 的测试计划中,添加一个 "HTTP 请求" 元件。 在 "HTTP 请求" 元件的参数化选项中,可以添加参数的名称和值。可以手动输入参数,也可以使用变量来传递参数值。 如果要使…

汇川机器人与PLC通信-ModbusTCP超详细案例

#SCARA机器人与H5UPLC通过ModbusTCP通信,HMI界面手动操作# 应用背景: 本项目案例部分软件界面已被更新,如机器人示教软件旧版本S01.19R03。但通信的原理基本一致,废话少说,我们直接上图。 一、PLC端配置 1.添加ROB通讯表(自定义),变量表内容包括ROB系统变量,IN区和…

Notepad++将搜索内容所在行选中,并进行复制等操作

背景 Notepad在非常多的数据行内容中,按照指定内容检索,并定位到具体行,而后对内容行的数据进行复制、剪切、删除等处理动作。 操作说明 检索并标记所在行 弹出搜索框:按下 Ctrl F。 输入查找字符串:在搜索框中输入要…

Cursor零基础小白教程系列「进阶」 - Cursor 智能代码补全详解(Tab)

最适合小白零基础的Cursor教程 网站lookai.top相同作者,最新文章会在网站更新,欢迎收藏书签 Cursor 智能代码补全详解(Tab) 概述 Cursor的智能代码补全,也就是快捷键Tab,是其最强大和独特的AI辅助编程工具之一。本教程将详细介绍…

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

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

抗肺癌市场迎新突破,十款创新药物获批!

在肺癌治疗领域,近年来取得了令人瞩目的进展。随着科学技术的不断进步和临床研究的深入,多款创新肺癌药物相继获批上市,为患者带来了前所未有的治疗选择和希望。本文将详细介绍十款最新获批的肺癌创新药物,探讨它们的特点、适应症…

Leetcode 1135. 最低成本连通所有城市

1.题目基本信息 1.1.题目描述 想象一下你是个城市基建规划者,地图上有 n 座城市,它们按以 1 到 n 的次序编号。 给你整数 n 和一个数组 conections,其中 connections[i] [x_i, y_i, cost_i] 表示将城市 x_i 和城市 y_i 连接所要的cost_i&…

Stable Diffusion Web UI 大白话术语解释 (二)

归纳整理,Stable Diffusion Web UI 使用过程中,相关术语 ControlNet ControlNet 说简单点,就是你可以给 AI 一些“规则”,比如让它根据某些线条、结构或者骨架去画图。 这样能让 AI 画出更符合你要求的图片,特别适合画…