ZhouChuang's Blog ZhouChuang's Blog
首页
  • 常用命令
  • 日常总结
  • Prometheus
  • 基础
  • 常用库
专题
  • 「编码」
更多
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Zhou Chuang

为学日益 为道日损
首页
  • 常用命令
  • 日常总结
  • Prometheus
  • 基础
  • 常用库
专题
  • 「编码」
更多
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Go语言基础

  • 常用库

  • 数据库相关内容

  • 技巧

    • Go 处理 json
    • Go 执行定时任务
      • 单次延迟任务
      • 周期性的定时任务
      • 动态调整时间
      • 在特定时刻执行
      • 对于复杂的定时任务
        • 主要功能
  • golang
  • 技巧
ZhouChuang
2025-03-18
目录

Go 执行定时任务

在 Go 中实现定时任务有多种方法,以下是常见且实用的实现方式。

# 单次延迟任务

如果只需要在特定时间后执行一次任务,通常使用 time.After 或 time.Sleep 。

func main() {
	fmt.Println("任务将在 5 秒后执行...")
	time.Sleep(5 * time.Second) // 延迟 5 秒
	doTask()

	// 或者使用 time.After
	<-time.After(5 * time.Second) // 等待 5 秒
	fmt.Println("5 秒已到!")
	doTask()
}

func doTask() {
	fmt.Println("执行定时任务...")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

特点:

  • 适合简单的单次延迟任务。
  • time.Sleep 会阻塞当前 goroutine,time.After 返回一个通道,可用于非阻塞场景。

# 周期性的定时任务

time.Ticker 适合需要周期性执行的任务,比如每隔一段时间运行一次。

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

	for {
		select {
		case t := <-ticker.C:
			fmt.Println("任务执行时间:", t)
			// 在这里执行你的定时任务逻辑
			doTask()
		}
	}
}

func doTask() {
	fmt.Println("执行定时任务...")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 动态调整时间

如果需要动态调整定时时间,可以使用 time.Timer。

func main() {
	timer := time.NewTimer(3 * time.Second)

	for {
		<-timer.C
		fmt.Println("任务执行时间:", time.Now())
		doTask()

		// 重置定时器,可以动态调整时间
		timer.Reset(5 * time.Second)
	}
}

func doTask() {
	fmt.Println("执行定时任务...")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 在特定时刻执行

func main() {
	for {
		now := time.Now()
		// 将当前时间截断到整点,然后加上5分钟,得到下一个整点时间
		next := now.Truncate(time.Hour).Add(time.Hour + 5*time.Minute)
		// 如果当前时间已经超过 next,则将 next 推迟到下个小时
		if now.After(next) {
			next = next.Add(time.Hour)
		}
		// 计算需要睡眠的时长
		sleepDuration := next.Sub(now)
		time.Sleep(sleepDuration)

		// 执行任务
		doTask()
	}
}

func doTask() {
	fmt.Println("执行定时任务...")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 对于复杂的定时任务

如果需要类似 cron 的调度功能(比如“每天 8 点执行”),可以使用第三方库 github.com/robfig/cron (opens new window)。

它是一个用于 Go 语言的强大且流行的 cron 调度库,它允许开发者在指定的时间或周期性调度任务。它最初由 Rob Figueiredo(robfig)开发,目前已经成为 Go 生态系统中处理定时任务的常用工具之一。该库的主要功能是解析 cron 表达式并根据时间表运行注册的任务,支持灵活的调度需求。

# 主要功能

  1. Cron 表达式解析:
    • 支持标准的 cron 表达式(例如 0 0 * * * 表示每小时整点执行)。
    • 默认使用标准的 5 字段格式(分钟、小时、日、月、星期),也可以通过选项支持 6 字段格式(包括秒)。
    • 提供预定义的快捷方式,例如 @hourly(每小时)、@daily(每天)、@every 1h30m(每隔 1 小时 30 分钟)。
  2. 任务调度:
    • 允许注册函数(Func)作为任务,在指定时间自动执行。
    • 任务运行在独立的 goroutine 中,不会阻塞主程序。
  3. 灵活的配置:
    • 支持时区设置,可以通过 CRON_TZ 前缀指定任务运行的时区。
    • 提供函数式选项(functional options)来定制调度器的行为,例如日志记录、panic 恢复等。
  4. 动态管理:
    • 支持在调度器运行时动态添加或移除任务。
    • 可以检查任务的下一次和上一次运行时间。
  5. 日志和错误处理:
    • 内置日志接口(兼容 github.com/go-logr/logr),支持详细日志记录。
    • 通过 JobWrapper 和 Chain 机制支持任务的拦截器,例如跳过仍在运行的任务或记录执行日志。
package main

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

func main() {
	// 创建一个新的 cron 调度器
	c := cron.New()

	// 每小时整点执行
	c.AddFunc("0 * * * *", func() {
		fmt.Println("每小时执行:", time.Now())
	})

	// 每天凌晨 0 点执行
	c.AddFunc("0 0 * * *", func() {
		fmt.Println("每天凌晨执行:", time.Now())
	})

	// 每隔 1 小时 30 分钟执行
	c.AddFunc("@every 1h30m", func() {
		fmt.Println("每隔1小时30分钟执行:", time.Now())
	})

	// 启动调度器
	c.Start()

	// 防止主程序退出
	select {}
}
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
31
32
33

标准 cron 表达式由 5 个字段组成(默认不支持秒,需通过 WithSeconds 启用)

cron.New(cron.WithSeconds()) // 启用秒级调度
1
#定时任务#cron
上次更新: 2025/05/06, 13:52:56
Go 处理 json

← Go 处理 json

最近更新
01
find 命令介绍
05-06
02
交换分区的配置
04-09
03
top 命令介绍
04-08
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Zhou Chuang 版权所有| 鲁ICP备2021031629号-2
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式