在实际开发过程中,我们有时候需要编写一些定时任务。当然我们可以使用crontab命令实现我们的需求。但是这种方法不满足一些定制化场景,同时会依赖具体的操作系统环境。

定时任务

golang中我们可以使用cron来实现我们定时任务的需求。他的使用方式非常简单,具体代码如下:

package main
import(
"fmt" cron "github.com/robfig/cron/v3"
) func main() {
crontab := cron.New()
task := func() {
fmt.Println("hello world")
}
// 添加定时任务, * * * * * 是 crontab,表示每分钟执行一次
crontab.AddFunc("* * * * *", task)
// 启动定时器
crontab.Start()
// 定时任务是另起协程执行的,这里使用 select 简答阻塞.实际开发中需要
// 根据实际情况进行控制
select {}
}

注:

  • New()函数支持多种初始化选项,比如cron.WithPanicLogger
  • 定时任务是另起协程执行的

上面就是 cron 的最简单使用示例,如果需要了解更加详细的用法,可以参考官方文档和示例。

自定义封装

在上述的使用方法基础上,基于我的实际需求,我对cron库进行了简单封装,主要为实现下面几个需求:

  • 管理所有的定时任务,需要记录定时任务的编号和相关信息
  • 停止一个定时任务
  • 支持添加函数类型和接口类型任务

话不多说,直接贴代码:

package main

import (
"fmt"
"sync" "github.com/pkg/errors"
cron "github.com/robfig/cron/v3"
) // Crontab crontab manager
type Crontab struct {
inner *cron.Cron
ids map[string]cron.EntryID
mutex sync.Mutex
} // NewCrontab new crontab
func NewCrontab() *Crontab {
return &Crontab{
inner: cron.New(),
ids: make(map[string]cron.EntryID),
}
} // IDs ...
func (c *Crontab) IDs() []string {
c.mutex.Lock()
defer c.mutex.Unlock()
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)
}
for _, id := range invalidIDs {
delete(c.ids, id)
}
return validIDs
} // Start start the crontab engine
func (c *Crontab) Start() {
c.inner.Start()
} // Stop stop the crontab engine
func (c *Crontab) Stop() {
c.inner.Stop()
} // DelByID remove one crontab task
func (c *Crontab) DelByID(id string) {
c.mutex.Lock()
defer c.mutex.Unlock() eid, ok := c.ids[id]
if !ok {
return
}
c.inner.Remove(eid)
delete(c.ids, id)
} // AddByID add one crontab task
// id is unique
// spec is the crontab expression
func (c *Crontab) AddByID(id string, 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] = eid
return nil
} // AddByFunc add function as crontab task
func (c *Crontab) AddByFunc(id string, 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] = eid
return nil
} // IsExists check the crontab task whether existed with job id
func (c *Crontab) IsExists(jid string) bool {
_, exist := c.ids[jid]
return exist
}

代码实现很简单,每个函数的作用都可以参考注释.下面简单实用一下上面的封装:

type testTask struct {
} func (t *testTask) Run() {
fmt.Println("hello world")
} func main() {
crontab := NewCrontab()
// 实现接口的方式添加定时任务
task := &testTask{}
if err := crontab.AddByID("1", "* * * * *", task); err != nil {
fmt.Printf("error to add crontab task:%s", err)
os.Exit(-1)
} // 添加函数作为定时任务
taskFunc := func() {
fmt.Println("hello world")
}
if err := crontab.AddByFunc("2", "* * * * *", taskFunc); err != nil {
fmt.Printf("error to add crontab task:%s", err)
os.Exit(-1)
}
crontab.Start()
select {} }

注:

  • task id 是唯一的,实际开发可以使用 uuid
  • 这个封装是并发安全的

不足:

  • 未支持初始化参数
  • 定时任务的错误采集,如果某个定时任务出错,应该能够获取到错误信息(这里指的是错误不是 panic)
  • panic 恢复操作可以参考 withChaincron.Recover

后记

下一篇详细解析 cron 的实现原理和更加复杂的用法

