select 语句的语法:

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

与switch语句可以选择任何使用相等比较的条件相比,select由比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作

  1. select { //不停的在这里检测
  2. case <-chanl : //检测有没有数据可以读
  3. //如果chanl成功读取到数据,则进行该case处理语句
  4. case chan2 <- 1 : //检测有没有可以写
  5. //如果成功向chan2写入数据,则进行该case处理语句
  6. //假如没有default,那么在以上两个条件都不成立的情况下,就会在此阻塞//一般default会不写在里面,select中的default子句总是可运行的,因为会很消耗CPU资源
  7. default:
  8. //如果以上都没有符合条件,那么则进行default处理流程
  9. }

空的select永远阻塞

select timeout 模式

  1. func main() {
  2. result := make(chan string)
  3. go func() {
  4. //模拟网络访问
  5. time.Sleep(8 * time.Second)
  6. result <- "服务端结果"
  7. }()
  8. select {
  9. case v := <-result:
  10. fmt.Println(v)
  11. case <-time.After(5 * time.Second):
  12. fmt.Println("网络访问超时了")
  13. }
  14. }

检测 chan 是否已经满了

  1. func main() {
  2. ch := make(chan int, 1)
  3. ch <- 1
  4. select {
  5. case ch <- 2:
  6. default:
  7. fmt.Println("channel is full !")
  8. }
  9. }