time包中存在一些有趣的功能,可以和通道组合使用
计时器:指定的时间间隔重复的向通道发送时间(时间间隔是纳秒)
type Ticker struct {
C <- chan Time
...
}
上面类型的工厂方法time.NewTicker(dur) * Ticker,传入时间间隔,调用stop()使计时器停止,在defer语句中使用。
特例:time.Tick()方法返回一个不用关闭的通道,这种计时器,可以用来处理按指定频率处理请求
定时器:只执行一次
time.After(d Duration) <- chan Time
习惯用法:简单超时模式
1.使用time.Sleep(10),在携程发送数据之前是休眠的
2.取消耗时很长的同步调用,可以使用time.After() 函数
如:
<-time.After(dur)
ch := make(chan int, 1)
go func() { for { ch <- 1 } } ()
L:
for {
select {
case <-ch:
// do something
case <-time.After(timeoutNs):
// call timed out
break L
}
}
注意:
》如果多个case同时满足条件,这个时间select对case的选择是伪随机的
》注意通道的缓存容量1是必传的,不然会导致死锁
3.假设程序从多个复制的数据库同时读取,只需要一个答案,需要接收首先到达的答案,再次声明,结果通道ch必须是带缓存的,以保证第一个发送进来的数据有地方可以存放,确保放入的首个数据总会成功,所以第一个到达的值会被获取并且与执行顺序无关,正在执行的协程,总是可以使用runtime.Goexit()来停止。
func Query(conns []Conn, query string) Result {
ch := make(chan Result, 1)
for _, conn := range conns {
go func(c Conn) {
select {
case ch <- c.DoQuery(query):
default:
}
}(conn)
}
return <- ch
}