开发者

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

开发者 https://www.devze.com 2025-08-08 11:37 出处:网络 作者: 程序员爱钓鱼
目录一、需求背景二、实现方案一:使用time.Ticker三、实现方案二:封装通用任务调度器结构体四、任务调度器使用场景举例五、注意事项六、进阶建议七、结语在后端服务、日志采集、数据清洗、健康检查等应用中,我们经
目录
  • 一、需求背景
  • 二、实现方案一:使用time.Ticker
  • 三、实现方案二:封装通用任务调度器结构体
  • 四、任务调度器使用场景举例
  • 五、注意事项
  • 六、进阶建议
  • 七、结语

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

一、需求背景

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

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

二、实现方案一:使用time.Ticker

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
 php           case <-s.ticker.C:
                task()
            }
        }
    }()
}

func (s *Scheduler) Stop() {
    s.mu.编程客栈Lock()
    defer s.mu.Unlock()

    if s.runninjavascriptg {
        close(s.quit)
        s.ticker.Stop()
        s.running = false
    }
}

使用示例

func main() {
    schedupythonler := 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定时任务调度器内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号