Go 学习笔记(77)— Go 第三方库之 cronexpr(解析 crontab 表达式,定时任务)
cronexpr
支持的比 Linux
自身的 crontab
更详细,可以精确到秒级别。
1. 实现方式
cronexpr
表达式从前到后的顺序如下所示:
字段类型 是否为必须字段 允许的值 允许的特殊字符
---------- ---------- -------------- --------------------------
Seconds No 0-59 * / , -
Minutes Yes 0-59 * / , -
Hours Yes 0-23 * / , -
Day of month Yes 1-31 * / , - L W
Month Yes 1-12 or JAN-DEC * / , -
Day of week Yes 0-6 or SUN-SAT * / , - L #
Year No 1970–2099 * / , -
我们定义第 0 个字段为 Seconds
,第 1 个字段为 Minutes
,各个字段的含义如下:
*
星号表示cron
表达式与该字段的所有值匹配。例如,在第四个字段(月)中使用星号表示每个月;/
斜线描述在该时间段的间隔。例如,分钟字段中的3-59/15
表示每小时的第三分钟,此后每15分钟。*/...
的形式相当于first-last/...
的形式,即在该字段的最大可能范围内的增量;,
逗号用于分隔列表中的项目。例如,在第 5 个字段(星期)中使用MON,WED,FRI
表示星期一、星期三和星期五;-
连字符定义范围。例如,2000-2010
表示公元 2000 年至 2010 年之间的每一年,包括在内,为闭区间;L
代表 “最后”。当在周天字段中使用时,它允许你指定诸如 “最后一个星期五”(5L
)这样的结构。在月日字段中,它指定了该月的最后一天;W
月日字段允许使用W
字符。这个字符用于指定离给定日期最近的工作日(周一至周五)。举个例子,如果你指定15W
作为月日字段的值,其含义是:“离本月 15 日最近的工作日”。所以,如果 15 号是星期六,触发器在 14 号星期五启动。如果 15 号是星期天,触发器在 16 号星期一启动。如果 15 号是星期二,那么它就在 15 号星期二触发。但是,如果你指定1W
作为月日的值,并且 1 号是星期六,那么触发器在 3 号星期一发射,因为它不会 "跳过 "一个月的天数边界。只有当月日是一个单一的日子,而不是一个范围或日期列表时,才能指定
W
字符。W
字符也可以与L
结合使用,如LW
表示 “本月的最后一个工作日”。#
允许在星期字段中使用#
,后面必须有一个 1 到 5 之间的数字。它允许你指定一些结构,如某个月的 “第二个星期五”。
2. 示例说明
Entry Description Equivalent to
@annually Run once a year at midnight in the morning of January 1 0 0 0 1 1 * *
@yearly Run once a year at midnight in the morning of January 1 0 0 0 1 1 * *
@monthly Run once a month at midnight in the morning of the first of the month 0 0 0 1 * * *
@weekly Run once a week at midnight in the morning of Sunday 0 0 0 * * 0 *
@daily Run once a day at midnight 0 0 0 * * * *
@hourly Run once an hour at the beginning of the hour 0 0 * * * * *
@reboot Not supported
3. 细节说明
- 如果只有六个字段,则会预加一个 0 秒字段,即
* * * * * 2013
在内部成为0 * * * * 2013
; - 如果只有五个字段,则预设 0 秒字段,并附加一个通配符年份字段,即
* * * * Mon
内部成为0 * * * Mon *
; - 星期字段的域是
[0-7]
,而不是[0-6]
,7 是星期天(像0)。这是为了符合http://linux.die.net/man/5/crontab#; - 如果提供了一个错误的cron表达式,代码的行为是不确定的;
4. 安装方式
go get github.com/gorhill/cronexpr
5. 重要函数
5.1 cronexpr.Parse
expr, err := cronexpr.Parse("*/5 * * * * * * ") // 如果表达式解析错误将返回一个错误
5.2 cronexpr.MustParse
expr = cronexpr.MustParse("*/5 * * * * * * ") // 如果表达式解析错误将直接抛出 panic
6. 代码实现
6.1 简单示例
package mainimport ("fmt""time""github.com/gorhill/cronexpr"
)func doTask() {fmt.Println("I am running, time is: ", time.Now())
}
func main() {// 每隔 5 秒执行1次expr, err := cronexpr.Parse("*/5 * * * * * * ") // 如果表达式解析错误将返回一个错误if err != nil {fmt.Println(err)return}nextTime := expr.Next(time.Now())fmt.Println(nextTime)time.AfterFunc(time.Until(nextTime), doTask)time.Sleep(10 * time.Second)}
6.2 监控任务和执行任务处于不同的协程
package mainimport ("fmt""time""github.com/gorhill/cronexpr"
)// 代表一个任务
type CronJob struct {expr *cronexpr.ExpressionnextTime time.Time // expr.Next(now)
}func main() {// 定时任务字典, key: 任务的名字, value 任务对象scheduleTable := make(map[string]*CronJob)now := time.Now()// 定义定时任务以每 5s 执行一次// MustParse 如果遇到解析 contab 错误时会直接抛出 panic ,不会像 Parse 一样返回一个错误expr := cronexpr.MustParse("*/5 * * * * * *")cronJob := &CronJob{expr: expr,nextTime: expr.Next(now),}// 任务注册到调度表scheduleTable["job1"] = cronJob// 定义定时任务以每 3s 执行一次expr = cronexpr.MustParse("*/3 * * * * * *")cronJob = &CronJob{expr: expr,nextTime: expr.Next(now),}// 任务注册到调度表scheduleTable["job2"] = cronJob// 定时检查一下任务调度表for {now := time.Now()for jobName, cronJob := range scheduleTable {// 判断是否到期,当前时间等于定时任务的下次执行时间,或者当前时间大于任务的定时时间if now.Equal(cronJob.nextTime) || now.After(cronJob.nextTime) {// 启动一个协程, 执行这个任务go func(jobName string) {fmt.Println("执行:", jobName)}(jobName)// 计算下一次调度时间cronJob.nextTime = cronJob.expr.Next(now)fmt.Println(jobName, "下次执行时间:", cronJob.nextTime)}}// 等待 1s,减少 CPU 消耗t := <-time.NewTimer(1 * time.Second).Cfmt.Println(t)}}
Go 学习笔记(77)— Go 第三方库之 cronexpr(解析 crontab 表达式,定时任务)相关推荐
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...
- python3第三方库手册_python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑...
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件? 当我们点开下载页时, 一 ...
- python学习笔记项目_python第三方库之Django学习笔记一
1.安装Django pip install Django 2.版本号查询 python -m django --version 3.创建项目 切换到你想创建项目的目录,执行命令:django-adm ...
- STM32CUBEMX入门学习笔记3:HAL库以及STM32CUBE相关资料
STM32CUBEMX入门学习笔记3:HAL库以及STM32CUBE相关资料 微雪课堂:http://www.waveshare.net/study/article-629-1.html 之前的正点原 ...
- Makefile学习笔记07|编译静态库并通过ifeq语句
Makefile学习笔记07|编译静态库并通过ifeq语句 希望看到这篇文章的朋友能在评论区留下宝贵的建议来让我们共同成长,谢谢. 这里是目录 本篇与上一篇有较多联系,有兴趣的可以先看上一 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- Python学习笔记:列表、字典与集合解析(List, Dict and Set Comprehensions)
Python学习笔记:列表.字典与集合解析(List, Dict and Set Comprehensions) 1.列表解析 最受喜爱的Python语言特性.过滤一个集合的元素生成一个新的列表. 一 ...
- Python学习笔记:常用第三方模块3
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:常用第三方模块(1)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python3 爬虫学习笔记 C01 【基本库 urllib 的使用】
Python3 爬虫学习笔记第一章 -- [基本库 urllib 的使用] 文章目录 [1.1] urllib 简介 [1.2] urllib.request 发送请求 [1.2.1] urllib. ...
最新文章
- hibernate 第三天
- xgboost 正则项_XGBoost入门系列第一讲
- R语言编写自定义分组统计函数(customize statistics function)可视化分组箱图并在X轴标签下方添加分组对应的统计值(样本数N、中位数median、四分位数的间距iqr)
- 性能测试场景设计之用户模式设置
- Coursera-AndrewNg(吴恩达)机器学习笔记——第四周编程作业(多分类与神经网络)...
- WP7 开发(九) WP7控件开发(六)-DeepZoom技术
- Google 地图 API 参考
- JS如何控制checkbox的全选反选
- [New Portal]Windows Azure Virtual Machine (17) Virtual Machine成本分析
- mysql读写分离 同步_MySQL数据库的同步配置+MySql读写分离
- class layout basic 2
- BZOJ5232[Lydsy2017省队十连测] 好题
- MSN Message协议分析
- html5 页面刷新的代码,js刷新当前页面的代码
- 易语言php验证码识别,易语言自动打码验证码服务端带案例
- DeepFool公式理解
- html代码打猎小游戏,html贪吃蛇小游戏课件-附源代码
- java集合源码分析
- 想要刚毕业就月入过万必须要懂这些面试题(Vue 篇)
- Git私服客户端免密码登录