channel是golang中独有的特性,也是面试中经常被问到的。相信大家都看到过下面这张图,对于不同状态下通道,在操作时会有什么结果。这张图总结的非常好。但我们不能死记硬背这些结果。要了解其底层的基本原理,就能理解这些结果是怎么来的。
我们分三部分来讲。先是channel的基础使用,基础使用提现了channel有哪些特性。再引出channel的底层数据结构。底层数据结构就是围绕这些特性而建立的。最后再看go是如何基于底层数据结构来实现这些特性的。
channel的基础使用
通道的定义和初始化
通过var定义通道
通过var定义一个通道变量ch,这个变量能够接收整型的数据。当然也可以指定其他任何数据类型。
var ch chan int
- ch 代表变量名
- chan固定值。代表ch是通道类型
- int代表在通道ch中存储的是整型数据。
- ch变量的默认值是
nil
。对于nil通道在操作时会有特殊的场景,一会我们也会讲解。
通过make初始化通道
通过make可以初始化无缓冲区通道和缓冲区通道。区别就在于make中是否指定了缓冲区的大小。如下:
var ch = make(chan int) //初始化无缓冲通道
var ch = make(chan int, 10) //缓冲区通道,缓冲区可以存10个元素
无缓冲通道和有缓冲通道的区别可以从属性上和行为两方面来体现:
- 从属性上区别:通道是否有一段缓冲区来暂存元素。
- 从行为上区别:发送者和接收者是否同步的还是异步的。
- 从底层数据结构上区别:是否有一块缓冲区来暂存数据。这个后面会详细讲解。
通道的操作
golang中对于通道有三种操作:往通道中发送元素、从通道中接收元素、关闭通道。如下:往通道中发送元素:
var ch chan int = make(chan int, 10)
2 ->ch //发送元素
var item int
item