基本概念
在go语言中,channel既指通道类型,也指代可以传递某种类型的值的通道。通道即某一个通道类型的值,是该类型的一个实例。
值表示法
正因为通道类型是一个引用类型,所以一个通道类型的变量在被初始化之前,其值一定是nil,这也是此类型的零值。
与其他类型不同,通道类型的变量是用来传递值的,也不是存储值的。所以,通道类型并没有对应的值表示法。它的值具有即时性,是无法用字面量来准确表达的。
操作的特性
通道是在多个groutine之间传递数据和同步的重要手段,而对通道的操作本身也是同步的。在同一时刻,仅有一个gorountin能向一个通道发送元素值,同时也仅有一个goriutine能从它那里接收元素值。在通道中,各个元素值都是严格按照发送到此的先后顺序排列的,最早被发送至通道的元素值会最先被接收。因此,通道相当于一个FIFO-先进先出的消息队列。此外,通道中的元素值都具有原子性,是不可被分割的。通道中的每一个元素值都只能被某一个goroutine接收,已被接收的元素值会立刻从通道中删除。
初始化通道
make(chan int, 10)
引用类型的值都需要使用内建函数make来初始化,这个表达式初始化了一个通道类型的值。传递给make函数的第一个参数表明,此值的具体类型是元素类型为了int的通道类型,而第二个参数则指出该通道值在同一时刻最多可以缓冲10个元素的值。一个通道值的缓冲容量总是固定不变的。如果第二个参数被省略了,就表示被初始化的这个通道永远无法缓冲任何元素值。发送给它的元素值应该被立刻取走,否则发送方的goroutine就会被暂停(或者阻塞),直到有接收方接收这个元素值。
接收元素值
接收操作符<-不但可以作为通道类型声明的一部分,也可以用于通道操作(发送或接收)。
elem, ok := <- strlen
当该通道中没有任何元素值时,当前goroutine会被阻塞在此。如果在进行接收操作之前或过程当中该通道被关闭了,那么该操作会立即结束,并且变量elem会被赋予该通道的元素类型的零值。
由于相应元素类型的零值也可以发送到通道中,所以当接收到这样一个元素值的时候,就无法判断它确实是通道中缓冲的一个元素值,还是用来标识该通道已经关闭的标识。这时,在特殊标记:=左边的第二个变量(ok)被赋予的值会提现出实际的情况。因此,变量ok必定会是一个bool。当接收操作因通道关闭而结束时,该值会为false(代表操作是吧),否则为true。
最后,有一点需要注意:视图从一个未被初始化的通道值(即值为nil的通道)那里接收元素值,会造成当前goroutine的永久阻塞!!!
发送元素值
发送语句由通道表达式、接收操作符<-和代表元素值的表达式组成。
strlen <- "a"