Write a timer with Go

  这个东西其实早就应该总结一下了,然而一直懒=_=,顺便事情很多,就一直没有总结。为什么需要做一个定时器呢,假设我们现在有个服务,服务过程中需要从 redis 中读取缓存数据,如果缓存数据不存在那么我们读线上数据库,读取完毕之后写入 redis 作为热数据。这个过程中,如果是同步的,很明显,读写缓存的操作是不应该阻塞主要服务的,这时候我们就需要自己做个定时器来做超时机制,防止因为缓存服务的问题而影响主要服务(当然,做成异步是OK的)。

Code Here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// author by @xiaoyusilen
package main
import (
"fmt"
"time"
)
func loop() int {
for i := 0; i < 100; i++ {
fmt.Println(i)
}
return 0
}
func main() {
ticker := time.Timer(time.Microsecond * 1) // 新建一个定时器,设置超时时间,这里设置的是1微秒
ch := make(chan *int, 1) // 设置一个 chan 接收服务返回值
go loop() // 起一个 goroutine 执行服务
select {
case <-ch: // 如果收到服务返回值,则说明未超时
ticker.Stop() // 停止计时器
return
case <-ticker.C: // 如果先收到定时器的信号,则说明超时了
fmt.Println("timeout") // 这里做超时处理
return
}
}

  这里写的非常简易~可以根据需要自行更改,至于用time.Timer更好还是time.Ticker更好,取决于实际情况,这两个最大的区别在于,time.Ticker不能调用time.After()方法,而且time.Ticker.Stop()调用了stopTimer的方法。这里的超时时间定为1微秒了,为了测试方便并且造成超时的情况,具体的超时时间根据业务需求来决定,通常超时时间不能超过主要服务的平均响应时间。

  测试结果如下,可以看到还没有输出完毕就超时了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
timeout

  好咯,一个简单的定时器就这样完成了~

FYI

godoc-tick

godoc-time/sleep