控制结构,类似于switch,用于通讯(channel),监听IO操作,case为面向channel的IO操作(发送或者接收数据)。

    select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。

    select 语句的语法:

    • 每个 case 都必须是一个通信
    • 所有 channel 表达式都会被求值
    • 所有被发送的表达式都会被求值
    • 如果任意某个通信可以进行,它就执行,其他被忽略。
    • 如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。
      否则:
      1. 如果有 default 子句,则执行该语句。
      2. 如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。

    典型用法:

    • 超时判断
      ```go // 使用全局resChan来接受response,如果时间超过3S,resChan中还没有数据返回,则第二条case将执行 var resChan = make(chan int) func test() { select { case data := <-resChan:
      1. doData(data)
      case <-time.After(time.Second * 3):
      1. fmt.Println("request time out")
      } }

    func doData(data int) { //… }

    1. - 退出
    2. ```go
    3. var shouldQuit=make(chan struct{})
    4. fun main(){
    5. {
    6. //loop
    7. }
    8. //...out of the loop
    9. select {
    10. case <-c.shouldQuit:
    11. cleanUp()
    12. return
    13. default:
    14. }
    15. //...
    16. }
    17. //再另外一个协程中,如果运行遇到非法操作或不可处理的错误,就向shouldQuit发送数据通知程序停止运行
    18. close(shouldQuit)
    • 判断channel是否阻塞
      1. //在某些情况下是存在不希望channel缓存满了的需求的,可以用如下方法判断
      2. ch := make (chan int, 5)
      3. //...
      4. data:=0
      5. select {
      6. case ch <- data:
      7. default:
      8. //做相应操作,比如丢弃data。视需求而定
      9. }