You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:18:20