美文网首页
golang select总结

golang select总结

作者: TimeMage | 来源:发表于2018-02-12 17:43 被阅读40次

    官方文档及理解

    • 每个case都必须是一个通信

    • 所有channel表达式都会被求值

    • 所有被发送的表达式都会被求值

    • 如果任意某个通信可以进行,它就执行;其他被忽略。

    • 如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。否则:

      • 如果有default子句,则执行该语句。
      • 如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。

    个人的理解及注意事项

    • 如果某个表达式无法求值,不会被阻塞,除非所有表达式都无法求值

    • 有多个表达式可以求值,只会执行1个表达式的case且其他表达式相当于没求值一样(测验出来的)

      func main() {
          var (
              a = make(chan int, 1)
              b = make(chan int, 1)//若容量为0,并发函数会阻塞,无法做到同时可以求值 
          )
          go func() {
              a <- 1
              b <- 2
          }()
          for i := 0; i < 1e8; i++ {
              i = i + i - i
          }//让并发函数先执行完
          var x int
          select {
          case x = <-a:
              println("a")
          case x = <-b:
              println("b")
          }
          fmt.Println(x)
          if x == 1 {
              fmt.Println(<-b)
          } else {
              fmt.Println(<-a)
          }
      }
      /*
      结果 b 2 1 或 a 1 2
      */
      
    • 把信道close了,也可以接收到值,若一个信道close,一个信道没close,都可以求值,有可能出现提前退出

      func sel() {
          a, b := make(chan int, 3), make(chan int)
          go func() {
              v, ok, s := 0, false, ""
              for {
                  select { //
                  case v, ok = <-a:
                      s = "a"
                  case v, ok = <-b:
                      s = "b"
                  }
                  if ok {
                      fmt.Println(s, v)
                  } else {
                      fmt.Println("end")
                      os.Exit(0)
                  }
              }
          }()
          close(a)
          for i := 0; i < 5; i++ {
              b <- i
          }
          select {}
      }
      //结果 b 0 end 或 end
      
    • for-select select里面有break 的话只会跳出select

    相关文章

      网友评论

          本文标题:golang select总结

          本文链接:https://www.haomeiwen.com/subject/lgqdtftx.html