如何在Go中实现类似JavaScript setInterval()的定时异步调用?
在Go中实现类似JavaScript setInterval的定时重复任务
针对你的需求,Go里有几种简单可靠的方式实现定时异步调用函数,以下是最常用的两种方案,同时会兼顾并发安全问题(后台更新数据和API读取数据会存在并发访问):
方案一:使用time.Ticker(推荐)
time.Ticker是Go标准库提供的专门用于定时触发事件的工具,它会按照固定间隔发送时间信号,适合精准的定时任务。
完整示例代码
package main import ( "sync" "time" ) var ( newsData map[string]interface{} dataMu sync.RWMutex // 读写锁,保证并发安全 ) func WebScraper() { // 模拟网页爬取逻辑,更新全局的newsData scrapedData := map[string]interface{}{ "site1": "今日头条:XXX", "site2": "科技新闻:XXX", } // 加写锁,更新数据时防止并发读取 dataMu.Lock() newsData = scrapedData dataMu.Unlock() } func startScraperTicker() { // 设置10分钟的间隔 interval := 10 * time.Minute ticker := time.NewTicker(interval) defer ticker.Stop() // 程序退出时停止ticker,避免资源泄漏 // 先立即执行一次,避免启动后等待10分钟才第一次更新 WebScraper() // 循环接收ticker的信号,每次触发就调用WebScraper for range ticker.C { WebScraper() } } func main() { // 启动后台定时任务goroutine go startScraperTicker() // 这里启动你的API服务,比如用gin、echo等框架 // 示例中用阻塞主goroutine的方式代替服务启动逻辑 select {} }
关键说明
time.NewTicker(interval)创建定时触发的ticker,每隔设置的间隔会向ticker.C通道发送时间值- 启动时手动调用一次
WebScraper,避免服务启动后用户首次请求无数据 - 使用
sync.RWMutex保证newsData的并发安全:更新时加写锁,API读取时加读锁(比如API接口中用dataMu.RLock()和dataMu.RUnlock())
方案二:使用time.Sleep循环(简单场景)
如果对定时间隔精度要求不高,可以用time.Sleep配合循环实现,逻辑更直观:
func startScraperSleepLoop() { interval := 10 * time.Minute // 先立即执行一次 WebScraper() for { time.Sleep(interval) WebScraper() } } // 在main中启动:go startScraperSleepLoop()
注意点
- 这种方式的间隔是函数执行完成后再等待设定时长,如果
WebScraper执行耗时较长,实际间隔会比10分钟久 - 同样需要添加读写锁保证并发安全
额外提示
如果需要优雅停止定时任务(比如收到系统退出信号时),可以结合context.Context控制循环退出:
import "context" func startScraperWithContext(ctx context.Context) { interval := 10 * time.Minute ticker := time.NewTicker(interval) defer ticker.Stop() WebScraper() for { select { case <-ticker.C: WebScraper() case <-ctx.Done(): // 收到停止信号,退出循环 return } } } // 在main中使用: // ctx, cancel := context.WithCancel(context.Background()) // go startScraperWithContext(ctx) // 当需要停止任务时调用cancel()
内容的提问来源于stack exchange,提问作者Titan
相关产品推荐
相关产品推荐

