Asynchronous Communication with Channel Readiness
In Go, channels facilitate concurrent communication between goroutines. When dealing with buffered send channels and unbuffered receive channels, it is possible to select on both channels simultaneously to optimize communication flow. This article explores the approach to implement this functionality while minimizing CPU utilization.
To understand the issue, consider the following context:
<code class="go">s := make(chan<- int, 5) // Buffered send channel r := make(<-chan int) // Unbuffered receive channel</code>
The question arises whether it is possible to select on both channels such that r gets selected when data is available to read, and s gets selected when the channel is not full.
Solution
One can achieve this using a select statement with a default case. Since the value to be sent is evaluated only once when using select, if both channels are not ready, the value becomes outdated. To avoid this, a default case is added to the selection statement, which gets executed if neither channel is ready. In this default case, the program sleeps for a short duration, allowing the channels to become ready, and then tries again with an updated value.
<code class="go">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) } }</code>
Warning
Using len(r) or cap(s) to check channel readiness and then sending/receiving is not recommended because the channel may change its state between the check and the attempt to send/receive.
The above is the detailed content of How to Achieve Asynchronous Communication with Channel Readiness in Go While Minimizing CPU Utilization?. For more information, please follow other related articles on the PHP Chinese website!