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

今天我们来看看golang中另一个非常重要的概念——渠道 。之前介绍goroutines的时候 , 我们问了一个问题 。在我们启动了几个go routine之后 , 我们如何让go routine保持沟通?

要回答这个问题 , 需要用到渠道 。

引导
channel的英文单词是channel , golang的关键单词是chan 。其目的是在goroutines之间传输数据 。在这里 , 你可能要问了 , 为什么一定要在goroutines之间传输数据呢?不能在函数间传递数据吗?

因为正常的传输数据可以直接以参数的形式传输 , 只有在并发的场景下 , 当多个线程相互隔离时 , 才需要一个特殊的结构来传输数据 。

Chan看起来很奇怪 , 但是在其他语言中根本没有出现过 , 但是原理和应用都很简单 。

我们先来看看它的应用 。首先 , 我们定义一个chan或一个旧规则 , 它是由make关键字创建的 。我们之前提到过 , golang的设计原则之一就是省则省 , 简则简 。从这个make关键字我们可以看出 , 它可以创建的东西太多了 , 比如创建切片 , 创建地图 , 创建通道 。

所以当我们想创造一个改变时 , 我们可以通过make来实现 。
【简介channel常见用法 channel是什么意思】
Ch:=make(chanint)
我们在chan之后跟随一个type , 它显示了这个通道传输的数据的类型 。如果要传输任何类型 , 可以使用我们之前讲过的接口{} 。

Chan成立后 , 很简单 , 我们想从中获取数据或向其中放入数据 。它非常简单 , 没有api , 所以我们可以直接使用生动的传输语句 。

例如 , 我们现在有一个名为ch的变更 , 我们希望将数据放入其中 。我们可以这样做:ch

我们用箭头来表示数据流 。是不是很生动直观?
街区
但这还没有结束 。chan的症结在于chan的应用受阻 。也就是说 , 下游从chan获取一段数据 , 然后我们才能传入一段数据 。否则传输数据的代码会一直期待chan Qing 空 。

同样 , 如果我们定义一个从chan中读取数据的语句 , 如果当前chan是空 , 那么它会阻塞期望 , 直到chan中有数据 。

所以我们知道chan的应用场景需要一个 人和一个花红豆的博主 。让我们来看一个golang的官方例子:
packagemainimport"fmt"funcsum(s[]int,cchanint){sum:=0for_,v:=ranges{sum+=v}c<-sum//将和送入c}funcmain(){s:=[]int{7,2,8,-9,4,0}c:=make(chanint)gosum(s[:len(s)/2],c)gosum(s[len(s)/2:],c)x,y:=<-c,<-c//从c中吸收fmt.Println(x,y,x+y)}
我们启动了两个goroutines来求和并返回数组 。goroutines产生的数据无法直接返回 , 只能通过chan的情况传递 。chan的传输需要下游开销 , 因此上述两个goroutine的数据将被传输到x , y:

正如我前面所说 , chan的传输被阻止 , 所以这句话将被期待 , 直到上述两个goroutine已经计算出来 。

如果你对自己看到的东西感到困惑 , 觉得好像有些人看懂了 , 其实好像没有 , 那么一个很简单的办法就是 , 在看懂的时候 , 改变应用场景 。把chan的应用场景想象成我们之前介绍过的生产者-消费者设计模式 , 其中chan的角色实际上是队列 。

生产者向红豆博客队列传输数据 , 消费者花费这些数据 。唯一不同的是 , 这个队列的容量是1 , 只有生产者和消费者都准备好了 , 才能进行数据传输 。
陈氏缓冲液
如前所述 , chan的容量只有1 , 只有在消费者和生产者都准备好的情况下才能传输数据 。我们也可以缓冲chan 。如果消费者没有时间花完所有的数据 , 允许制造商将数据临时存储在chan中 , 直到chan满了才会被阻塞 。

用法也很简单 。当我们通过make创建chan时 , 我们可以再添加一个参数来表示容量 , 这与我们之前创建切片的原因非常相似 。

Ch:=make(chanint,100)
例如 , 我们创建了一个缓冲区为100的通道 。

但是多说一句 , 其实这种情况并不是很常见 , 原因很简单 。因为高低游的成本情况是统一的 , 如果制片方把快速穿越做得太快 , 支出方跟不上 , 即使暂时存放在缓冲区 , 迟早也会被封杀 。