Golang想实现计时器的功能,一般有三种 第一种是for循环中不断sleep,但是更多地,我们使用Go提供的两个结构来实现。
timer.Timer
type Timer struct {
C <-chan Time
r runtimeTimer
}
type runtimeTimer struct {
tb uintptr
i int
when int64
period int64
f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{}
seq uintptr
}
可以看出,Timer结构有一个只读的channel,还有一个runtimeTimer类型的结构体
使用定时器Timer一般都是通过NewTimer或AfterFunc函数来获取
func NewTimer(d *Duration) *Timer {
c := make(chan Time, 1)
t := &Timer {
C: c,
r: runtimeTimer {
when: when(d), //表示经过d时间,调用f
f: sendTime, // f表示一个函数调用,sendTime表示向Timer.C发送当前的时间
arg: c, // arg表示调用f时传递的参数, c用于接受接受sendTime发送时间
}
}
startTimer(&t.r)
return t
}
例子
package main
import (
"fmt"
"time"
)
func Love() {
timer := time.NewTimer(2 * time.Second)
// 新建一个Timer
for {
select {
case <-timer.C:
fmt.Println("I Love You!")
timer.Reset(2 * time.Second)
// 上一个when执行完成,重置时间
}
}
return
}
func main() {
go Love()
stop := 0
for {
fmt.Scan(&stop)
if stop == 1 {
break
}
}
}
time.Tricker
Tricker和Timer的结构是类似的,Tricker是一个重复版本的Timer,它会在重复的时间d后向Tricker中写入数据。(即不需要time.Reset()方法)
func main() {
tricker := time.NewTricker(time.Millisecond * 500)
go func() {
for t := range tricker.C {
fmt.Println(t)
fmt.Println("I Love You!")
}
}()
time.Sleep(time.Second * 10)
tricker.Stop()
}