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


猜你喜欢
- 之前写页面的时候有试过想用js获取某些元素的translate的数值什么的,但是translate又是transform的子样式(勉强说说)
- 什么是SeleniumSelenium是一个用于测试网站的自动化测试工具,支持各种浏览器包括Chrome、Firefox、Safari等主流
- 关于变量的命名,这又是一个容易引发程序员论战的话题。如何命名才能更具有可读性、易写性与明义性呢?众说纷纭。本期“Python为什么”栏目,我
- 前言数组类型是各种编程语言中基本的数组结构了,本文来盘点下Python中各种“数组”类型的实现。listtuplearray.arrayst
- 在设计网页之前,客户或产品经理会提出对网页视觉风格设计的期望:活跃、大气、稳重、信赖、都市化….. 设计师一听到关键词或许很自然地在心里蹦出
- 现在有越来越多的个人主页站长需要了解如何如何在windows系统下配置自己的php,cgi服务器,以方便本地调试cgi和php的程序。我们可
- 本文实例讲述了Python数据结构与算法之字典树实现方法。分享给大家供大家参考,具体如下:class TrieTree(): d
- Vue.js是一个JavaScript框架,可用于构建Web应用程序的前端框架。特别是在创建复杂功能时,对于每个项目,有必要在我们的应用程序
- 本文以实例形式展示了Python获取电脑硬件信息及状态的实现方法,是Python程序设计中很有实用价值的技巧。分享给大家供大家参考之用。具体
- 展示import tkinter if __name__ == '__main__': win =
- 前言:record类型,这是一种新引用类型,而不是类或结构。record与类不同,区别在于record类型使用基于值的相等性。例如:publ
- 1.用CSS实现布局让我们一起来做一个页面,首先,我们需要一个布局。请使用CSS控制3个div,实现如下图的布局。考察应试者的基本布局知识—
- 背景:由于最近公司项目好像有点受不住并发压力了,优化迫在眉睫。由于当前系统是单数据库系统原因,能优化的地方也尽力优化了但是数据库瓶颈还是严重
- 在SQL查询分析器执行以下代码就可以了。declare @t varchar(255),@c varchar(255)declare tab
- 本文实例为大家分享了Python3多线程版TCP端口扫描器的具体代码,供大家参考,具体内容如下使用命令python BannerDemo.p
- 前言今天呢,笔者想和大家来聊聊python+pytest接口自动化测试的参数关联,笔者这边就不多说废话了,咱们直接进入正题。一、什么是参数关
- https://discuss.pytorch.org/t/how-to-modify-the-final-fc-layer-based-o
- 所有数据库和状态文件都包含在其中。但是,在确定数据目录内容的布局中管理员有某些职责。本文讨论为什么要移动数据目录的各个部分(甚至是字典本身)
- <!DOCTYPE html> <html lang="en" xmlns="http://
- 前言Python 一直以来被大家所诟病的一点就是执行速度慢,但不可否认的是 Python 依然是我们学习和工作中的一大利器。因此,我们对 P