在回忆管道方向的语法上时不时地会出错,所以搜罗一些资料以加强自身的记忆。
基础
channel 是 Go 提供同步的、强类型的消息传输功能的一种数据结构,搭配上 goroutine,构建了 Go 的 Communicating Sequential Processes(CSP)并发模型。
channel 和 goroutine 是 Go 的 CSP 并发模型的基石。
定义一个 channel 只需要一个 chan
关键字及 channel 中传输的元素的类型,如:
var c chan int
// 或
c := make(chan int)
默认情况下,channel 的双向的,即 channel 的一端可读、另一端可写。因为没有定义 channel 的方向,在编写程序的过程中,很有可以向一个已关闭的 channel 发送信息。比较优的编码实践应该在代码中指定 channel 的方向。
channel 的方向
操作符 <-
用于指定 channel 是方向,表示读或写的操作。由此可知,声明一个 channel 有 3 种方式:
var c chan int // 双向
var c <-chan int // 只能读
var c chan<- int // 只能写
记忆方式:
<-chan // 从 channel 中来
chan<- // 到 channel 中去
值得注意的是,一开始的 channel 声明可以是双向的,并且可以作为参数的过程中指定 channel 的方法,这样就可以避免在读取 channel 的过程中关闭 channel(因为只有写 channel 的代码才有权限关闭 channel)。
只读的 channel 不能被关闭。
在函数签名中,也应该使用带有方向的 channel 作为参数类型或返回值类型,除非在某一函数中完全使用双向的 channel。
func ReturnReadOnly() <-chan int {
c := make(chan int)
// ...
return c
}
// 因为 ReturnReadOnly 返回的是只读的 channel,所以 readOnly 是只读的
// 但在 ReturnReadOnly 函数中声明的是一个双向的 channel `c := make(chan int)`
readOnly := ReturnReadOnly()
使用带方向的 channel 的好处:
- 事先声明 channel 的读写性质;
- 编写的 channel 相关代码语义明显;
评论