本文为《Go专家编程》读书笔记~
Go专家编程
定时器
Go提供了两种定时器,此处分为一次性定时器、周期性定时器。
一次性定时器:定时器只计时一次,结束便停止;
周期性定时器:定时器周期性进行计时,除非主动停止,否则将永久运行;
Timer
Timer实际上是一种单一事件的定时器,即经过指定的时间后触发一个事件,这个事件通过其本身提供的channel进 行通知。之所以叫单一事件,是因为Timer只执行一次就结束,这也是Timer与Ticker的最重要的区别之一。
通过timer.NewTimer(d Duration)可以创建一个timer,参数即等待的时间,时间到来后立即触发一个事件。
type Timer struct {
// Timer代表一次定时,时间到来后仅发生一个事件。
// Timer对外仅暴露一个channel,指定的时间到来时就往该channel中写入系统时间,也即一个事件。
C <-chan Time
r runtimeTimer
}
使用场景
设定超时时间 / 延迟执行某个方法
func WaitChannel(conn <-chan string) bool {
timer := time.NewTimer(1 * time.Second)
select {
case <- conn:
timer.Stop()
return true
case <- timer.C: // 超时
println("WaitChannel timeout!")
return false
}
}
WaitChannel作用就是检测指定的管道中是否有数据到来,通过select语句轮询conn和timer.C两个管道,timer 会在1s后向timer.C写入数据,如果1s内conn还没有数据,则会判断为超时
time.AfterFunc()异步
time.AfterFunc()是异步执行的,所以需要在函数最后sleep等待指定的协程退出,否则可能函数结束时协程还未执行。
func main() {
fmt.Println(time.Now())
<-time.After(time.Second*1)
fmt.Println(time.Now())
log.Println("AfterFuncDemo start: ", time.Now())
// time.AfterFunc()是异步执行的,所以需要在函数最后sleep等待指定的协程退出,否 则可能函数结束时协程还未执行。
time.AfterFunc(time.Second*2, func() {
log.Println("AfterFuncDemo end: ", time.Now())
})
time.Sleep(3 * time.Second) // 等待协程退出
}
Timer对外接口
创建定时器
使用方法 func NewTimer(d Duration) *Timer
指定一个时间即可创建一个Timer,Timer一经创建便开始计时,不需要 额外的启动命令。
实际上,创建Timer意味着把一个计时任务交给系统守护协程,该协程管理着所有的Timer,当Timer的时间到达后 向Timer的管道中发送当前的时间作为事件。
停止定时器
Timer创建后可以随时停止,停止计时器的方法是:
1. func (t *Timer) Stop() bool
其返回值代表定时器有没有超时:
- true: 定时器超时前停止,后续不会再有事件发送;
- false: 定时器超时后停止;
重置定时器
已过期的定时器或者已停止的定时器,可以通