golang 实现定时任务的更多相关文章

  1. golang的定时任务

    golang的定时任务使用的是cron这个包来解决的 官方文档地址:https://godoc.org/github.com/robfig/cron cron包的基础知识 字段名 是否必须 允许的值 ...

  2. golang cronexpr定时任务包使用

    包获取 go get -u github.com/gorhill/cronexpr 创建一个定时任务 expr, err = cron.Parse("* * * * *"); 获得 ...

  3. Golang cron 定时任务使用

    1.cron 表达式的基本格式 用过 linux 的应该对 cron 有所了解.linux 中可以通过 crontab -e 来配置定时任务.不过,linux 中的 cron 只能精确到分钟.而我们这 ...

  4. Golang——Cron 定时任务

    开门见山写一个 package main import ( "fmt" "github.com/robfig/cron" "log" &qu ...

  5. cron表达式的双重人格:星期和数字到底如何对应?

    写在前面 cron在希腊语中是时间的意思,而cron表达式(cron expression)则是遵循特定规则,用于描述定时设置的字符串,常用于执行定时任务.本文总结了不同环境(如平台.库等)下,cro ...

  6. Golang 入门系列(八) cron定时任务

    1.cron 表达式的基本格式  Go 实现的cron 表达式的基本语法跟linux 中的 crontab基本是类似的.cron(计划任务),就是按照约定的时间,定时的执行特定的任务(job).cro ...

  7. Golang定时任务简单实现

    下载cron包: go get github.com/robfig/cron 开启一个定时: 根据cron表达式进行时间调度,cron可以精确到秒,大部分表达式格式也是从秒开始. c := cron. ...

  8. Go 定时任务

    本文基于Golang Crontab 实现了一个Crontab Job Manager.更加容易使用,同时也能够满足更加复杂的场景. 仓储地址, 如果有用,欢迎点赞,欢迎讨论,欢迎找茬. 需求 在开发 ...

  9. Golang mysql 上线的一个坑 Db.close重要性

    急冲冲完成的mysql的一个监控自动处理程序上线了,线下处理是正常的,没想到线上才半小时就奔溃了. 现在时间是晚上11点,心慌焦虑涌上心头,需要熬夜?肾上腺素激增. 程序主要是一个定时任务的处理程序, ...

随机推荐

  1. 嘉立创制作PCB流程

    现在做板子基本上是选择嘉立创和捷配,今天看一下嘉立创如何下PCB和STM贴片单,改天再写一下捷配的下单 我喜欢用下单助手,比较方便 注意需要把自己的板子的PCB文件用压缩软件生成压缩包文件,名字自己取 ...

  2. 利用Python进行数据分析【第二版】【高清中文版英文版源代码】

    如果被河蟹请回复我更新链接   这是我花钱弄的,免费分享给大家.没有密码,直接可以观看!   希望大家不要拿去后再做收费分享   如果好用,请给个赞好嘛~~~   1.中文pdf 链接:https:/ ...

  3. javascript 百度地图无秘钥(appkey)创建marker标记地图

    创建简单的marker地图不一定需要去百度地图申请key,简单代码实现marker地图,效果如图: html代码如下,代码中的baidu.api.js参考后面的隐藏代码: <!DOCTYPE h ...

  4. ARC093F Dark Horse 【容斥,状压dp】

    题目链接:gfoj 神仙计数题. 可以转化为求\(p_1,p_2,\ldots,p_{2^n}\),使得\(b_i=\min\limits_{j=2^i+1}^{2^{i+1}}p_j\)都不属于\( ...

  5. 38861cba61c66739c1452c3a71e39852.ttf net::ERR_ABORTED 404 (Not Found)

    error: http://localhost:63342/clappr-dev/js/38861cba61c66739c1452c3a71e39852.ttf net::ERR_ABORTED 40 ...

  6. Android中如何动态添加碎片

    Android中的开发需要兼容手机和平板,两个方面.这就引入了碎片的概念.(注意:这里用的Fragment强烈建议使用support-v4库中的Fragment) 碎片:是一种可以嵌入在活动当中的UI ...

  7. hdu1002 A + B Problem II[大数加法]

    目录 题目地址 题干 代码和解释 参考 题目地址 hdu1002 题干 代码和解释 由题意这是一个涉及到大数的加法问题.去看了一眼大数加法的方法感觉头很大,然后突然发现Java可以流氓解决大数问题,毅 ...

  8. 【CNN】--- 卷积过程中RGB与灰度的区别

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/hacker_Dem_br/article/ ...

  9. log4net 控制台和文件和数据库输出三种方式

    1.新建console应用项目SendEvaluateDataToProvinceConsole 2.选择SendEvaluateDataToProvinceConsole项目右键 选择 管理NuGe ...

  10. k8s 传参给docker env command、args和dockerfile中的entrypoint、cmd之间的关系

    [k8s]args指令案例-彻底理解docker entrypoint     需求: 搞个镜像,可以运行java -jar xxx.jar包,xxx.jar包名称要用参数传 思路1: 打对应运行ja ...