基于Go语言轻松构建定时任务调度器的示例代码

作者:

文章目录
  • 我们希望实现一个任务调度器,能够: 每隔固定时间执行某个函数; 支持并发安全; 可停止调度器(支持任务终止); 可扩展多个任务调度。
  • Go 的 time.Ticker 提供了周期性触发的功能。配合 select 和 goroutine 可实现高效的调度器。 示例:每 2 秒执行一次任务 package main import ( “fmt” “time” ) func task() { fmt.Println(“任务执行时间:”, time.Now()) } func main() { ticker := time.NewTicker(2 * time.Second) defer ticker.Stop() done := make(chan bool) go func() { for { select { case <-done: fmt.Println(“调度器已停止”) return case t := <-ticker.C: fmt.Println(“调度器触发:”, t) task() } } }() // 模拟运行一段时间后终止 time.Sleep(10 * time.Second) done <- true } 输出示例: 调度器触发:2025-08-05 20:00:00任务执行时间:2025-08-05 20:00:00调度器触发:2025-08-05 20:00:02任务执行时间:2025-08-05 20:00:02…调度器已停止
  • 为了更灵活地管理多个任务,我们可以封装一个 Scheduler 类型。 type TaskFunc func() type Scheduler struct { ticker *time.Ticker quit chan struct{} running bool mu sync.Mutex } func NewScheduler(interval time.Duration, task TaskFunc) *Scheduler { return &Scheduler{ ticker: time.NewTicker(interval), quit: make(chan struct{}), running: false, } } func (s *Scheduler) Start(task TaskFunc) { s.mu.Lock() if s.running { s.mu.Unlock() return } s.running = true s.mu.Unlock() go func() { for { select { case <-s.quit: return case <-s.ticker.C: task() } } }() } func (s *Scheduler) Stop() { s.mu.Lock() defer s.mu.Unlock() if s.running { close(s.quit) s.ticker.Stop() s.running = false } } 使用示例 func main() { scheduler := NewScheduler(3*time.Second, nil) scheduler.Start(func() { fmt.Println(“执行任务:”, time.Now()) }) time.Sleep(10 * time.Second) scheduler.Stop() fmt.Println(“调度器停止”) }
  • 场景 调度内容 日志清理 每天凌晨清除旧日志 服务心跳 每 5 秒上报健康状态 数据同步 每小时同步远程数据 自动备份 每天 23:00 执行数据备份
  • 1. 资源释放: 使用 time.Ticker 时,一定要在停止时调用 ticker.Stop(),否则会泄露定时器资源。 2. 线程安全: 如果调度器涉及状态管理(如是否运行中),需要使用 sync.Mutex 加锁保护。 3. 协程退出机制: 使用 chan struct{} 来安全地关闭 goroutine 是一种推荐方式。
  • 可结合 context.Context 实现更细粒度的取消控制; 支持动态更改调度时间(重设 ticker); 结合 cron 表达式(第三方库如 robfig/cron)实现更复杂的计划任务; 支持任务失败重试与日志记录机制。
  • 通过 time.Ticker 和 goroutine,Go 可以非常优雅地实现定时任务调度器。虽然标准库方案简单,但足以应对大多数日常应用。你可以在此基础上封装出强大的任务调度框架,用于后台服务、数据处理、定时推送等业务场景。 到此这篇关于基于Go语言轻松构建定时任务调度器的示例代码的文章就介绍到这了,更多相关Go定时任务调度器内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: Go实现一个轻量级并发任务调度器(支持限速) Golang并发编程之调度器初始化详解 一文详解Golang协程调度器scheduler 一文理解Goland协程调度器scheduler的实现 在Golang中实现定时任务的几种高效方法 Go语言封装一个Cron定时任务管理器
  • 目录
    • 一、需求背景
    • 二、实现方案一:使用time.Ticker
    • 三、实现方案二:封装通用任务调度器结构体
    • 四、任务调度器使用场景举例
    • 五、注意事项
    • 六、进阶建议
    • 七、结语

    在后端服务、日志采集、数据清洗、健康检查等应用中,我们经常需要实现“每隔一段时间执行某个任务”。Go 标准库 time 包提供了非常强大且简洁的支持,配合协程可轻松构建定时任务调度器。

    我们希望实现一个任务调度器,能够:

    • 每隔固定时间执行某个函数;
    • 支持并发安全;
    • 可停止调度器(支持任务终止);
    • 可扩展多个任务调度。

    Go 的 time.Ticker 提供了周期性触发的功能。配合 select 和 goroutine 可实现高效的调度器。

    示例:每 2 秒执行一次任务

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func task() {
        fmt.Println("任务执行时间:", time.Now())
    }
    
    func main() {
        ticker := time.NewTicker(2 * time.Second)
        defer ticker.Stop()
    
        done := make(chan bool)
    
        go func() {
            for {
                select {
                case <-done:
                    fmt.Println("调度器已停止")
                    return
                case t := <-ticker.C:
                    fmt.Println("调度器触发:", t)
                    task()
                }
            }
        }()
    
        // 模拟运行一段时间后终止
        time.Sleep(10 * time.Second)
        done <- true
    }
    

    输出示例:

    调度器触发:2025-08-05 20:00:00
    任务执行时间:2025-08-05 20:00:00
    调度器触发:2025-08-05 20:00:02
    任务执行时间:2025-08-05 20:00:02

    调度器已停止

    为了更灵活地管理多个任务,我们可以封装一个 Scheduler 类型。

    type TaskFunc func()
    
    type Scheduler struct {
        ticker  *time.Ticker
        quit    chan struct{}
        running bool
        mu      sync.Mutex
    }
    
    func NewScheduler(interval time.Duration, task TaskFunc) *Scheduler {
        return &Scheduler{
            ticker:  time.NewTicker(interval),
            quit:    make(chan struct{}),
            running: false,
        }
    }
    
    func (s *Scheduler) Start(task TaskFunc) {
        s.mu.Lock()
        if s.running {
            s.mu.Unlock()
            return
        }
        s.running = true
        s.mu.Unlock()
    
        go func() {
            for {
                select {
                case <-s.quit:
                    return
                case <-s.ticker.C:
                    task()
                }
            }
        }()
    }
    
    func (s *Scheduler) Stop() {
        s.mu.Lock()
        defer s.mu.Unlock()
    
        if s.running {
            close(s.quit)
            s.ticker.Stop()
            s.running = false
        }
    }
    

    使用示例

    func main() {
        scheduler := NewScheduler(3*time.Second, nil)
        scheduler.Start(func() {
            fmt.Println("执行任务:", time.Now())
        })
    
        time.Sleep(10 * time.Second)
        scheduler.Stop()
        fmt.Println("调度器停止")
    }
    

    场景 调度内容
    日志清理 每天凌晨清除旧日志
    服务心跳 每 5 秒上报健康状态
    数据同步 每小时同步远程数据
    自动备份 每天 23:00 执行数据备份

    1. 资源释放

    使用 time.Ticker 时,一定要在停止时调用 ticker.Stop(),否则会泄露定时器资源。

    2. 线程安全

    如果调度器涉及状态管理(如是否运行中),需要使用 sync.Mutex 加锁保护。

    3. 协程退出机制

    使用 chan struct{} 来安全地关闭 goroutine 是一种推荐方式。

    可结合 context.Context 实现更细粒度的取消控制;

    支持动态更改调度时间(重设 ticker);

    结合 cron 表达式(第三方库如 robfig/cron)实现更复杂的计划任务;

    支持任务失败重试与日志记录机制。

    通过 time.Ticker 和 goroutine,Go 可以非常优雅地实现定时任务调度器。虽然标准库方案简单,但足以应对大多数日常应用。你可以在此基础上封装出强大的任务调度框架,用于后台服务、数据处理、定时推送等业务场景。

    到此这篇关于基于Go语言轻松构建定时任务调度器的示例代码的文章就介绍到这了,更多相关Go定时任务调度器内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • Go实现一个轻量级并发任务调度器(支持限速)
    • Golang并发编程之调度器初始化详解
    • 一文详解Golang协程调度器scheduler
    • 一文理解Goland协程调度器scheduler的实现
    • 在Golang中实现定时任务的几种高效方法
    • Go语言封装一个Cron定时任务管理器

    站内搜索