【转】GO中的select3个特性

原文链接

作者:大彬
链接:https://segmentfault.com/a/1190000017410112
来源:SegmentFault 思否

select的三个特性

nil的通道永远阻塞
  • 当case上读一个通道时,如果这个通道是nil,则该case永远阻塞
  • 这个功能有1个妙用,select通常处理的是多个通道,当某个读通道关闭了,但不想select再继续关注此case,继续处理其他case,把该通道设置为nil即可。
  • 下面是一个合并程序等待两个输入通道都关闭后才退出的例子,就使用了这个特性。
func combine(inCh1, inCh2 <-chan int) <-chan int {
    // 输出通道
    out := make(chan int)

    // 启动协程合并数据
    go func() {
        defer close(out)
        for {
            select {
            case x, open := <-inCh1:
                if !open {
                    inCh1 = nil
                    continue
                }
                out<-x
            case x, open := <-inCh2:
                if !open {
                    inCh2 = nil
                    continue
                }
                out<-x
            }

            // 当ch1和ch2都关闭是才退出
            if inCh1 == nil && inCh2 == nil {
                break
            }
        }
    }()

    return out
}
如何跳出for-select

break在select内的并不能跳出for-select循环。
看下面的例子,consume函数从通道inCh不停读数据,期待在inCh关闭后退出for-select循环,但结果是永远没有退出。

func consume(inCh <-chan int) {
    i := 0
    for {
        fmt.Printf("for: %d\n", i)
        select {
        case x, open := <-inCh:
            if !open {
                break
            }
            fmt.Printf("read: %d\n", x)
        }
        i++
    }

    fmt.Println("combine-routine exit")
}


//运行结果:
//➜ go run x.go
//for: 0
//read: 0
//for: 1
//read: 1
//for: 2
//read: 2
//for: 3
//gen exit
//for: 4
//for: 5
//for: 6
//for: 7
//for: 8
//... // never stop
跳出for-select3个方法:
  • 在满足条件的case内,使用return,如果有结尾工作,尝试交给defer。
  • 在select外for内使用break挑出循环,如combine函数。
  • 使用goto。
select{}永远阻塞

select{}的效果等价于创建了1个通道,直接从通道读数据:

ch := make(chan int)
<-ch

当你开发一个并发程序的时候,main函数千万不能在子协程干完活前退出,不然所有的协程都被迫退出了,这时候可以用这个阻塞上,防止main函数退出

  • 写了个Web服务程序,端口监听、后端处理等等都在子协程跑起来了,main函数同理不能退出,可使用这个阻塞。
select应用场景
  1. 无阻塞的读、写通道。即使通道是带缓存的,也是存在阻塞的情况,使用select可以完美的解决阻塞读写.
  2. 给某个请求/处理/操作,设置超时时间,一旦超时时间内无法完成,则停止处理。
  3. select本色:多通道处理
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值