在实际开发过程中,我们有时候需要编写一些定时任务。当然我们可以使用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. PHP生成随机数;订单号唯一

    //8-12位随机数 function makeRand($num=){ $strand = (; if(strlen($strand)<$num){ $strand = str_pad($st ...

  2. SQL基础-汇总统计及GROUP BY

    一.汇总统计 1.聚集函数 COUNT() 计算总数 SUM() 求和 MAX() 最大值 MIN() 最小值 AVG() 平均值 2.聚集函数使用 总共有多少名学生? SELECT COUNT(*) ...

  3. ICEM-圆角正方体

    原视频下载地址:https://pan.baidu.com/s/1c2cNgJm 密码: rci8

  4. 配置docker阿里云加速器

    1. 安装/升级Docker客户端 推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce 2. 配置镜像加速器 针对Docker客户端版本大于 1.10.0 的用户 您可以通 ...

  5. GIT 使用记录,新手->会用(mac 用户)

    (唔,mac 用户这个要求是因为集成在 terminal 中可直接使用) 1. github 中 创建 git 账户 2. github -> 在个人设置中 找到 ssh  and GPGkey ...

  6. Python3之logging模块浅析

    Python3之logging模块浅析   目录 Python3之logging模块浅析 简单用法 日志与控制台同时输出 一个同时输出到屏幕.文件的完成例子 日志文件截取 日志重复打印问题解决 问题分 ...

  7. RSA前台加密后台解密

    RSA解密时BadPaddingException java rsa 解密报:javax.crypto.BadPaddingException: Decryption error Java安全架构__ ...

  8. el-cascader遇到一个坑的问题

    经仔细分析,如果二级和三级的value一样,就会出现这个问题.

  9. odoo开发笔记--一个模块显示两个一级菜单

    场景描述: 在已启动开发的模块中,odoo顶部一级菜单只有一个“会员管理”,需求是:在同一级顶部菜单,增加新菜单“产品管理”.举例如图:       处理方式: 按照odoo的机制,实现这种效果,可以 ...

  10. 搭建SpringCloud微服务

    建立spring父模块 删除不必要的src目录 父模块中的pom.xml中添加相应的依赖以及插件.远程仓库地址 <!-- 项目的打包类型, 即项目的发布形式, 默认为 jar. 对于聚合项目的父 ...