select语句是专门为通道设计的,它可以包含若干个候选分支,每个分支中的case表达式都会包含针对摸个通道的发送活接收操作。

基础语法

  1. select {
  2. case <-chan1:
  3. // 接收操作,如果成功从chan1读到数据,则进行该case处理语句
  4. case ret, open := <-chan2:
  5. // 接收操作,如果成功从chan2读到数据,则进行该case处理语句
  6. // ret: 从chan2读到的值,通道关闭时,ret为该类型的零值
  7. // open: 用来判断chan2是否关闭。关闭通道使用close(retCh)
  8. case chan3 <- 1:
  9. // 发送操作,如果成功向chan3写入数据,则进行该case处理语句
  10. case <-time.After(time.Second * 1):
  11. // 1秒后超时,存在default时,永远不会超时
  12. default:
  13. // 如果所有case语句都未执行,则进行default处理语句
  14. }

分支选择规则

  1. 对于每一个case表达式,都至少会包含一个发送操作或一个接收操作,同时也可能会包含其他表达式。

    • 如果case表达式是包含了接收表达式的短变量声明时,那么在赋值符号左侧的就可以是一个或者两个表达式(表达式的结果必须是可被赋值的)。
    • 上述case表达式被求值时,它包含的多个表达式总会以从左到右的顺序被求值。
  2. 在select语句开始执行时,所有候选分支中的case表达式都会在先被求值,且求值的顺序是依从代码编写的顺序从上到下的。

    即,排在最上边的候选分支中最左边的表达式会最先被求职,然后是它右边的表达式,仅当最上边的候选分支中的所有表达式都被求值完毕后,上数第二个候选分支中的表达式才会被求值,顺序同样是从左到右,以此类推。

  3. 仅当select语句中的所有case表达式都被求值完毕后,它才会开始选择候选分支。

  4. 满足条件时执行分支。所有候选分支都不满足条件时,执行默认分支。若默认分支不存在,则select语句所在goroutine被阻塞,直到某一候选分支的条件被满足。
  5. 一个select中只能有一个默认分支。默认分支只有在所有候选分支的条件都不满足时被执行,这与它的编写位置无关。
  6. select语句的每次执行、case表达式求值以及分支选择都是独立的。
  7. select是否并发安全取决于case表达式和分支中的代码是否并发安全。