Ver Fonte

Update 14.4.md

glight2000 há 10 anos atrás
pai
commit
e357fc09c2
1 ficheiros alterados com 84 adições e 0 exclusões
  1. 84 0
      eBook/14.4.md

+ 84 - 0
eBook/14.4.md

@@ -1,5 +1,89 @@
 # 14.4 使用select切换协程
 
+从不不同的并发执行的协程中获取值可以通过关键字`select`来完成,它和`switch`控制语句非常相似(章节5.3)也被称作通信开关;它的行为像是“你准备好了吗”的轮询机制;`select`监听进入通道的数据,也可以是用通道发送值的时候。
+```go
+select {
+case u:= <- ch1:
+        ...
+case v:= <- ch2:
+        ...
+        ...
+default: // no value ready to be received
+        ...
+}
+```
+`default`语句是可选的;fallthrough行为,和普通的switch相似,是不允许的。在任何一个case中执行`break`或者`return`,select就结束了。
+
+`select`做得就是:选择处理列出的多个通信情况中的一个。
+* 如果都阻塞了,会等待直到其中一个可以处理
+* 如果多个可以处理,随机选择一个
+* 如果没有通道操作可以处理并且写了`default`语句,它就会执行:`default`永远是可运行的(这就是准备好了,可以执行)。
+
+在`select`中使用发送操作并且有`default`可以确保发送不被阻塞!如果没有cases,select就会一直阻塞。
+
+`select`语句实现了一种监听模式,通常用在(无限)循环中;在某种情况下,通过`break`语句使循环退出。
+
+在程序[goroutine_select.go](examples/chapter_14/goroutine_select.go)中有2个通道`ch1`和`ch2`,三个协程`pump1()`,`pump2()`和`suck()`。这是一个典型的生产者消费者模式。在无限循环中,`ch1`和`ch2`通过`pump1()`和`pump2()`填充整数;`suck()`也是在无限循环中轮询输入的,通过`select`语句获取`ch1`和`ch2`的整数并输出。选择哪一个case取决于哪一个通道收到了信息。程序在main执行1秒后结束。
+
+示例 14.10-[goroutine_select.go](examples/chapter_14/goroutine_select.go)
+```go
+package main
+
+import (
+	"fmt"
+	"time"
+)
+
+func main() {
+	ch1 := make(chan int)
+	ch2 := make(chan int)
+
+	go pump1(ch1)
+	go pump2(ch2)
+	go suck(ch1, ch2)
+
+	time.Sleep(1e9)
+}
+
+func pump1(ch chan int) {
+	for i := 0; ; i++ {
+		ch <- i * 2
+	}
+}
+
+func pump2(ch chan int) {
+	for i := 0; ; i++ {
+		ch <- i + 5
+	}
+}
+
+func suck(ch1, ch2 chan int) {
+	for {
+		select {
+		case v := <-ch1:
+			fmt.Printf("Received on channel 1: %d\n", v)
+		case v := <-ch2:
+			fmt.Printf("Received on channel 2: %d\n", v)
+		}
+	}
+}
+```
+输出:
+```
+Received on channel 2: 5
+Received on channel 2: 6
+Received on channel 1: 0
+Received on channel 2: 7
+Received on channel 2: 8
+Received on channel 2: 9
+Received on channel 2: 10
+Received on channel 1: 2
+Received on channel 2: 11
+...
+Received on channel 2: 47404
+Received on channel 1: 94346
+Received on channel 1: 94348
+```
 
 ## 链接