golang定时器使用踩的坑:定时器每天执行一次

golang定时器使用踩的坑

  • 项目背景以及问题
  • 解决方案

项目背景以及问题

项目中有这样一个需求,需要用定时器在每天的上午10:00:00处理某些业务逻辑,但是遇到了2个问题。
不比比,上代码

go func() {
		for {
			now := time.Now()
			var next time.Time

			//每天10:00与苏轼论道
			if now.Hour() < 10 || now.Hour() == 10 {
				next = now
			} else {
				next = now.Add(time.Hour * 24)
			}

			//每天10:00与苏轼论道
			next = time.Date(next.Year(), next.Month(), next.Day(), 10, 0, 0, 0, next.Location())

			// 定时时间已过,防止项目重启时,再次触发定时器。如10点执行一次,10:10重启了服务,此时设置为下一天执行

			logger.Info("UpdateOndutys Now=%s Next=%s", now, next)
			timer := time.NewTimer(next.Sub(now))

			select {
			case ts := <-timer.C:
				// go function() //业务逻辑
				logger.Info("Start UpdateOnduty_7day ts=%s", ts.String())
				time.Sleep(120 * time.Second)
				timer.Stop()
			}
		}
	}()

问题1:golang定时器有一个特点就是你设置一个过期的时间它仍然会执行,比如,当前是上午10:00:00,然后我设置定时器是今天的9:00:00去执行,它仍然会执行。
问题2:如果定时器是上午10:00:00执行,然后我10:44:44重启了项目,然后它就又执行一次,但是需求是一天只执行一次。

解决方案

在我们启动定时器之前判断一下当前时间与定时器的执行时间大小,如果当前时间大于定时器执行时间,说明定时器已经执行过,那么就设置为明天再执行。如果当前时间小于定时器时间那么定时器未执行过,按照正常逻辑今日执行。

go func() {
		for {
			now := time.Now()
			var next time.Time

			//每天10:00与苏轼论道
			if now.Hour() < 10 || now.Hour() == 10 {
				next = now
			} else {
				next = now.Add(time.Hour * 24)
			}

			//每天10:00与苏轼论道
			next = time.Date(next.Year(), next.Month(), next.Day(), 10, 0, 0, 0, next.Location())

			// 定时时间已过,防止项目重启时,再次触发定时器。如10点执行一次,10:10重启了服务,此时设置为下一天执行
			if now.Unix() > next.Unix() {
				next = now.Add(time.Hour * 24)
				next = time.Date(next.Year(), next.Month(), next.Day(), 10, 0, 0, 0, next.Location())
			}

			logger.Info("UpdateOndutys Now=%s Next=%s", now, next)
			timer := time.NewTimer(next.Sub(now))

			select {
			case ts := <-timer.C:
				// go function() //业务逻辑
				logger.Info("Start UpdateOnduty_7day ts=%s", ts.String())
				time.Sleep(120 * time.Second)
				timer.Stop()
			}
		}
	}()

你可能感兴趣的:(#,杂谈_go,golang,定时器,timer)