1 select的作用

一个select语句用来选择哪个case中的发送或接收操作可以被立即执行。
它类似于switch语句,但是它的case涉及到channel有关的I/O操作。
select就是用来监听和channel有关的IO操作,当 IO 操作发生时,触发相应的动作。
单Go程下只能监控一个channel的状态,
使用select可以io多路复用, 同时监控多个channel

注意:

  • 每个case 语句都必须是一个面向channel的操作
  • select只会执行其中一条, 如果没有一种case能执行, 则循环判断
  • 如果有一个或多个IO操作可以完成,则Go运行时系统会随机的选择一个执行
  • 否则如果有default分支,则执行default分支语句
  • 如果连default都没有,则select语句会一直阻塞,直到至少有一个IO操作可以进行
  • 如果case里有break, 则只会跳出select语句, 而不会跳出外面的for循环

image.png

2 案例

(1) 多通道选择

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. c := make(chan int)
  7. quit := make(chan int)
  8. go func() {
  9. for i := 0; i < 5; i++ {
  10. fmt.Println("子程收到:", <-c)
  11. }
  12. fmt.Println("子程发送:退出")
  13. quit <- 0
  14. }()
  15. for {
  16. select {
  17. case c <- 1: // 如果成功向c写入2
  18. fmt.Println("写入1")
  19. case c <- 2: // 如果成功向c写入2
  20. fmt.Println("写入2")
  21. case <-quit: // 如果成功从quit读取出数据
  22. fmt.Println("收到退出")
  23. return
  24. default: // 如果上面都没有成功, 就进入default
  25. fmt.Println("default")
  26. }
  27. }
  28. }

(2) 超时控制

  1. select {
  2. case ret := <-retCh:
  3. fmt.Println(ret)
  4. case <-time.After(time.Second):
  5. fmt.Println("time out")
  6. }