基于Go語言輕松構(gòu)建定時(shí)任務(wù)調(diào)度器的示例代碼
在后端服務(wù)、日志采集、數(shù)據(jù)清洗、健康檢查等應(yīng)用中,我們經(jīng)常需要實(shí)現(xiàn)“每隔一段時(shí)間執(zhí)行某個(gè)任務(wù)”。Go 標(biāo)準(zhǔn)庫 time 包提供了非常強(qiáng)大且簡潔的支持,配合協(xié)程可輕松構(gòu)建定時(shí)任務(wù)調(diào)度器。
一、需求背景
我們希望實(shí)現(xiàn)一個(gè)任務(wù)調(diào)度器,能夠:
- 每隔固定時(shí)間執(zhí)行某個(gè)函數(shù);
- 支持并發(fā)安全;
- 可停止調(diào)度器(支持任務(wù)終止);
- 可擴(kuò)展多個(gè)任務(wù)調(diào)度。
二、實(shí)現(xiàn)方案一:使用time.Ticker
Go 的 time.Ticker 提供了周期性觸發(fā)的功能。配合 select 和 goroutine 可實(shí)現(xiàn)高效的調(diào)度器。
示例:每 2 秒執(zhí)行一次任務(wù)
package main
import (
"fmt"
"time"
)
func task() {
fmt.Println("任務(wù)執(zhí)行時(shí)間:", 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("調(diào)度器已停止")
return
case t := <-ticker.C:
fmt.Println("調(diào)度器觸發(fā):", t)
task()
}
}
}()
// 模擬運(yùn)行一段時(shí)間后終止
time.Sleep(10 * time.Second)
done <- true
}
輸出示例:
調(diào)度器觸發(fā):2025-08-05 20:00:00
任務(wù)執(zhí)行時(shí)間:2025-08-05 20:00:00
調(diào)度器觸發(fā):2025-08-05 20:00:02
任務(wù)執(zhí)行時(shí)間:2025-08-05 20:00:02
...
調(diào)度器已停止
三、實(shí)現(xiàn)方案二:封裝通用任務(wù)調(diào)度器結(jié)構(gòu)體
為了更靈活地管理多個(gè)任務(wù),我們可以封裝一個(gè) 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("執(zhí)行任務(wù):", time.Now())
})
time.Sleep(10 * time.Second)
scheduler.Stop()
fmt.Println("調(diào)度器停止")
}
四、任務(wù)調(diào)度器使用場景舉例
| 場景 | 調(diào)度內(nèi)容 |
|---|---|
| 日志清理 | 每天凌晨清除舊日志 |
| 服務(wù)心跳 | 每 5 秒上報(bào)健康狀態(tài) |
| 數(shù)據(jù)同步 | 每小時(shí)同步遠(yuǎn)程數(shù)據(jù) |
| 自動(dòng)備份 | 每天 23:00 執(zhí)行數(shù)據(jù)備份 |
五、注意事項(xiàng)
1. 資源釋放:
使用 time.Ticker 時(shí),一定要在停止時(shí)調(diào)用 ticker.Stop(),否則會(huì)泄露定時(shí)器資源。
2. 線程安全:
如果調(diào)度器涉及狀態(tài)管理(如是否運(yùn)行中),需要使用 sync.Mutex 加鎖保護(hù)。
3. 協(xié)程退出機(jī)制:
使用 chan struct{} 來安全地關(guān)閉 goroutine 是一種推薦方式。
六、進(jìn)階建議
可結(jié)合 context.Context 實(shí)現(xiàn)更細(xì)粒度的取消控制;
支持動(dòng)態(tài)更改調(diào)度時(shí)間(重設(shè) ticker);
結(jié)合 cron 表達(dá)式(第三方庫如 robfig/cron)實(shí)現(xiàn)更復(fù)雜的計(jì)劃任務(wù);
支持任務(wù)失敗重試與日志記錄機(jī)制。
七、結(jié)語
通過 time.Ticker 和 goroutine,Go 可以非常優(yōu)雅地實(shí)現(xiàn)定時(shí)任務(wù)調(diào)度器。雖然標(biāo)準(zhǔn)庫方案簡單,但足以應(yīng)對(duì)大多數(shù)日常應(yīng)用。你可以在此基礎(chǔ)上封裝出強(qiáng)大的任務(wù)調(diào)度框架,用于后臺(tái)服務(wù)、數(shù)據(jù)處理、定時(shí)推送等業(yè)務(wù)場景。
到此這篇關(guān)于基于Go語言輕松構(gòu)建定時(shí)任務(wù)調(diào)度器的示例代碼的文章就介紹到這了,更多相關(guān)Go定時(shí)任務(wù)調(diào)度器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go中字符串處理?fmt.Sprintf與string.Builder的區(qū)別對(duì)比分析
在Go語言中,我們通常會(huì)遇到兩種主要的方式來處理和操作字符串:使用fmt.Sprintf函數(shù)和string.Builder類型,本文給大家介紹它們在性能和用法上有一些關(guān)鍵區(qū)別,感興趣的朋友跟隨小編一起看看吧2023-11-11
golang跳轉(zhuǎn)語句goto,break,continue的使用及區(qū)別說明
這篇文章主要介紹了golang跳轉(zhuǎn)語句goto,break,continue的使用及區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Golang 協(xié)程配合管道的實(shí)現(xiàn)示例
本文主要介紹了Golang協(xié)程配合管道的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
正則表達(dá)式在Go字符串處理中的實(shí)戰(zhàn)應(yīng)用代碼
在Go語言中,正則表達(dá)式與字符串處理是強(qiáng)大的工具,能夠大幅提升文本處理效率,下面這篇文章主要介紹了正則表達(dá)式在Go字符串處理中實(shí)戰(zhàn)應(yīng)用的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2026-03-03
Go語言學(xué)習(xí)之?dāng)?shù)組的用法詳解
數(shù)組是相同數(shù)據(jù)類型的一組數(shù)據(jù)的集合,數(shù)組一旦定義長度不能修改,數(shù)組可以通過下標(biāo)(或者叫索引)來訪問元素。本文將通過示例詳細(xì)講解Go語言中數(shù)組的使用,需要的可以參考一下2022-04-04

