为了账号安全,请及时绑定邮箱和手机立即绑定

同时选择发送和接收通道

同时选择发送和接收通道

Go
呼啦一阵风 2021-09-13 10:56:44
假设我有一个缓冲发送和非缓冲接收通道:s := make(chan<- int, 5)r := make(<-chan int)是否可以select同时r选择它们,以便在有内容阅读时s将其选中,如果未满则将被选中?与此等效的东西,但不使用 100% CPU:for {    if len(s) < cap(s) {        // Send something    }    if len(r) > 0 {        // Receive something    }}请注意,我想在发送时决定要发送的内容,而不是更早。编辑这个问题基本上相当于“我可以阻塞直到一个通道准备好发送,而不发送任何东西吗?”
查看完整描述

3 回答

?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

您可以这样做,select但由于要发送的值只评估一次,如果两个通道都没有准备好,要发送的值将在可以发送时过时。


因此,添加一个default案例,如果没有任何通道准备好,您将在其中“睡眠”一点,然后再试一次(计算/获取更新的新值以发送)。通过休眠,您不会消耗 CPU 资源:


s := make(chan<- int, 5)

r := make(<-chan int)


for {

    v := valueToSend() // Evaluated each time we try to send

    select {

    case s <- v:

        fmt.Println("Sent value:", v)

    case vr := <-r:

        fmt.Println("Received:", vr)

    default: // If none are ready currently, we end up here

        time.Sleep(time.Millisecond * 1)

    }

}

请注意,检查通道的长度或容量然后发送/接收不被认为是一个好的解决方案,因为在检查其长度/上限和您尝试发送/接收之间,通道可能未准备好,如下图所示:


if len(r) > 0 {

    // r is ready to receive


    // Optional other code here,

    // meanwhile another goroutine might receive the value from r!


    r <-  // If other goroutine received from r, this will block!

}


查看完整回答
反对 回复 2021-09-13
?
慕标5832272

TA贡献1966条经验 获得超4个赞

这是一个简单的选择:


select {

case s <- n:

    // Successful send.

case n := <- r:

    // Successful receive. Do something with n.

}


查看完整回答
反对 回复 2021-09-13
  • 3 回答
  • 0 关注
  • 174 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信