简介channel常见用法 channel是什么意思

今天我们来看看golang当中另一个很重要的概念——信道 。我们之前介绍goroutine的时候曾经提过一个问题 , 当我们启动了多个goroutine之后 , 我们怎么样让goroutine之间保持通信呢?
要回答这个问题就需要用到信道 。
channel信道的英文是channel , 在golang当中的关键字是chan 。它的用途是用来在goroutine之间传输数据 , 这里你可能要问了 , 为什么一定得是goroutine之间传输数据呢 , 函数之间传递不行吗?
因为正常的传输数据直接以参数的形式传递就可以了 , 只有在并发场景当中 , 多个线程彼此隔离的情况下 , 才需要一个特殊的结构传输数据 。
Chan看起来比较怪 , 在其他语言当中基本没有出现过 , 但是它的原理和使用都非常简单 。
我们先来看它的使用 , 首先是定义一个chan , 还是老规矩 , 通过make关键字创建 。我们之前也提过 , golang当中的一个设计原则就是能省则省 , 能简单则简单 。从这个make关键字就看得出来 , 它可以创建的东西太多了 , 既可以创建一个切片 , 也可以创建map , 还可以创建信道 。
所以当我们要创建一个chan的时候 , 可以通过make实现 。
Ch := make(chan int)我们在chan后面跟上一个类型 , 表示这个信道传输的数据类型 。如果你想要传输任何类型呢 , 那可以用我们之前说过的interface{} 。
Chan创建了之后 , 我们想要从其中获取数据或者是把数据放入其中也非常简单 , 简单到都没有api , 直接用形象的传输语句就可以了 。
比如我们现在有一个chan是ch , 我们想要放入数据 , 我们可以这样ch <- a 。我们想要从ch当中获取数据 , 我们可以v := <- ch 。
我们用箭头表示数据的流动 , 是不是很形象很直观呢?

阻塞但是还没完 , chan有一个很关键的点在于 , chan的使用是阻塞的 。也就是说下游从chan当中拿走一个数据我们才可以传入一个数据 。否则的话 , 传输数据的代码就会一直等待chan清空 。
【简介channel常见用法 channel是什么意思】同样 , 如果我们定义了一个从chan当中读取数据的语句 , 假如当前的chan是空的话 , 那么它也会一直阻塞等待 , 直到chan当中有数据了为止 。
所以我们就知道了 , chan的使用场景当中需要一个生产方 , 也需要一个消费方 。我们来看一个golang官方的一个例子:
package mainimport fmtfunc sum(s []int, c chan int) { sum := 0 for _, v := range s {  sum += v } c <- sum // 将和送入 c}func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // 从 c 中接收 fmt.Println(x, y, x+y)}我们启动了两个goroutine去对数组进行求和并进行返回 , goroutine生产的数据是没办法直接return的 , 所以只能通过chan的形式传输出来 。chan传输出来需要下游消费 , 所以上面两个goroutine的数据会传输到x, y: <-c, <-c 这一句语句当中 。
前面说过了 , chan的传输是阻塞的 , 所以这一句语句会一直等待 , 直到上面两个goroutine都计算完成了为止 。

推荐阅读