猿问

同时选择发送和接收通道

假设我有一个缓冲发送和非缓冲接收通道:


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

    }

}

请注意,我想在发送时决定要发送的内容,而不是更早。


编辑

这个问题基本上相当于“我可以阻塞直到一个通道准备好发送,而不发送任何东西吗?”


呼啦一阵风
浏览 175回答 3
3回答

ABOUTYOU

您可以这样做,select但由于要发送的值只评估一次,如果两个通道都没有准备好,要发送的值将在可以发送时过时。因此,添加一个default案例,如果没有任何通道准备好,您将在其中“睡眠”一点,然后再试一次(计算/获取更新的新值以发送)。通过休眠,您不会消耗 CPU 资源:s := make(chan<- int, 5)r := make(<-chan int)for {&nbsp; &nbsp; v := valueToSend() // Evaluated each time we try to send&nbsp; &nbsp; select {&nbsp; &nbsp; case s <- v:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Sent value:", v)&nbsp; &nbsp; case vr := <-r:&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Received:", vr)&nbsp; &nbsp; default: // If none are ready currently, we end up here&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(time.Millisecond * 1)&nbsp; &nbsp; }}请注意,检查通道的长度或容量然后发送/接收不被认为是一个好的解决方案,因为在检查其长度/上限和您尝试发送/接收之间,通道可能未准备好,如下图所示:if len(r) > 0 {&nbsp; &nbsp; // r is ready to receive&nbsp; &nbsp; // Optional other code here,&nbsp; &nbsp; // meanwhile another goroutine might receive the value from r!&nbsp; &nbsp; r <-&nbsp; // If other goroutine received from r, this will block!}

慕标5832272

这是一个简单的选择:select {case s <- n:&nbsp; &nbsp; // Successful send.case n := <- r:&nbsp; &nbsp; // Successful receive. Do something with n.}
随时随地看视频慕课网APP

相关分类

Go
我要回答