mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-12 06:36:43 +08:00
Create 14.2.md
This commit is contained in:
61
eBook/14.2.md
Normal file
61
eBook/14.2.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# 14.2 协程间的信道
|
||||
|
||||
## 14.2.1 概念
|
||||
|
||||
在第一个例子中,协程是独立执行的,他们之间没有通信。他们必须通信才会变得更有用:彼此之间发送和接收信息并且协调/同步他们的工作。协程可以使用共享变量来通信,但是很不提倡这样做,因为这种方式给所有的共享内存的多线程都带来了困难。
|
||||
|
||||
而Go有一个特殊的类型,`通道(channel)`,像是通道(管道),可以通过它们发送类型化的数据在协程之间通信,可以避开所有内存共享导致的坑;通道的通信方式保证了同步性。数据通过通道:同一时间只有一个协程可以访问数据:所以不会出现数据竞争,设计如此。数据的归属(可以读写数据的能力)被传递。
|
||||
|
||||
工厂的传送带是个很有用的例子。一个机器(生产者协程)在传送带上放置物品,另外一个机器(消费者协程)拿到物品并打包。
|
||||
|
||||
通道服务于通信的两个目的:值的交换,同步的,保证了两个计算(协程)任何时候都是可知状态。
|
||||
|
||||

|
||||
|
||||
通常使用这样的格式来声明通道:`var identifier chan datatype`
|
||||
|
||||
未初始化的通道的值是nil。
|
||||
|
||||
所以通道稚嫩传输一种类型的数据,比如`chan int`或者`chan string`,所有的类型都可以用于通道,空接口`interface{}`也可以。甚至可以(有时非常有用)创建通道的通道。
|
||||
|
||||
通道实际上是类型化消息的队列:使数据得以传输。它是先进先出(FIFO)结构的所以可以保证发送给他们的元素的顺序(有些人知道,通道可以比作Unix shells中的双向管道(tw-way pipe))。通道也是引用类型,所以我们使用`make()`函数来给它分配内存。这里先声明了一个字符串通道ch1,然后创建了它(实例化):
|
||||
```go
|
||||
var ch1 chan string
|
||||
ch1 = make(chan string)
|
||||
```
|
||||
当然可以更短: `ch1 := make(chan string)`
|
||||
|
||||
这里我们构建一个int通道的通道: `chanOfChans := make(chan chan int)`
|
||||
|
||||
或者函数通道: `funcChan := chan func()`(相关示例请看章节[14.17](14.17.md))
|
||||
|
||||
所以通道是对象的第一类型:可以存储在变量中,作为函数的参数传递,从函数返回以及通过通道发送它们自身。另外它们是类型化的,允许类型检查,比如尝试使用整数通道发送一个指针。
|
||||
|
||||
## 14.2.2 通信操作符 <-
|
||||
|
||||
这个操作符直观的标示了数据的传输:信息按照箭头的方向流动。
|
||||
|
||||
流向通道(发送)
|
||||
|
||||
`ch <- int1`表示:用通道ch发送变量int1(二进制操作符,中缀 = 发送)
|
||||
|
||||
从通道流出(接收),三种方式:
|
||||
|
||||
`int2 = <- ch`表示:变量int2从通道ch(一元运算的前缀操作符,前缀 = 接收)接收数据(获取新值);假设int2已经声明过了,如果没有的话可以写成:`int2 := <- ch`
|
||||
|
||||
`<- ch`可以单独调用获取通道的(下一个)值,当前值会被丢弃,但是可以用来验证,所以以下代码是合法的:
|
||||
```go
|
||||
if <- ch != 1000{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 链接
|
||||
|
||||
- [目录](directory.md)
|
||||
- 上一节:[并发,并行和协程](14.1.md)
|
||||
- 下一节:[协程同步:关闭通道-测试阻塞的通道](14.3.md)
|
Reference in New Issue
Block a user