diff --git a/eBook/14.2.md b/eBook/14.2.md index d70af95eb..700155163 100644 --- a/eBook/14.2.md +++ b/eBook/14.2.md @@ -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 +} +``` + + ## 链接