Golang:实现cron/在特定时间执行任务

Golang:实现cron/在特定时间执行任务,cron,go,scheduled-tasks,crontab,ticker,Cron,Go,Scheduled Tasks,Crontab,Ticker,我一直在寻找关于如何实现一个函数的示例,该函数允许您在Go中的某个特定时间执行任务,但我找不到任何东西 我自己实现了一个,我在答案中分享了它,这样其他人就可以为自己的实现提供参考。这是一个通用实现,您可以设置: 间隔期 计时 分秒必争 倒数第二 更新:(内存泄漏已修复) 导入( “fmt” “时间” ) 常数间隔\周期时间。持续时间=24*时间。小时 常数小时到刻度int=23 常数分钟到刻度int=00 常数秒到刻度int=03 类型jobTicker结构{ 定时器*time.timer

我一直在寻找关于如何实现一个函数的示例,该函数允许您在Go中的某个特定时间执行任务,但我找不到任何东西


我自己实现了一个,我在答案中分享了它,这样其他人就可以为自己的实现提供参考。

这是一个通用实现,您可以设置:

  • 间隔期
  • 计时
  • 分秒必争
  • 倒数第二
更新:(内存泄漏已修复)

导入(
“fmt”
“时间”
)
常数间隔\周期时间。持续时间=24*时间。小时
常数小时到刻度int=23
常数分钟到刻度int=00
常数秒到刻度int=03
类型jobTicker结构{
定时器*time.timer
}
func运行例程(){
jobTicker:=&jobTicker{}
jobTicker.updateTimer()
为了{

以防有人偶然发现这个问题,寻求快速解决方案。 我发现了一个整洁的图书馆,可以让安排工作变得非常容易

链接:

API非常简单:

import (
    "fmt"
    "github.com/jasonlvhit/gocron"
)

func task() {
    fmt.Println("Task is being performed.")
}

func main() {
    s := gocron.NewScheduler()
    s.Every(2).Hours().Do(task)
    <- s.Start()
}
导入(
“fmt”
“github.com/jasonlvhit/gocron”
)
func任务(){
fmt.Println(“正在执行任务”)
}
func main(){
s:=gocron.NewScheduler()
s、 每(2)小时().Do(任务)

@danieleb提供的答案还不够好,正如@Caleb所说,这个实现会泄漏内存,因为每次我们创建一个新的ticker,旧的将永远不会被释放

因此,我包装了
time.timer
,并每次都重置它,例如:

package main

import (
    "fmt"
    "time"
)

const INTERVAL_PERIOD time.Duration = 24 * time.Hour

const HOUR_TO_TICK int = 23
const MINUTE_TO_TICK int = 21
const SECOND_TO_TICK int = 03

type jobTicker struct {
    t *time.Timer
}

func getNextTickDuration() time.Duration {
    now := time.Now()
    nextTick := time.Date(now.Year(), now.Month(), now.Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
    if nextTick.Before(now) {
        nextTick = nextTick.Add(INTERVAL_PERIOD)
    }
    return nextTick.Sub(time.Now())
}

func NewJobTicker() jobTicker {
    fmt.Println("new tick here")
    return jobTicker{time.NewTimer(getNextTickDuration())}
}

func (jt jobTicker) updateJobTicker() {
    fmt.Println("next tick here")
    jt.t.Reset(getNextTickDuration())
}

func main() {
    jt := NewJobTicker()
    for {
        <-jt.t.C
        fmt.Println(time.Now(), "- just ticked")
        jt.updateJobTicker()
    }
}
主程序包
进口(
“fmt”
“时间”
)
常数间隔\周期时间。持续时间=24*时间。小时
常数小时到刻度int=23
常数分钟到刻度int=21
常数秒到刻度int=03
类型jobTicker结构{
时间计时器
}
func getnextitckduration()time.Duration{
现在:=时间。现在()
nextTick:=time.Date(now.Year(),now.Month(),now.Day(),小时到刻度,分钟到刻度,秒到刻度,0,time.Local)
如果下一次检查之前(现在){
nextTick=nextTick.Add(间隔时间)
}
返回nextTick.Sub(time.Now())
}
func NewJobTicker()jobTicker{
fmt.Println(“此处新勾选”)
返回jobTicker{time.NewTimer(getNextTickDuration())}
}
func(jt jobTicker)updatejobicker(){
fmt.Println(“此处下一个勾号”)
jt.t.Reset(getnextitckduration())
}
func main(){
jt:=NewJobTicker()
为了{

如果您熟悉crontab语法,我已经创建了一个支持crontab语法的包,例如:

ctab := crontab.New()
ctab.AddJob("*/5 * * * *", myFunc)
ctab.AddJob("0 0 * * *", myFunc2)

包链接:

这是另一个不需要第三方库的通用实现

免责声明:此实现与兼容。要管理时区,必须对其进行修改。

每天中午运行一次
func

  • 时段:
    time.Hour*24
  • 偏移量:
    time.Hour*12
每天在03:40(00:00+03:40)和15:40(12:00+03:40)运行两次
func

  • 时段:
    time.Hour*12
  • 偏移量:
    time.Hour*3+time.Minute*40
更新(2020-01-28): 变化:

  • context.context
    可用于取消,使其可测试
  • time.Ticker
    无需计算下一次执行的时间
主程序包
进口(
“上下文”
“时间”
)
//调度调用函数'f',其句点'p'被'o'抵消。
func计划(ctx context.context,p time.Duration,o time.Duration,f func(time.time)){
//定位第一次执行
first:=time.Now().Truncate(p).Add(o)
if first.Before(time.Now()){
第一个=第一个。添加(p)
}
firstC:=time.After(first.Sub(time.Now()))
//从零信道块接收数据
t:=&time.Ticker{C:nil}
为了{
挑选{

案例五:=此实现存在内存泄漏。>停止ticker以释放相关资源。@Caleb是对的,每次我们创建一个新的ticker,旧的将永远不会被释放。更好的解决方案是:@Caleb,谢谢!请随时更新答案上的代码,以修复泄漏。它不是被垃圾收集了吗?这不处理NTP时钟调整好吧…一个每日行情器有时会触发两次。无耻的插件:也许你可以看看这个:极简主义cron go软件包:github.com/roylee0704/gron这真是太好了!创建这个软件包的Thx:)
ctab := crontab.New()
ctab.AddJob("*/5 * * * *", myFunc)
ctab.AddJob("0 0 * * *", myFunc2)