Golang:实现cron/在特定时间执行任务
我一直在寻找关于如何实现一个函数的示例,该函数允许您在Go中的某个特定时间执行任务,但我找不到任何东西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
我自己实现了一个,我在答案中分享了它,这样其他人就可以为自己的实现提供参考。这是一个通用实现,您可以设置:
- 间隔期
- 计时
- 分秒必争
- 倒数第二
导入(
“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)