当前位置: 首页 > news >正文

go-zero中定时任务的用法

文章目录

  • 使用扩展
  • 定义调度器
  • 测试方法

使用扩展

在go-zero框架中使用定时任务调度的写法示例,首先需要用到的扩展:go get -u github.com/robfig/cron/v3

扩展网址:robfig/cron: a cron library for go (github.com)

定义调度器

gozero/internal 目录下新建 crontab目录,然后首先需要创建一个配置文件:gozero/internal/crontab/config.go ,在这里我写上两个示例的定时任务,分别为“20秒打印一次SayHello”,以及“每一分钟查询一次当前用户总数”:

package crontab

type TaskConfig struct {
	Name      string `json:"name"`      //任务名称
	Scheduler string `json:"scheduler"` //@every表达式中的单位可以是s(秒)、m(分钟)、h(小时)等
	Enabled   bool   // 是否启用
}

func DefaultTask() []TaskConfig {
	return []TaskConfig{
		{
			Name:      "SayHello",
			Scheduler: "@every 20s", //每20秒钟执行一次
			Enabled:   true,
		},
		{
			Name:      "StatisticsUserCount",
			Scheduler: "@every 1m", //每1分钟执行一次
			Enabled:   true,
		},
	}
}

然后,定义定时任务调度器文件:gozero/internal/crontab/scheduler.go,这个文件中,先定义好调度器的结构体和注册方法以及启动方法。代码如下:

type Scheduler struct {
	cron   *cron.Cron
	svcCtx *svc.ServiceContext
}

// NewScheduler creates a new scheduler instance.
func NewScheduler(svcCtx *svc.ServiceContext) *Scheduler {
	return &Scheduler{
		cron:   cron.New(),
		svcCtx: svcCtx,
	}
}

// RegisterTask registers a task with the scheduler.
func (s *Scheduler) RegisterTask(name, schedule string, task func(ctx context.Context, svcCtx *svc.ServiceContext)) {
	_, err := s.cron.AddFunc(schedule, func() {
		task(context.Background(), s.svcCtx)
	})
	if err != nil {
		log.Fatalf("Failed to register task %s: %v", name, err)
	}
	log.Printf("Registered task %s with schedule %s", name, schedule)
}

func (s *Scheduler) Start() {
	s.cron.Start()
	log.Println("Scheduler started")
}

func (s *Scheduler) Stop() {
	s.cron.Stop()
	log.Println("Scheduler stopped")
}

上面的 Start() 和 Stop() 方法,分别实现了 vendor/github.com/robfig/cron/v3/cron.go 中的 Start() 和 Stop() 方法。

接下来,需要初始化定时任务调度器,对于config.go中配置好的定时任务,分别实现不同的业务逻辑。

// InitScheduler 初始化定时任务调度器
func InitScheduler(svcCtx *svc.ServiceContext) (*Scheduler, error) {
	log.Println("Initializing scheduler...")
	scheduler := NewScheduler(svcCtx)
	if scheduler == nil {
		return nil, fmt.Errorf("failed to create scheduler")
	}
	taskConfigs := DefaultTask()
	if taskConfigs == nil {
		return nil, fmt.Errorf("failed to load task configurations")
	}
	for _, taskConfig := range taskConfigs {
		if !taskConfig.Enabled {
			log.Printf("Task %s is disabled, skipping...", taskConfig.Name)
			continue
		}

		log.Printf("Registering task %s...", taskConfig.Name)

		switch taskConfig.Name {
		case "SayHello": //SayHello
			scheduler.RegisterTask(taskConfig.Name, taskConfig.Scheduler, hello.SayHello)
		case "StatisticsUserCount": //统计用户总数
			scheduler.RegisterTask(taskConfig.Name, taskConfig.Scheduler, user.StatisticsUserCount)
		case "xxxx":
			// todo 注册其他定时任务
		default:
			log.Printf("Unknown task: %s", taskConfig.Name)
		}
	}
	return scheduler, nil
}

接下来, 在入口文件gozero/gozero.gomain方法中调用上面定义好的调度器:

func main() {
	//....

	// 定时任务调度
	scheduler, err := crontab.InitScheduler(ctx)
	if err != nil {
		fmt.Printf("Failed to initialize scheduler: %v", err)
	}
	scheduler.Start()

	fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
	server.Start()
}

测试方法

接下来,在 gozero/internal/crontab/task 目录下,新建两个测试方法,测试一下上面配置的两个定时任务:

  • SayHello方法: gozero/internal/crontab/task/hello/say_hello.go
func SayHello(ctx context.Context, svcCtx *svc.ServiceContext) {
	fmt.Println("SayHello running at:", time.Now())
	return
}
  • 查询用户总数的方法:gozero/internal/crontab/task/user/statistics_user_count.go
package user

func StatisticsUserCount(ctx context.Context, svcCtx *svc.ServiceContext) {
	fmt.Println("StatisticsUserCount running at:", time.Now())

	listLogic := admin.NewUserListLogic(ctx, svcCtx)
	count, err := listLogic.GetUserCount() //调用逻辑层查询数据库
	if err != nil {
		fmt.Println("StatisticsUserCount error:", err)
		return
	}
	if count == 0 {
		fmt.Println("StatisticsUserCount count is 0")
		return
	}
	fmt.Println("StatisticsUserCount count:", count)
	return
}

然后运行一下:

image-20250225113155576

这样就可以轻松的在go-zero中实现定时任务的调度了,可以精确到秒级别。

https://gitee.com/rxbook/go-demo-2025/tree/master/gozero

相关文章:

  • 如何搭建和管理 FTP 服务器
  • 取topN不同算法的实现的性能差别
  • Java线程池入门04
  • Neo4j 图数据库安装与操作指南(以mac为例)
  • SpringBatch简单处理多表批量动态更新
  • python的列表和元组别再傻傻分不清啦
  • Java 大视界 -- Java 大数据分布式文件系统的性能调优实战(101)
  • 序列化是什么?常见的序列化方式有哪些?什么时候我们会用到序列化?
  • 利用2600分钟开发springboot3+vue3+mybatis保姆级项目总结
  • 天猫代运营公司推荐:品融电商
  • 若依框架集成阿里云OSS
  • CentOS7最小化安装中使用curl安装yum和wget
  • Solr中得Core和Collection的作用和关系
  • 解决Moodo调节心情模块-大声喊出来无法测量出音频分贝
  • 怎么获取免费的 GPU 资源完成大语言模型(LLM)实验
  • P9231 [蓝桥杯 2023 省 A] 平方差--巧妙统计奇数的个数!
  • Java SE与Java EE
  • 【力扣】2620. 计数器——认识闭包
  • FreeRTOS(3)列表List
  • apache-maven-3.2.1
  • 企业内部网站源码/百度图片
  • java做3d游戏下载网站/浏览器谷歌手机版下载
  • 怎么制作网站app/疫情最新消息今天公布
  • 成都网站设计报价/网络信息发布平台
  • 商丘市住房和城乡建设厅网站/seo外链增加
  • 网店美工毕业设计/百度灰色词优化排名