Home > Backend Development > Golang > Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?

Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?

Susan Sarandon
Release: 2024-10-26 22:34:31
Original
958 people have browsed it

 Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?

Selecting on Bidirectional Channels for Conditional Sending and Receiving

In Go, it's possible to set up buffered channels for both sending and receiving, allowing selective operations based on their availability. Consider the following scenario:

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)
Copy after login

We have a buffered send channel s and an unbuffered receive channel r. The question arises: can we select on both channels to determine if r has data or s is not full? This mimics the functionality of the following, but without consuming 100% CPU:

<code class="go">for {
    if len(s) < cap(s) {
        // Send something
    }
    if len(r) > 0 {
        // Receive something
    }
}</code>
Copy after login

Implementing Select with a Default Case

To achieve this, we can utilize the select statement with a default case. In the default case, if neither channel is ready, we temporarily "sleep" the goroutine to avoid unnecessary resource consumption.

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

for {
    v := valueToSend() // Value to be sent, evaluated upon each attempt
    select {
    case s <- v:
        fmt.Println("Sent value:", v)
    case vr := <-r:
        fmt.Println("Received:", vr)
    default: // Neither channel is ready, pause briefly
        time.Sleep(time.Millisecond * 1)
    }
}
Copy after login

Why Length and Capacity Checks Are Not Ideal

It's crucial to avoid checking the length or capacity of a channel before attempting to send or receive. This is because the channel's state can change between the time of checking and the actual operation, potentially leading to unexpected blocking. For instance:

<code class="go">if len(r) > 0 {
    // r is ready to receive

    // Other code...

    r <-  // This may block if another goroutine has already received from r!
}</code>
Copy after login

The above is the detailed content of Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template