Golang的通道技巧
2011 年 7 月 3 日
time.After(d)
函数声明为 func After(d Duration) <-chan Time
,在 Duration d
之后,当前时间被发到返回的通道;因此它和 NewTimer(d).C
等价;它类似 Tick()
,但 After()
只发送一次时间。可以使用此函数应对简单的超时模式,以下为三种形式。
- 要执行某个任务(如从通道
ch
中读取数据),但最多等待1秒。先创建一个信号通道,之后启动一个lambda
协程,协程在给通道发送数据前休眠:

- 用
time.After()
函数替换timeout-channel
。可以在select
中使用来让发送信号超时或停止协程的执行。以下代码,在timeoutNs
纳秒后执行select
的timeout
分支后,包含client.Call
的lambda
协程也随之结束,不会给通道ch
返回值。缓冲大小设置为 1 是必要的,可以避免协程死锁以及确保超时的通道可以被垃圾回收。需要注意如果select
中的某些非定时器选项的通道读写密集,则可能无法结束这些进程。这种情况如果将select
放到一个for
循环中,也无法精确地在定时器通道写入时就结束,因为select
对可以执行的多个case
采取伪随机算法选择,可能结束进程的时间要比定时器发出信号略晚一些。

- 假设程序从多个复制的数据库同时读取,只需要接收首先到达的答案,
Query
函数获取数据库的连接切片,并行请求每一个数据库并返回收到的第一个响应。结果通道ch
必须是带缓冲的,以保证第一个发送进来的数据有地方可以存放,确保放入的首个数据总会成功:
