select:多路复用机制,用于监听多个管道,当我们不知道该怎么去处理channel的关闭时,可使用select
注意:select里的case执行是无序的

用法

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

实例

  1. func main() {
  2. intchan :=make(chan int,10)
  3. primechan :=make(chan int,10)
  4. for i:=0;i<10;i++{
  5. intchan <- i
  6. primechan <- i*2
  7. }
  8. label:
  9. for {
  10. select {
  11. case a:=<-intchan:
  12. fmt.Println("intchan----",a)
  13. case b:=<-primechan:
  14. fmt.Println("primechan---",b)
  15. default:
  16. break label
  17. }
  18. }
  19. }

斐波那契数列

  1. //ch只写,quit只读
  2. func fbn(ch chan<- int, quit <-chan bool) {
  3. x, y := 1, 1
  4. for {
  5. //监听channel数据的流动
  6. select {
  7. case ch <- x: //往里写 。第一次写的时候是1,如果没有地方读的话,那么这里会阻塞
  8. x, y = y, x+y //第一次是往ch写1,y的值也是1,下一次y的值就是x+y
  9. case <-quit:
  10. return
  11. }
  12. }
  13. }
  14. func main() {
  15. ch := make(chan int) //数字通道
  16. quit := make(chan bool) //程序是否结束
  17. go func() {
  18. for i := 0; i < 8; i++ {
  19. num := <-ch //这里读是因为防止select那里会阻塞
  20. fmt.Println(num)
  21. }
  22. quit <- true
  23. }()
  24. fbn(ch, quit)
  25. }

timeout 机制

  1. func main() {
  2. ch := make (chan int)
  3. select {
  4. case <-ch:
  5. case <-time.After(time.Second * 1): //一般不会用time.After
  6. fmt.Println("超时啦!")
  7. }
  8. }

判断channel是否阻塞

  1. func main() {
  2. ch := make (chan int,1) // 注意这里给的容量是1
  3. ch <- 1
  4. select {
  5. case ch <- 2:
  6. default:
  7. fmt.Println("通道channel已经满啦,塞不下东西了!")
  8. }
  9. }