Go 语言入门之Go 计时器介绍

作者:宇宙之一粟 时间:2024-05-25 15:16:04 

引言

一般来说,很多时候我们面临这样一种情况,即我们需要运行时间记录器,它不断向我们显示当前时间或在给定的时间间隔内保持执行一定的代码和平,在这种情况下,我们应该使用 ??Ticker???,使用这个我们需要使用 go 语言的 ??time??? 包,我们有一个名为 ??NewTicker()??? 的方法,它允许我们停止和启动时间代码,我们需要通过传递 ??chan??? 和 ??bool?? 作为将使用的参数来创建一个代码通道检查它是否打开,如果通道打开意味着计时器将继续。

Go 的计时器

Go 提供了非常简单的语法来实现一个计时器,定时器的结构体定义:

type Ticker struct {
C <-chan Time // 抛出来的channel,给上层系统使用,实现计时
r runtimeTimer // 给系统管理使用的定时器,系统通过该字段确定定时器是否到时,如果到时,调用对应的函数向C中推送当前时间。
}

Ticker对外仅暴露一个 channel,指定的时间到来时就往该 channel 中写入系统时间,也即一个事件。

Ticker 的使用方式也很简单,代码如下:

import time
TimeTicker := time.NewTicker(1 * time.Second)
TimeTicker.Stop()
  • ??time??? : 如果想要使用??time?? 中的计时器,那么需要将其导入代码中

  • ??NewTicker()??? 函数:这个很好理解,新建一个计时器,然后该计时器以时间表达式作为参数,比如一秒??1*time.Second??? ,而不是直接传入??1??? ,也可以传入其他时间方式,比如??2*time.Millisecond??

  • 最后,我们可以使用时间表达式调用由??NewTicker??? 函数创建的变量上的任何活动。例如,在上面的语法中,我们使用了??TimeTicker.Stop()??? 来停止时间计时器。我们可以在特定条件下使用它,比如定义倒数 10 秒的计时器,就可以检查时间是否满足 10 秒,一旦 10 秒发生,我们可以调用??TimeTicker.stop()??。

我们可以每隔一秒输出一个结果,比如实现一个倒数 10 个数的功能:

package main
import (
"fmt"
"time"
)
func main() {
TimeTicker := time.NewTicker(1 * time.Second)
i := 10
for {
<-TimeTicker.C
fmt.Println("i = ", i)
i--
if i == 0 {
TimeTicker.Stop()
break
}
}
}

然后执行该程序:

$ go run main.go
i = 10
i = 9
i = 8
i = 7
i = 6
i = 5
i = 4
i = 3
i = 2
i = 1

Ticker 计时器是如何工作的?

??NewTicker???创建的计时器与??NewTimer???创建的计时器持有的时间??channel???一样都是带一个缓存的??channel???,每次触发后执行的函数也是??sendTime???,这样即保证了无论有误接收方??Ticker??触发时间事件时都不会阻塞:

func NewTicker(d Duration) *Ticker {
if d <= 0 {
panic(errors.New("non-positive interval for NewTicker"))
}
// Give the channel a 1-element time buffer.
// If the client falls behind while reading, we drop ticks
// on the floor until the client catches up.
c := make(chan Time, 1)
t := &Ticker{
C: c,
r: runtimeTimer{
when: when(d),
period: int64(d),
f: sendTime,
arg: c,
},
}
startTimer(&t.r)
return t
}

NewTicker()只是构造了一个Ticker,然后把Ticker.r通过startTimer()交给系统协程维护。

其中period为事件触发的周期。

其中??sendTime()??方法便是定时器触发时的动作:

func sendTime(c interface{}, seq uintptr) {
select {
case c.(chan Time) <- Now():
default:
}
}

??sendTime?? 接收一个管道作为参数,其主要任务是向管道中写入当前时间。

停止Ticker:

停止Ticker,只是简单的把Ticker从系统协程中移除。

