Go语言封装Cron定时任务

Go语言封装Cron定时任务

  • 介绍
  • 目标
  • 项目背景
  • 代码分析
    • 代码实现
    • 主要功能
  • Cron表达式解析
    • 例子
  • 使用示例
  • 总结

介绍

在现代应用中,定时任务是非常常见的需求,无论是用于定时清理数据、定时发送邮件,还是定时执行系统维护任务。Go语言作为一门现代编程语言,提供了多种方法来实现定时任务。本文将重点介绍如何在Go中封装一个Cron定时任务管理器,帮助开发者高效管理定时任务。

目标

我们将通过使用 github.com/robfig/cron/v3 库来实现一个简洁、灵活的定时任务调度器。该库支持基于 Cron 表达式的任务调度,我们将基于该库封装出一个简单的 API,供开发者在实际项目中使用。

项目背景

Cron 表达式是一种用来表示时间计划的格式,它通常由 5 或 6 个字段组成,表示一个特定的时间点或时间间隔。Go中的 robfig/cron 库提供了非常便利的接口来处理这些表达式,并能够定期执行任务。

我们的目标是封装一个 Crontab 结构体,它将管理所有的定时任务,支持任务的添加、删除、查询以及启动和停止功能。

代码分析

下面是一个简单的 Cron 定时任务调度器的封装代码。它基于 robfig/cron 库并扩展了一个 Crontab 结构体,提供了一些常用的操作方法。

代码实现

