Go 定时任务

Go 实现定时任务有多种方式,每种方式都有其适用的场景。下面是一些常见的实现方法:

1、使用 time.Ticker

time.Tickertime 包提供的一个结构体,它会在一个指定的时间间隔重复执行某个任务。有两种使用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"fmt"
"time"
)

func main() {
ticker := time.NewTicker(2 * time.Second) // 创建一个每2秒触发一次的Ticker
defer ticker.Stop() // 确保在main函数结束时停止Ticker

done := make(chan bool) // 创建一个传递结束标志的 chan

// 由于ticker.Stop()内部不会关闭chan,故使用 for range 会内存泄露
// 推荐使用 for + select + return 的方式,让 ticker 最终被GC
go func() {
for {
select {
case <-done:
return
case t := <-ticker.C:
fmt.Println("Tick at", t)
}
}
}()

// 让程序运行一段时间后停止,防止主函数退出
time.Sleep(10 * time.Second)
done <- true
}

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
"time"
)

func main() {
ticker := time.NewTicker(1 * time.Minute)
defer ticker.Stop()

for range ticker.C {
fmt.Println("Doing something...")
}
}

2、使用 time.AfterFunc

time.AfterFunc 可以在指定的时间间隔后执行一次性的定时任务。它接受两个参数,第一个参数是等待的时间间隔,第二个参数是待执行的函数。如果你想重复执行,可以在函数内部再次调用 time.AfterFunc,和轮训一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
"time"
)

func doSomething() {
fmt.Println("Doing something...")
}

func main() {
var tick func()
tick = func() {
fmt.Println("Tick at", time.Now())
time.AfterFunc(1*time.Second, tick)
}

time.AfterFunc(1*time.Second, tick)

time.Sleep(10 * time.Second) // 让程序运行一段时间后停止,防止主函数退出
fmt.Println("Done!")
}

注意:通常不推荐在time.AfterFunc 中使用立即延迟(如time.AfterFunc(0, doSomething)),因为这将导致每次调用都创建一个新的定时器,这不是最佳实践。更好的做法是直接调用函数或者在另一个 goroutine 中调用doSomething

3、使用cron包(第三方库)

如果你需要更复杂的定时任务调度,比如按照 cron 表达式执行任务,可以使用第三方库如 robfig/cron。首先需要安装这个包:

1
go get github.com/robfig/cron/v3

然后你可以这样使用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
"fmt"
"github.com/robfig/cron/v3"
)

func main() {
c := cron.New() // 创建一个Cron实例
c.AddFunc("*/5 * * * *", func() { // 每5分钟执行一次任务,cron表达式解释为每5分钟执行一次的格式
fmt.Println("Running task every 5 minutes")
}) // 添加任务到Cron实例中,并设置cron表达式和要执行的函数。cron表达式遵循Unix crontab格式。
c.Start() // 启动Cron实例开始执行任务。这将阻塞当前goroutine,直到调用Stop或Cron实例被销毁。如果你不想阻塞,可以在单独的goroutine中启动它。
}

使用第三方库可以让你更灵活地安排复杂的定时任务。例如,你可以按照特定的时间表(如每天的特定时间、每周的特定天等)来安排任务。


Go 定时任务
https://flepeng.github.io/021-Go-36-Go-脚本-Go-定时任务/
作者
Lepeng
发布于
2024年12月6日
许可协议