我一直在寻找有关如何实现一个允许您在Go中的某个时间执行任务的函数的示例,但我找不到任何内容。
我自己实施了一个,我在答案中分享了它,所以其他人可以参考他们自己的实现。
答案 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)
所以我将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)
答案 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")
}