channel 管道
channel是通过通信的方式来共享内存,而不是通过共享内存来通信
channel创建
Channel是引用类型,声明方式如下:
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
其中:
-
chan channel类型关键字
-
<- 操作符,用于Channel收发,定义Channel类型时,用于表示Channel的方向:
- 默认是双向,可收可发。还可以定义为定向的,仅收仅发。
- chan<- 仅发送Channel
- <-chan 仅接收Channel
-
ElementType Channel中元素类型
ch := make(chan int)
var ch = make(chan int)
ch := make(chan int, 10) // 定义一个容量为10的缓冲管道
ch := make(<-chan int) // 只读
ch := make(chan<- int, 10) // 只可以写
未使用make()初始化的 channel 为 nil 。nil channel不能执行收发通信操作,例如:
var ch chan int // nil
ch就是nil channel。
Send语句语法:
SendStmt = Channel "<-" Expression .
Channel = Expression .
ch <- Expression
ch <- 42
ch <- f()
接收操作符语法:
<-ch
v1 := <-ch // 声明
v = <-ch // 赋值
f(<-ch) // 函数调用
<-strobe // 等待接收
channel关闭
通过close(ch)关闭管道。
关闭Channel的意思是记录该Channel不能再被发送任何元素了「不能再向管道放数据」,而不是销毁该Channel的意思。也就意味着关闭的Channel是可以继续接收值的「可以从管道拿出数据」。因此:
- 向已关闭的Channel发送会引发runtime panic
- 关闭nil Channel会引发runtime panic
- 不能关闭仅接收Channel
- 不能关闭已经关闭的Channel,否则会引发runtime panic
当从已关闭的Channel接收时:
- 可以接收关闭前发送的全部值
- 若没有已发送的值会返回类型的零值,不会被阻塞
使用接收操作符的多值返回结构,可以判断Channel是否已经关闭:
var x, ok = <-ch
x, ok := <-ch
- ok为true,channel未关闭
- ok为false,channel已关闭
缓冲和无缓冲channel
Channel区别于是否存在缓冲区,分为:
-
缓冲Channel,make(chan T, cap),cap是大于0的值。
适合用于goroutine的通信
-
无缓冲Channel, make(chan T), make(chan T, 0)
适合做goroutine的信号
单向channel
单向Channel,指的是仅支持接收或仅支持发送操作的Channel。语法上:
chan<- T仅发送Channel<-chan T仅接收Channel
单向Channel的意义在于约束Channel的使用方式。
仅使用单向Channel通常没有实际意义,单向Channel最典型的使用方式是:
使用单向通道约束双向通道的操作。
语法上来说,就是我们会将双向Channel转换为单向Channel来使用。典型使用在函数参数或返回值类型中。