第八章 goroutine和通道
< P225 >
- 同类型的
chan可以用==比较,当两者指向同一channel data structure时结果为真; - 容量大于零都算buffered channel;
cap为零即没有缓冲,发送方要一直等到接收方接收;
< P229 >
- channel被关闭后,后续的发送会引发
panic,而后续的接收只会得到零值;可以增加第二个接受布尔类型的返回值检测是否关闭,更简便的方法是用range,channel关闭后range循环也结束; - 关闭一个已关闭的channel或值为
nil的都会引发panic; - 当GC检测到channel是unreachable时,不管关闭与否都会将其GC,所以关闭channel不是必要的;
< P230 >
- 加上助记符
<-变成unidirectional channel,如<-chan T或chan<- T,表示数据只能单方向传输,会在编译时检查是否有违法的操作; - 对read-only的channel使用
close方法会引发编译错误; - 存在从双向channel到单向的隐式转换,但这种转换是不可逆的;
< P232 >
- 用
len和cap方法查看channel的当前缓存元素个数和容量; - 不要把channel当作队列使用,因为channel和当前goroutine的时序联系很深,可能会阻塞运行;
- goroutine leak发生在goroutine向一个channel发送数据时被阻塞,而该channel之后也不会被取出数据,所以阻塞一直持续;
< P236 >
使用匿名函数的goroutine也要注意变量的捕获,应该用传参或者新的局部变量捕获;
1 | func main() { |
< P245 >
- 没有
case的select结构会wait forever; - 当多个
case都ready时,select随机选择一个运行; - 使用
time.Tick函数会新建一个goroutine,只建议全局都用到的时候才使用,不然会造成goroutine leak;一般推荐使用time.NewTicker,使用返回对象的Stop方法终止计时goroutine; select里的case只能存在channel的接收或发送操作;- 对值为
nil的channel的接收或发送都永远阻塞;配合select可以作为选项开关; select加入default可以用作对channel的查询(polling channel);否则会停留直到其中一个case可行;
< P252 >
poll一个closed channel可以取得零值(以及false)。