Go 里面提供了一个关键字 select,通过 select 可以监听 channel 上的数据流动

语法

select - 图1

  1. select 的用法与 switch 语言非常类似,但区别在于/要求 1. 开头无字段 2. 每个 case 语句里必须是一个 IO 操作,或者什么都不写,默认执行 3. default语句可省略
  2. 判断标准 1. 执行这个case里的IO操作,并判断是否成功,若成功,则执行case内容,若阻塞,则不执行 2. 成功
    如果有两个及以上的case满足条件,那么会随机公平的选出一个执行,其他不会执行 3. 阻塞
    ——如果没有可运行的case,那么有两种可能的情况: 1. 如果给出了 default 语句,那么就会执行 default 语句,同时程序的执行会从 select 语句后的语句中恢复。 2. 如果没有 default 语句,那么 select 语句将被阻塞,直到至少有一个通信可以进行下去。

:::info 实例——斐波那契数列

:::

  1. package main
  2. import "fmt"
  3. func fibonacci(ch1 chan<- int, quit1 <-chan bool){
  4. x,y :=1, 1
  5. for{ //套在无限循环中,等命令进行来结束
  6. select {
  7. case ch1<-x:
  8. x,y = y, x+y
  9. case <-quit1:
  10. fmt.Println("quit")
  11. return
  12. }
  13. }
  14. }
  15. func main() {
  16. ch := make(chan int) //数字通信
  17. quit := make(chan bool)//用来命令计算结束的
  18. go func() {
  19. for i:=0; i<8; i++{ //计算数列个数为8的斐波那契数列
  20. fmt.Println(<-ch)
  21. }
  22. quit<-true
  23. }()
  24. fibonacci(ch, quit) //ch在main作用域中,是双向的,在函数中是单向的,但由于channel是引用类型
  25. }

select - 图2回j结果select - 图3

超时

实际工程中,阻塞不能永远执行下去,若超时,必须有个退出

  1. 语法:case: <-time.After(n*time.Second)
  2. 实例1
    select - 图4
    结果:
    select - 图5
  3. 实例2——上面例子的有数据的时候
    select - 图6
    结果:
    select - 图7