Go语言standard package——time.Timer
本篇文章将对go语言的标准包time.Timer进行介绍,附带部分应用实例
1. time.Timer介绍
-
TImer的定义: type Timer struct { C <-chan Time // contains filtered or unexported fields } 从上面的定义中可以看出,Timer是一个struct,内部包含有一个接受Time的的单向channel Timer对应了一个驱动事件(a single event),Timer的创建方式只有两种: NewTimer:func NewTimer(d Duration) *Timer,该方法接收一个Duration,返回一个Timer。当指定的时间间隔过去之后,返回的Timer会接收到一个Time。 AfterFunc:func AfterFunc(d Duration, f func()) *Timer,该方法接收一个Duration以及一个func,返回一个Timer;AfterFunc会在Duration指定的时间间隔结束之后,在一个独立的goroutine中调用传入的func,而返回的Timer包含一个stop方法,可以用于在duration期间内终止func的调用
2. time.Timer的方法
-
Reset:func (t *Timer) Reset(d Duration) bool,可以认为Reset方法是用于重定义一个已有Timer: 对于用NewTimer方法定义的Timer,该方法只能够在该TImer处于stopped或expired(也就是初定义Duration已过,channel接受过时间的情况)下使用 注意在调用Reset方法前,一定要判断该TImer是否处于对应的可执行状态,如下所示:注意,该过程不应该并发地与其他接受channel内容的操作并发执行 if !t.Stop() { <-t.C } t.Reset(d) 对于用AfterFunc方法定义的Timer,Reset方法的返回值具有一下意义: True:调用时Timer的func还没有执行,Reset会重调度该方法 False:调用时Timer的func已经在执行或执行完成,Reset会调度该方法并使其在此执行;注意:如果返回的是false,那么Reset不会保证上次执行的func已经执行完毕,也不会保证下次执行的func不与上次执行func并发执行;如果用户想要知道上次的func是否已经执行完毕,那么需要在func中设置对应的标志 Stop:func (t *Timer) Stop() bool,Stop方法会阻止Timer被“激活”: 返回True:如果成果停止了Timer 返回False:如果Timer已经被激活了或处于原来就处于Stop状态;注意:为了防止因度对应channel产生的错误,Stop方法不会关闭对应的channel 为了保证在执行完Stop方法或TImer的channel是空的,可以对Stop方法的返回值进行检查,同时抽取channel的内容: if !t.Stop() { <-t.C } 对于一个由AfterFunc定义的Timer,如果Stop方法的返回值时false,那么说明该Timer已经被激活了,而其中的func已经在另一个goroutine中执行或执行完成;Stop方法不会等待func执行完毕之后才返回,如果用户想要确定func是否已经执行完成,那么需要通过在func中设定对应的标志
3. 示例
-
示例一:Timer会在指定Duration之后接收到一个时间
6 package main 5 4 import "time" 3 import "fmt" 2 1 func main() { 7 t := time.NewTimer(time.Duration(3*time.Second)) 1 time.Sleep(5*time.Second) 2 if !t.Stop() { 3 now := <-t.C 4 fmt.Println(now) 5 } 6 }
输出:2022-02-18 10:40:05.167702931 +0800 CST m=+3.002078547
-
示例二:用AfterFunc定义的Timer不会在Duration结束之后接收到时间,而是会在另一个goroutine中执行指定的func
18 package main 17 16 import ( 15 "time" 14 "fmt" 13 ) 12 11 func main() { 10 f := func() { 9 fmt.Println("function is invoked!") 8 } 7 t := time.AfterFunc(time.Duration(3*time.Second), f) 6 time.Sleep(5*time.Second) 5 if !t.Stop() { 4 // now := <-t.C 3 // fmt.Println(now) 2 // 上述操作会陷入死锁 1 // 这也说明了用AfterFunc定义的Timer在指定的Duration结束之后并不会接收到时间 19 } 1 }