Go channel 的使用注意项记录

Golang的定义了goroutine间通信的规范,其中对channel的操作有若干注意项及最佳实践。channel 的源码能自解析以下各项条目。


channel:
  • 若使用 channel之前没有 make,会出现fatal error: all goroutines are asleep - deadlock!错误。
  • 如果没有设置buffer,或者buffer设置为0, 说明channel没有缓存,只有senderreceiver都准备好了后它们的通讯才会发生。如果设置了缓存,只有buffer满了后 send才会阻塞, 而只有缓存空了后receive才会阻塞。
  • make channel 的良好代码规范是要么没有buffer,要么buffer设为1, 参见此
  • 往一个已经被closechannel中继续发送数据会导致runtime panic
  • channel 不一定需要被关闭,不再被使用的channel会被gc, 参见此
  • 重复关闭 channel 会导致 runtime panic。在实际编程中, 不适宜在receiver端关闭 channel。在有多个sender的情况下, 也不适合在sender中关闭channel详见此
  • 已关闭的channel也可读, 读出 channel 中已有的数据之后再读就是 channel 类似的默认值,比如 chan int 类型的 channel关闭之后读取到的值为 0
  • 可以关闭一个仍有值被接收的channel
  • 已关闭的channel 永远不会阻塞
  • 只能读的单向channel : ch := make(<-chan int, 1)。只能写的单向channel : ch := make(chan <- int, 1)channel type.
  • 多个goroutine从/往 一个channelreceive/send 数据, 不必考虑额外的同步措施。
  • channel是先进先出的queue,接收的数据和发送的数据的顺序一致。


Select :
  • select中除default外,每个case操作一个channel
  • select中除default外,各case执行顺序是随机的。比如同时有多个channel可以接收数据,那么Go会伪随机的选择一个case处理(pseudo-random)。
  • select中如果没有default语句,则会阻塞等待任一case
  • select语句中包含default和已读取关闭的channelcase, 会执行后者。
  • select可实现超时控制:
select {
  case <- ch:
    // get data from ch
  case <- time.After(2 * time.Second)
    // read data from ch timeout
}
  • select语句中的case也可判断channel是否已关闭:
select {
    case e, ok := <-ch1:
        ...
    case e, ok := <-ch2:
        ...
    default:  
}
  • 要使用select持续读取channel, 一般在selectfor循环且提供退出机制, 如
for{
    select {
        case ...
        case <-ctx.done():
            return
    }
}
  • 关于for{}select{}的开销见此.


Range:
  • range会轮询channel 直到channel关闭, 若channel不关闭会阻塞。
  • 可以防止读取已经关闭的channel造成读到数据为通道所存储的数据类型的零值。
Reference:
  • https://colobu.com/2016/04/14/Golang-Channels/
  • http://www.legendtkl.com/2017/07/30/understanding-golang-channel/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值