• Golang select 基础语法与用法


    select语句用来处理与channel有关的I/O操作。

    语法:

    1. 每个case都必须是一个通信;
    2. 所有channel表达式和被发送的表达式都会被求值;
    3. 任意某个通道可以运行,它就执行,其他被忽略;
    4. 多个case可以运行,随机选一个执行;
    5. 都不可以运行,有default,执行default,没有就阻塞,直到某个通信可以运行,且不会重新对表达式求值;
    6. 一个select最多执行一次case里的代码,需要一直检测case,外层加for循环;
    7. case里的break只退出当前select,和for循环无关;

    示例一,执行default:

    func main() {
       ch1 := make(chan int)
       ch2 := make(chan int)
    
       go func() {
          time.Sleep(time.Second)
          ch1 <- 1
       }()
    
       go func() {
          time.Sleep(time.Second)
          ch2 <- 2
       }()
    
       //time.Sleep(2*time.Second)
    
       select {
       case i := <-ch1:
          fmt.Println("ch1 receive:", i)
       case i := <-ch2:
          fmt.Println("ch2 receive:", i)
       default:
          fmt.Println("no i/o operation")
       }
    }
    

    结果总是打印:no i/o operation,因为当主线程走到select时,两个channel所在goroutine里的channel还没有等待写入,输出就会阻塞,执行default。

    示例二,随机执行case:

    func main() {
       ch1 := make(chan int)
       ch2 := make(chan int)
    
       go func() {
          time.Sleep(time.Second)
          ch1 <- 1
       }()
    
       go func() {
          time.Sleep(time.Second)
          ch2 <- 2
       }()
    
       time.Sleep(2 * time.Second)
    
       select {
       case i := <-ch1:
          fmt.Println("ch1 receive:", i)
       case i := <-ch2:
          fmt.Println("ch2 receive:", i)
       default:
          fmt.Println("no i/o operation")
       }
    }
    

    结果随机打印:ch1 receive: 1ch2 receive: 2,因为两个channal等待写入,select里两个case都符合执行条件,随机执行。

    示例三,所有表达式都会被求值:

    func main() {
       ch1 := make(chan int)
       ch2 := make(chan int)
    
       go func() {
          time.Sleep(time.Second)
          <-ch1
       }()
    
       go func() {
          time.Sleep(time.Second)
          <-ch2
       }()
    
       select {
       case getChannel(1, ch1) <- getValue(1):
          fmt.Println("send 1 to ch1")
       case getChannel(2, ch2) <- getValue(2):
          fmt.Println("send 2 to ch2")
       default:
          fmt.Println("no i/o operation")
       }
    }
    
    func getValue(i int) int {
       fmt.Println("getValue:", i)
       return i
    }
    
    func getChannel(i int, ch chan int) chan int {
       fmt.Println("getChannel:", i)
       return ch
    }
    

    结果打印如下,case所有表达式从左到右,从上到下,依次求值:

    getChannel: 1
    getValue: 1
    getChannel: 2
    getValue: 2
    no i/o operation
    

    用法:

    示例一,当有goroutine运行时,用select{} 简单阻塞一下主流程:

    func main() {
       go func() {
          for {
             time.Sleep(5 * time.Second)
             fmt.Println(1)
          }
       }()
       
       select {}
    }
    

    示例二,实现对 channel 操作的超时设置:

    func main() {
       ch1 := make(chan int)
       ch2 := make(chan int)
    
       go func() {
          time.Sleep(5 * time.Second)
          ch2 <- 1
       }()
    
       select {
       case i:= <-ch1:
          fmt.Println("ch1 receive:", i)
       case <-ch2:
          fmt.Println("ch1 receive timeout")
       }
    }
    
    func main() {
       ch := make(chan int)
    
       select {
       case i := <-ch:
          fmt.Println("ch receive:", i)
       case <-time.After(5 * time.Second):
          fmt.Println("ch receive timeout")
       }
    }
    

    示例三,检查 channel 是否已满阻塞:

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

    示例四,退出函数:

    func main() {
       stop := make(chan bool, 1)
       stop <- true
          
       select {
       case i := <-stop:
          if i {
             fmt.Println("已退出")
             return
          }
       default:
          fmt.Println("no i/o operation")
       }
    
       fmt.Println("执行结束")
    }
    

    公众号:李田路口

  • 相关阅读:
    mysql 修改表
    mac下安装MySQL 5.7
    win&linux下path中%%与$ 以及;与:区别,
    PATH
    转 path设置方式
    MyEclipse乱码问题
    03 最大的数据库 information_schema介绍以及sql注入第一题题解
    02.mysql数据库 基本命令
    01.Windows进入MySQL数据库
    Web web4
  • 原文地址:https://www.cnblogs.com/dubinyang/p/14020097.html
Copyright © 2020-2023  润新知