Go语言:实现时间轮询

2,366 阅读1分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

如何在Go语言中时间定期执行,如果是从别的语言转到go语言,很容易想到如下这种方式:


for {
    time.Sleep(2 * time.Second)  // 2 秒间隔
    do_some_thing()
}

在Go语言中,更优雅的方式是:

for range time.Tick(2 * time.Second ) {
  do_some_thing()
}

time.Tick() 函数返回的是一个 channel ,每隔指定的时间就会有数据从 channel 中出来。

range 其实是可以不接收遍历的值的,如果不接收,就可以简写成上面的格式。

那为什么我们不推荐 time.Sleep() 的方式呢,毕竟从上面的例子上看,感觉也没差多少啊?

但是,如果我们要指定退出机制,用 time.Sleep() 可能的做法就是

func main() {
   stop := false

   go func() {
      for {
         if stop {
            break
         }
         fmt.Println(1)
         time.Sleep(2 * time.Second) // 2 秒间隔
      }
   }()

   time.Sleep(10 * time.Second)
   stop = true
   fmt.Println(2)
   time.Sleep(10 * time.Second)
   fmt.Println(3)
}

而用 time.Tick() 的做法则是

func main() {
   t := time.NewTicker(time.Second * 2)

   go func() {
      for {
         select {
         case <-t.C:
            fmt.Println(1)
         }
      }
   }()

   time.Sleep(10 * time.Second)
   fmt.Println(2)
   t.Stop()
   time.Sleep(10 * time.Second)
   fmt.Println(3)
}

从逻辑和语义上来将 time.NewTicker() 的方式显然更 go