package crontabimport ("github.com/pkg/errors"cron "github.com/robfig/cron/v3""sync"
)// Crontab crontab struct
type Crontab struct {inner *cron.Cronids   map[string]cron.EntryIDmutex *sync.RWMutex
}// NewCrontab new crontab
func NewCrontab() *Crontab {return &Crontab{inner: cron.New(cron.WithSeconds()), // 支持秒级别的Cron表达式ids:   make(map[string]cron.EntryID),mutex: new(sync.RWMutex),}
}// IDs 获取所有有效的Cron任务ID
func (c *Crontab) IDs() []string {c.mutex.RLock()defer c.mutex.RUnlock()validIDs := make([]string, 0, len(c.ids))invalidIDs := make([]string, 0)for sid, eid := range c.ids {if e := c.inner.Entry(eid); e.ID != eid {invalidIDs = append(invalidIDs, sid)continue}validIDs = append(validIDs, sid)}// 清理无效的任务IDfor _, id := range invalidIDs {delete(c.ids, id)}return validIDs
}// Start 启动定时任务调度器
func (c *Crontab) Start() {c.inner.Start()
}// Stop 停止定时任务调度器
func (c *Crontab) Stop() {c.inner.Stop()
}// DelByID 根据ID删除定时任务
func (c *Crontab) DelByID(id string) error {c.mutex.Lock()defer c.mutex.Unlock()eid, ok := c.ids[id]if !ok {return errors.Errorf("crontab id not exists!")}c.inner.Remove(eid)delete(c.ids, id)return nil
}// AddByID 根据ID添加定时任务
// spec 是Cron表达式,cmd 是执行的任务
func (c *Crontab) AddByID(id, spec string, cmd cron.Job) error {c.mutex.Lock()defer c.mutex.Unlock()if _, ok := c.ids[id]; ok {return errors.Errorf("crontab id exists!")}eid, err := c.inner.AddJob(spec, cmd)if err != nil {return err}c.ids[id] = eidreturn nil
}// AddByFunc 根据ID添加函数作为定时任务
func (c *Crontab) AddByFunc(id, spec string, f func()) error {c.mutex.Lock()defer c.mutex.Unlock()if _, ok := c.ids[id]; ok {return errors.Errorf("crontab id exists!")}eid, err := c.inner.AddFunc(spec, f)if err != nil {return err}c.ids[id] = eidreturn nil
}// IsExists 判断某个任务ID是否已存在
func (c *Crontab) IsExists(jid string) bool {c.mutex.RLock()defer c.mutex.RUnlock()_, exist := c.ids[jid]return exist
}

主要功能

  • NewCrontab(): 初始化一个新的 Crontab 实例,内部使用 cron.New() 来创建一个 Cron 调度器,支持秒级别的 Cron 表达式。

  • IDs(): 获取当前所有有效的定时任务ID。会清理掉无效的任务ID。

  • Start(): 启动 Cron 调度器,开始执行所有的定时任务。

  • Stop(): 停止 Cron 调度器,暂停定时任务的执行。

  • DelByID(id): 根据任务ID删除定时任务。

  • AddByID(id, spec, cmd): 根据 Cron 表达式添加一个新的定时任务。任务ID必须唯一。

  • AddByFunc(id, spec, f): 将一个函数作为定时任务来添加,使用 Cron 表达式来指定执行频率。

  • IsExists(jid): 判断某个定时任务ID是否存在。

Cron表达式解析

Cron 表达式是定时任务调度中常见的表示方式,它由五个或六个字段组成,每个字段代表一个时间单位。标准的 Cron 表达式格式如下:

* * * * * *
│ │ │ │ │ │
│ │ │ │ │ └─ 星期几 (0 - 7) (0或7代表星期天)
│ │ │ │ └──── 月份 (1 - 12)
│ │ │ └────── 日 (1 - 31)
│ │ └──────── 小时 (0 - 23)
│ └────────── 分钟 (0 - 59)
└──────────── 秒 (0 - 59)

例子

* * * * * *:每秒执行一次任务
0 * * * * *:每分钟的第0秒执行一次任务
0 0 * * * *:每天午夜执行一次任务
0 0 1 * * *:每月的第一天执行一次任务

使用示例

以下是如何使用封装好的 Crontab 类型来管理定时任务的示例:

package mainimport ("fmt""github.com/robfig/cron/v3""time""your_project/crontab"
)func main() {// 创建一个新的 Crontab 实例c := crontab.NewCrontab()// 定义一个定时任务task := func() {fmt.Println("Task executed at", time.Now())}// 添加定时任务err := c.AddByFunc("task1", "*/5 * * * * *", task) // 每5秒执行一次if err != nil {fmt.Println("Error adding task:", err)return}// 启动任务调度器c.Start()// 等待一段时间后停止time.Sleep(20 * time.Second)c.Stop()// 删除任务err = c.DelByID("task1")if err != nil {fmt.Println("Error deleting task:", err)}
}

总结

通过使用 robfig/cron 库并封装成一个简单易用的 Crontab 类型,我们可以非常方便地在 Go 项目中管理定时任务。Cron 表达式为我们提供了灵活的时间配置,帮助开发者应对复杂的定时任务调度需求。

在实际应用中,我们可以根据需要扩展 Crontab 类型,支持更多功能,如任务状态监控、任务重试等,进一步提高定时任务管理的效率。

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

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

相关文章

3.4 stm32系列:定时器(PWM、定时中断)

一、定时器概述 1.1 软件定时原理 使用纯软件(CPU死等)的方式实现定时(延时)功能; 不精准的延迟: /* 微秒级延迟函数* 不精准* stm32存在压出栈过程需要消耗时间* 存在流水线,执行时间不确定…

28、论文阅读:基于像素分布重映射和多先验Retinex变分模型的水下图像增强

A Pixel Distribution Remapping and Multi-Prior Retinex Variational Model for Underwater Image Enhancement 摘要介绍相关工作基于模型的水下图像增强方法:无模型水下图像增强方法:基于深度学习的水下图像增强方法: 论文方法概述像素分布…

【路径规划】原理及实现

路径规划(Path Planning)是指在给定地图、起始点和目标点的情况下,确定应该采取的最佳路径。常见的路径规划算法包括A* 算法、Dijkstra 算法、RRT(Rapidly-exploring Random Tree)等。 目录 一.A* 1.算法原理 2.实…

java web springboot

0. 引言 SpringBoot对Spring的改善和优化,它基于约定优于配置的思想,提供了大量的默认配置和实现 使用SpringBoot之后,程序员只需按照它规定的方式去进行程序代码的开发即可,而无需再去编写一堆复杂的配置 SpringBoot的主要功能…

transformer用作分类任务

系列博客目录 文章目录 系列博客目录1、在手写数字图像这个数据集上进行分类1. 数据准备2. 将图像转化为适合Transformer的输入3. 位置编码4. Transformer编码器5. 池化操作6. 分类头7. 训练8. 评估总结流程:相关模型: 1、在手写数字图像这个数据集上进行…

实验四 综合数据流处理-Storm (单机和集群配置部分)

1.前期准备 (1)把docker和docker-compose给下载好 参考:基于docker-compose来搭建zookeeper集群-CSDN博客(注意对于这篇文章下面配置zookeeper的内容,可以直接跳过,因为我们只需要看最上面下载docker-com…

前端开发 之 12个鼠标交互特效下【附完整源码】

前端开发 之 12个鼠标交互特效下【附完整源码】 文章目录 前端开发 之 12个鼠标交互特效下【附完整源码】七:粒子烟花绽放特效1.效果展示2.HTML完整代码 八:彩球释放特效1.效果展示2.HTML完整代码 九:雨滴掉落特效1.效果展示2.HTML完整代码 十…

ChatGPT与领域特定语言的集成

用ChatGPT做软件测试 领域特定语言(Domain-Specific Language,DSL)是一种编程语言,专门设计用于满足特定领域或问题领域的需求。它是一种定制的语言,通常包括特定领域的专业术语以及相应的语法规则。DSL的设计旨在让领…

linux系统编程(六)

1、线程 一个进程可以包含多个线程,同一程序中的所有线程会独立执行相同的程序,共享同一份全局内存区域(初始化数据段、未初始化数据段、堆)。 同样是执行并行任务,用子进程会有一些限制,比如&#xff1a…

Java设计模式 —— 【结构型模式】外观模式详解

文章目录 概述结构案例实现优缺点 概述 外观模式又名门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这…

基于Springboot + vue实现的汽车资讯网站

🥂(❁◡❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞 💖📕🎉🔥 支持我:点赞👍收藏⭐️留言📝欢迎留言讨论 🔥🔥&…

Html:点击图标链接发起QQ临时会话

我们在做前端开发的时候&#xff0c;会遇到用户需要点击一个图标可以发起QQ临时会话&#xff0c;这样不用添加好友也能沟通的&#xff0c;那我们就来看看如何实现这个功能&#xff1a; <a href"http://wpa.qq.com/msgrd?v3&uin你的QQ号码&siteqq&menuyes…

【后端面试总结】MySQL主从复制逻辑的技术介绍

MySQL主从复制逻辑的技术介绍 1. 基本概念 MySQL主从复制是一种数据库复制技术&#xff0c;用于将一个数据库服务器&#xff08;主服务器&#xff0c;Master&#xff09;上的数据更改同步到一个或多个其他数据库服务器&#xff08;从服务器&#xff0c;Slave&#xff09;上。…

echarts画风向杆

1.安装echarts 2.引入echarts 4.获取数据&#xff0c;转换数据格式 windProfile.title.text ${moment(time.searchTime[0], ‘YYYY-MM-DD HH:mm:ss’).format( ‘YYYY-MM-DD HH:mm’ )}-${moment(time.searchTime[1], ‘YYYY-MM-DD HH:mm:ss’).format(‘YYYY-MM-DD HH:mm’)…

Linux系统编程——理解系统内核中的信号捕获

目录 一、sigaction() 使用 信号捕捉技巧 二、可重入函数 三、volatile关键字 四、SIGCHLD信号 在信号这一篇中我们已经学习到了一种信号捕捉的调用接口&#xff1a;signal(),为了深入理解操作系统内核中的信号捕获机制&#xff0c;我们今天再来看一个接口&#xff1a;si…

HTTP、HTTPS和SOCKS5代理協議

一、HTTP代理協議 HTTP代理是最基礎、使用最廣泛的代理協議之一。它主要用於處理HTTP協議的數據請求&#xff0c;即流覽網頁時的數據傳輸。HTTP代理的工作原理相對簡單&#xff1a;當用戶向網站發送請求時&#xff0c;HTTP代理伺服器首先接收該請求&#xff0c;然後將其轉發給…

IEC104 协议 | 规约帧格式 / 规约调试

注&#xff1a;本文为 “ IEC104 协议” 相关文章合辑。 未整理去重&#xff0c;如有内容异常请看原文。 图片清晰度限于引文原状。 从零开始理解 IEC104 协议之一 ——104 规约帧格式 洪城小电工 IP 属地&#xff1a;江西 2020.06.10 00:30:54 前言 本文根据相关标准、本…

代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

贪心没有套路&#xff0c;说白了就是常识性推导加上举反例 今天的内容比较简单 简单了解贪心是通过局部最优解反推全局最优解&#xff08;有经验成分&#xff09; 455.分发饼干 题目链接&#xff1a;455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09; 讲解链接&#xff…

WPS如何快速将数字金额批量转换成中文大写金额,其实非常简单

大家好&#xff0c;我是小鱼。 在日常的工作中经常会遇到需要使用金额大写的情况&#xff0c;比如说签订业务合同时一般都会标注大写金额&#xff0c;这样是为了安全和防止串改。但是很多人也许不太熟悉金额大写的方法和习惯&#xff0c;其它没有关系&#xff0c;我们在用WPS制…

Vue3之Pinia

在前端开发中&#xff0c;随着应用程序的规模和复杂性增加&#xff0c;状态管理成为了不可或缺的一部分。Pinia作为Vue 3的专属状态管理库&#xff0c;以其轻量级、易用性和灵活性&#xff0c;逐渐成为了Vue开发者的新宠。本文将详细介绍Pinia的基本概念、功能特点、应用场景、…