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

时间:2013-10-23 18:08:00

标签: cron go scheduled-tasks crontab ticker

我一直在寻找有关如何实现一个允许您在Go中的某个时间执行任务的函数的示例,但我找不到任何内容。

我自己实施了一个,我在答案中分享了它,所以其他人可以参考他们自己的实现。

6 个答案:

答案 0 :(得分:21)

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

  • 间隔期
  • 小时刻度
  • 分钟刻度
  • 秒嘀嗒

更新:(内存泄漏已修复)

import (
"fmt"
"time"
)

const INTERVAL_PERIOD time.Duration = 24 * time.Hour

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

type jobTicker struct {
    timer *time.Timer
}

func runningRoutine() {
    jobTicker := &jobTicker{}
    jobTicker.updateTimer()
    for {
        <-jobTicker.timer.C
        fmt.Println(time.Now(), "- just ticked")
        jobTicker.updateTimer()
    }
}

func (t *jobTicker) updateTimer() {
    nextTick := time.Date(time.Now().Year(), time.Now().Month(), 
    time.Now().Day(), HOUR_TO_TICK, MINUTE_TO_TICK, SECOND_TO_TICK, 0, time.Local)
    if !nextTick.After(time.Now()) {
        nextTick = nextTick.Add(INTERVAL_PERIOD)
    }
    fmt.Println(nextTick, "- next tick")
    diff := nextTick.Sub(time.Now())
    if t.timer == nil {
        t.timer = time.NewTimer(diff)
    } else {
        t.timer.Reset(diff)
    }
}

答案 1 :(得分:13)

@Daniele B提供的答案不够好,正如@Caleb所说,实施会泄漏内存,因为每次我们创建一个新的自动收报机时,旧的自动收报机将永远不会被释放。

所以我将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()
    }
}

答案 2 :(得分:9)

如果有人在寻找快速解决方案的问题。 我发现了一个整洁的库,可以很容易地安排工作。

链接:https://github.com/jasonlvhit/gocron

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()
}

答案 3 :(得分:2)

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

for (Map.Entry<String, Integer> me : set)

包裹链接:https://github.com/mileusna/crontab

答案 4 :(得分:0)

这是另一个常规实现。无需第三方库。

每天中午运行一次func

  • 期间:time.Hour * 24
  • 偏移量:time.Hour * 12

每天在03:40和16:40运行两次func

  • 期间:time.Hour * 12
  • 偏移量:time.Hour * 3 + time.Minute * 40
package main

import (
    "fmt"
    "time"
)

// Repeat calls function `f` with a period `d` offsetted by `o`.
func Repeat(d time.Duration, o time.Duration, f func(time.Time)) {
    next := time.Now().Truncate(d).Add(o)
    if next.Before(time.Now()) {
        next = next.Add(d)
    }

    t := time.NewTimer(next.Sub(time.Now()))

    for {
        v := <-t.C
        next = next.Add(d)
        t.Reset(next.Sub(time.Now()))
        f(v)
    }
}

答案 5 :(得分:0)

我正在使用 https://github.com/ehsaniara/gointerlock。分布式系统也支持它,并有一个内置的分发锁(Redis)

import (
    "context"
    "fmt"
    "github.com/ehsaniara/gointerlock"
    "log"
    "time"
)

var job = gointerlock.GoInterval{
    Interval: 2 * time.Second,
    Arg:      myJob,
}

err := job.Run(ctx)
if err != nil {
    log.Fatalf("Error: %s", err)
}

func myJob() {
    fmt.Println(time.Now(), " - called")
}