Golang Channel 实战技巧和说明
Channel 的一些实战说明
关于 close Channel
close Channel 的一些说明
channel 不需要通过 close 来释放资源,这个是它与 socket、file 等不一样的地方,对于 channel 而言,唯一需要 close 的就是我们想通过 close 触发 channel 读事件。
- close chan 对 chan 阻塞无效,写了数据不读,直接 close,还是会阻塞的。
- 如果 channel 已经被关闭,继续往它发送数据会导致 panic
send on closed channel
- closed 的 channel,再次关闭 close 会 panic
- close channel 的推荐使用姿势是在发送方来执行,因为 channel 的关闭在接收端能感知到,但是发送端感知不到,因此一般只能在发送端主动关闭。而且大部分时候可以不执行 close,只需要读写即可。
- 从一个已经 close 的 chan 中读取数据,是可以读取的,读到的数据为 0
- 读取的 channel 如果被关闭,并不会影响正在读的数据,它会将所有数据读取完毕,在读取完已发送的数据后会返回元素类型的零值(zero value)。
v, ok := <-ch 判断是否 close
比如 v, ok := <-ch
中 ok 是一个 bool 类型,可以通过它来判断 channel 是否已经关闭,如果 channel 关闭该值为 false ,此时 v 接收到的是 channel 类型的零值。比如:channel 是传递的 int, 那么 v 就是 0 ;如果是结构体,那么 v 就是结构体内部对应字段的零值。
_,ok := <-ch
对应的函数是 func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
,入参block含义是当前goroutine是否可阻塞,当block为false代表的是select操作,不可阻塞当前goroutine的在channel操作,否则是普通操作(即_, ok不在select中)。返回值selected代表当前操作是否成功,主要为select服务,返回received代表是否从channel读到有效值。它有3种返回值情况:
-
block为false,即执行select时,如果channel为空,返回(false,false),代表select操作失败,没接收到值。
-
否则,如果channel已经关闭,并且没有数据,ep即接收数据的变量设置为零值,返回(true,false),代表select操作成功,但channel已关闭,没读到有效值。
-
否则,其他读到有效数据的情况,返回(true,ture)。