美文网首页
go 中的 select

go 中的 select

作者: wayyyy | 来源:发表于2021-10-17 11:54 被阅读0次
select
  • 规则
    select 和 IO 复用中的sleect 差不多一个思想,都是想通过多路复用提高效率。
    其满足以下特性:

    • 如果有1个 case 语句满足,那么就执行这一个case

      func main() {
          ch := make(chan int, 1)
          select {
          case ch <-1:
              fmt.Println("ch<-")
          default:
              fmt.Println("default")
      }
      }
      
      // 输出:  ch<-
      
    • 如果多个case 同时满足的情况,会随机选择一个case

      func main() {
          ch1 := make(chan int, 1)
          ch2 := make(chan int, 1)
          select {
          case ch1 <-1:
              fmt.Println("ch1<-")
          case ch2 <-1:
              fmt.Println("ch2<-")
          default:
              fmt.Println("default")
          }
      }
      
      // 输出:多次运行,既有输出 ch2<-,也有输出 ch1<-
      
    • select存在default的话,在case不命中的情况下,会直接进入default分支处理

      func main() {
         timeout := time.After(time.Second * 100)
      
         select {
         case <-timeout:
             fmt.Println("timeout")
         default:
             fmt.Println("default")
         }
      
         fmt.Println("select finish")
      
         for {
         }
      }
      
      // 输出:
      default
      select finish 
      
    • 如果没有 default,那么 代码块会被阻塞,直到有一个 case 通过;否则一直阻塞

      func main() {
          timeout := time.After(time.Second * 10)
      
          fmt.Println("select start")
          select {
          case <-timeout:
              fmt.Println("timeout")
          }
          
          fmt.Println("select finish")
          
          for {
          }
      }
      
      // 输出
      select start
      timeout    // 这里超时10s输出
      select finish
      
  • 应用场景1:阻止main退出

    func main() {
        ...
        select {}
    }
    
  • 应用场景2:生成随机数序列

    func main() {
        ch := make(chan int)
        go func() {
            for {
                select {
                case ch <- 1:
                case ch <- 2:
                case ch <- 3:
                case ch <- 4:
                case ch <- 5:
                case ch <- 6:
                }
            }
        }()
    
        for v := range ch {
            fmt.Print(v, " ")
        }
    }
    
  • 应用场景3:为处理设置超时时间

    c1 := make(chan string)
    timeout := time.After(time.Second * 2)
    
    go func(c chan string) {
        defer fmt.Println("go end", time.Now())
        for {
            select {  
            case str1 := <-c:
                fmt.Println("chan c1 receive:", str1, time.Now())  
            case <-timeout:
                return
             }
        }
    }(c1)
    
    time.Sleep(time.Second * 10)
    

相关文章

网友评论

      本文标题:go 中的 select

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