|
|
@@ -401,6 +401,63 @@ func suck(ch chan int) {
|
|
|
|
|
|
## 14.2.10 给通道使用For循环
|
|
|
|
|
|
+`for`循环的`range`语句可以用在通道`ch`上,便可以从通道中获取值,像这样:
|
|
|
+```go
|
|
|
+for v := range ch {
|
|
|
+ fmt.Printf("The value is %v\n", v)
|
|
|
+}
|
|
|
+```
|
|
|
+它从指定通道中读取数据直到通道关闭,才继续执行下边的代码。很明显,另外一个协程必须写入`ch`(不然代码就阻塞在for循环了),而且必须在写入完成后才关闭。`suck`函数可以这样写,且在协程中调用这个动作,程序变成了这样:
|
|
|
+
|
|
|
+示例 14.6-[channel_idiom2.go](examples/chapter_14/channel_idiom2.go)
|
|
|
+```go
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "fmt"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+func main() {
|
|
|
+ suck(pump())
|
|
|
+ time.Sleep(1e9)
|
|
|
+}
|
|
|
+
|
|
|
+func pump() chan int {
|
|
|
+ ch := make(chan int)
|
|
|
+ go func() {
|
|
|
+ for i := 0; ; i++ {
|
|
|
+ ch <- i
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ return ch
|
|
|
+}
|
|
|
+
|
|
|
+func suck(ch chan int) {
|
|
|
+ go func() {
|
|
|
+ for v := range ch {
|
|
|
+ fmt.Println(v)
|
|
|
+ }
|
|
|
+ }()
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+习惯用法:通道迭代模式
|
|
|
+
|
|
|
+这个模式用到了前边示例[14.6](exercises/chapter_14/producer_consumer.go)中的模式,通常,需要从包含了地址索引字段items的容器给通道填入元素。为容器的类型定义一个方法`Iter()`,返回一个只读的通道(参见章节[14.2.8](14.2.8.md))items,如下:
|
|
|
+```go
|
|
|
+func (c *container) Iter () <- chan items {
|
|
|
+ ch := make(chan item)
|
|
|
+ go func () {
|
|
|
+ for i:= 0; i < c.Len(); i++{ // or use a for-range loop
|
|
|
+ ch <- c.items[i]
|
|
|
+ }
|
|
|
+ } ()
|
|
|
+ return ch
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+
|
|
|
|
|
|
## 链接
|
|
|
|