函数主要实现如下:

func (t *Ticker) Stop() {
stopTimer(&t.r)
}

??stopTicker()?? 即通知系统协程把该 Ticker 移除,即不再监控。系统协程只是移除 Ticker 并不会关闭管道,以避免用户协程读取错误。

Ticker 使用方式

例子一:

package main
import (
"fmt"
"time"
)
func main() {
TimeTicker := time.NewTicker(3 * time.Second)
tickerChannel := make(chan bool)
go func() {
for {
select {
case timeticker := <-TimeTicker.C:
fmt.Println("The time for current is : ", timeticker)
case <-tickerChannel:
return
}
}
}()
time.Sleep(6 * time.Second)
TimeTicker.Stop()
tickerChannel <- true
fmt.Println("Time for running ticker is completed")
}

运行该代码:

$ go run main.go
The time for current is : 2022-04-29 22:37:13.93862 +0800 CST m=+3.000267823
The time for current is : 2022-04-29 22:37:16.939081 +0800 CST m=+6.000707515
Time for running ticker is completed

例子二:

package main
import (
"fmt"
"time"
)
func main() {
tm := time.Millisecond
tickerTicker := time.NewTicker(400 * tm)
tickerChaneel := make(chan bool)
go func() {
for {
select {
case <-tickerChaneel:
return
case tmtr := <-tickerTicker.C:
fmt.Println("Ticker time at current is", tmtr)
}
}
}()
time.Sleep(1400 * time.Millisecond)
tickerTicker.Stop()
tickerChaneel <- true
fmt.Println("Ticker has stopped now")
}

运行该代码:

$ go run main.go
Ticker time at current is 2022-04-29 22:39:51.13057 +0800 CST m=+0.400159916
Ticker time at current is 2022-04-29 22:39:51.531516 +0800 CST m=+0.801102997
Ticker time at current is 2022-04-29 22:39:51.931238 +0800 CST m=+1.200822301
Ticker has stopped now

来源:https://blog.51cto.com/yuzhou1su/5262636

标签:Go,计时器
0
投稿

猜你喜欢

  • 分享Pytest fixture参数传递的几种方式

    2023-06-15 01:25:28
  • python执行shell获取硬件参数写入mysql的方法

    2024-01-26 15:56:04
  • 使用Python和Prometheus跟踪天气的使用方法

    2021-05-15 14:31:05
  • 解决sql server 数据库,sa用户被锁定的问题

    2024-01-18 23:21:08
  • MySQL5.7.23解压版安装教程图文详解

    2024-01-15 18:19:27
  • python 集合常用操作汇总

    2023-11-15 08:41:22
  • Python 如何将integer转化为罗马数(3999以内)

    2023-01-19 12:46:51
  • Python基本数据类型之字符串str

    2021-06-03 22:47:31
  • Qt数据库应用之实现通用数据生成器

    2024-01-16 00:37:49
  • python list与numpy数组效率对比

    2023-08-18 22:49:39
  • Golang中channel的原理解读(推荐)

    2024-02-08 15:41:38
  • javascript ajax的5种状态介绍

    2024-04-30 10:15:43
  • 前端开发中的一些用户体验细节

    2010-10-19 12:23:00
  • Python匹配中文的正则表达式

    2022-03-21 18:05:50
  • python 如何调用 dubbo 接口

    2022-09-28 13:20:13
  • mysql存储过程事务管理简析

    2024-01-17 14:30:28
  • Jupyter Notebook读取csv文件出现的问题及解决

    2023-08-09 23:11:50
  • VUE预渲染及遇到的坑

    2023-07-02 17:08:34
  • python3 循环读取excel文件并写入json操作

    2022-11-07 15:40:11
  • 前女友发来加密的"520快乐.pdf",我用python破解开之后,却发现

    2023-07-17 20:33:16
  • asp之家 网络编程 m.aspxhome.com