ZBLOG

golang 每天定时任务

Golang 实现每天定时任务

在 Go 中实现每天定时任务有几种常用方法,以下是详细的实现方案:

1. 使用 time.Ticker + 时间判断(简单场景)

package main

import (
	"fmt"
	"time"
)

func main() {
	ticker := time.NewTicker(1 * time.Minute) // 每分钟检查一次
	defer ticker.Stop()

	for now := range ticker.C {
		if isTargetTime(now) { // 判断是否是目标时间
			fmt.Println("执行每日任务:", now.Format("2006-01-02 15:04:05"))
			dailyTask()
		}
	}
}

// 判断当前时间是否为目标执行时间(例如每天凌晨2点)
func isTargetTime(t time.Time) bool {
	return t.Hour() == 2 && t.Minute() == 0
}

func dailyTask() {
	fmt.Println("正在执行每日任务...")
	// 这里放置你的实际业务逻辑
}

2. 使用 github.com/robfig/cron(推荐)

安装 cron v3:

go get github.com/robfig/cron/v3@v3.0.0

示例代码:

package main

import (
	"fmt"
	"github.com/robfig/cron/v3"
)

func main() {
	c := cron.New()

	// 添加每日任务(每天凌晨2点30分执行)
	id, err := c.AddFunc("30 2 * * *", func() {
		fmt.Println("Cron触发每日任务")
		dailyTask()
	})
	
	if err != nil {
		fmt.Printf("添加定时任务失败: %v\n", err)
		return
	}
	
	fmt.Printf("已添加定时任务,ID: %d\n", id)
	
	c.Start()
	
	defer c.Stop()
	
	// 保持程序运行
	select {}
}

func dailyTask() {
	fmt.Println("正在执行每日任务...")
}

Cron表达式说明:

*    *    *    *    *
-    -    -    -    -
|    |    |    |    |
|    |    |    |    星期几 (0 - 6) (周日=0)
|    |    |    月份 (1 - 12)
|    |    日 (1 - 31)
|    小时 (0 -23)
分钟 (0 -59)

示例:
"30  2   *   *   *" = 每天凌晨2点30分
"0   */6   *   *   *" =每6小时整点执行一次 

3. gocron库(更友好的API)

安装:

go get github.com/go-co-op/gocron@v1.18.0

示例代码:

package main

import (
	"fmt"
        "time"

        "github.com/go-co-op/gocron"
)

func main() {
	s := gocron.NewScheduler(time.Local)

        // UTC+8时区,每天早上9点15分执行        
        _, err := s.Every(1).Day().At("09:15").Do(dailyTask)
        if err != nil {
                panic(err)
        }

        s.StartAsync()
        
        defer s.Stop()
        
        select {}
}

func dailyTask() {
        fmt.Printf("%s: Executing daily task\n", time.Now().Format(time.RFC3339))
}

4. context控制的任务管理

package main

import (
       "context"
       "fmt"
       "os/signal"
       "syscall"
       "time"

       "github.com/robfig/cron/v3"
)

func main() {    
       ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
       defer stop()

       c := cron.New(cron.WithLocation(time.Local)) //使用本地时区
    
       _, err := c.AddFunc("@daily", func(){
              fmt.Printf("[%s] Daily job started\n", time.Now().Format(time.DateTime))
              doDailyJob(ctx) 
              fmt.Printf("[%s] Daily job completed\n", time.Now().Format(time.DateTime))
       })
    
       if err != nil{
              panic(err)
       }
    
       c.Start()
    
      <-ctx.Done()
      fmt.Println("\nReceived shutdown signal...")

      ctxShutdown, cancel := context.WithTimeout(context.Background(),5*time.Second)
      defer cancel()

      <-c.Stop().Done()
      fmt.Println("Cron jobs stopped cleanly")
}

func doDailyJob(ctx context.Context){
      select{
      case <-ctx.Done():
          return 
      default:
          fmt.Println("- Processing dayly data...")
          time.Sleep(3*time.Second)//模拟耗时操作  
      }
}

最佳实践建议

1.时区处理:明确指定时区,避免服务器时区设置导致的时间偏差问题。

2.错误恢复:在定时任务的函数中添加recover机制,防止panic导致整个调度停止。

3.日志记录:详细记录每次任务的开始、结束时间和状态。

4.分布式锁:如果是多实例部署,考虑使用Redis等实现分布式锁,避免重复执行。

5.资源清理:确保在程序退出前正确关闭所有定时器或调度器。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23832

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?