OBJUI

Go 语言定时任务 4 种常用方法

2025-06-04 16:49:48 41

在Go语言里,实现定时任务有多种方式,下面为你介绍几种常见的方法及其示例代码。

1. 使用time.Ticker(固定间隔执行)

这是实现定时任务最简单的方法,适合用于需要周期性执行的任务。

package main

import (
    "fmt"
    "time"
)

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

    // 创建一个用于终止的通道
    done := make(chan bool)

    // 启动一个goroutine执行定时任务
    go func() {
        for {
            select {
            case <-done:
                return
            case t := <-ticker.C:
                fmt.Println("执行定时任务,当前时间:", t)
                // 在这里编写具体的任务逻辑
            }
        }
    }()

    // 让主程序运行15秒后退出
    time.Sleep(15 * time.Second)
    done <- true
    fmt.Println("程序退出")
}

这个程序会每隔3秒执行一次任务,15秒后自动退出。

2. 使用time.Timer(延迟执行单次任务)

若你只需要执行一次延迟任务,time.Timer是个不错的选择。

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("程序启动")

    // 创建一个5秒后触发的Timer
    timer := time.NewTimer(5 * time.Second)

    // 等待Timer触发
    <-timer.C
    fmt.Println("5秒后执行此任务")

    // 也可以使用time.Sleep实现相同效果
    // time.Sleep(5 * time.Second)
    // fmt.Println("5秒后执行此任务")
}

3. 使用第三方库robfig/cron(支持Cron表达式)

对于复杂的定时任务需求,推荐使用robfig/cron库,它支持类似Unix Cron的表达式。 首先需要安装该库:

go get github.com/robfig/cron/v3

以下是使用示例:

package main

import (
    "fmt"
    "log"

    "github.com/robfig/cron/v3"
)

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

    // 添加任务到调度器
    // 格式:秒(可选) 分 时 日 月 周
    _, err := c.AddFunc("0 */5 * * * *", func() { // 每5分钟执行一次
        fmt.Println("执行每5分钟任务")
    })
    if err != nil {
        log.Fatalf("添加任务失败: %v", err)
    }

    _, err = c.AddFunc("0 0 * * * *", func() { // 每小时执行一次
        fmt.Println("执行每小时任务")
    })
    if err != nil {
        log.Fatalf("添加任务失败: %v", err)
    }

    // 启动调度器
    c.Start()
    defer c.Stop() // 程序结束时停止调度器

    // 让主程序保持运行
    select {}
}

Cron表达式的格式为:秒(可选) 分 时 日 月 周,例如:

  • 0 0 * * * *:每小时执行一次
  • 0 */5 * * * *:每5分钟执行一次
  • 0 0 12 * * *:每天中午12点执行
  • 0 0 0 * * 0:每周日午夜执行

4. 带错误处理的定时任务

在实际应用中,通常需要对任务执行过程中可能出现的错误进行处理。

package main

import (
    "fmt"
    "log"
    "time"
)

func main() {
    ticker := time.NewTicker(5 * time.Second)
    defer ticker.Stop()

    done := make(chan bool)

    go func() {
        for {
            select {
            case <-done:
                return
            case <-ticker.C:
                if err := performTask(); err != nil {
                    log.Printf("任务执行失败: %v", err)
                    // 可以添加重试逻辑或其他错误处理
                }
            }
        }
    }()

    time.Sleep(30 * time.Second)
    done <- true
    fmt.Println("程序退出")
}

// 模拟一个可能会出错的任务
func performTask() error {
    // 任务逻辑...
    fmt.Println("执行任务")
    // 模拟错误
    // return fmt.Errorf("模拟任务执行失败")
    return nil
}

总结

  • 若任务逻辑简单且执行间隔固定,可直接使用time.Ticker
  • 对于复杂的调度需求,建议使用robfig/cron库。
  • 在生产环境中,还需要考虑任务执行失败的重试机制、并发控制以及日志记录等方面。
更多精彩,请关注公众号

微信公众号