Is there a priority rule between sent and receive operation in a go select statement ?
Since a "send" operation is always ready, not like a "receive" operation that wait for something to come from the channel, I always have the feeling that the "send" will be executed first on a select.
I tried a little to code to test what happens when both send and receive are ready:
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go goOne(ch1)
go goTwo(ch2)
time.Sleep(time.Second * 2)
select {
case ch2 <- "To goTwo goroutine":
case msg1 := <-ch1:
fmt.Println(msg1)
}
}
func goOne(ch chan string) {
ch <- "From goOne goroutine"
}
func goTwo(ch chan string) {
msg := <-ch
fmt.Println(msg)
}
The result seems to always be "From goOne goroutine". So it seems the receive operation has the priority. But is it by design effect ? Or could it happen that the sent got executed first? I couldn't find the info in the doc
If I want the receive operation to have the priority, can I rely on that or should I do something else ?
Thanks!
CodePudding user response:
Is there a priority rule between sent and receive operation in a go select statement?
No. When more than one case
is ready at the same time, one at random is executed.
Since a "send" operation is always ready
Not true. A send operation may just block (i.e. not ready) when nothing is receiving on the other side, or when a buffered channel's buffer is full.
Or could it happen that the sent got executed first?
Yes, but you may see no output when this case is selected because your program resumes execution in main and exits immediately before the goTwo
goroutine can actually print anything.
If I want the receive operation to have the priority [...]
The very semantics of a select statement are: "execute whichever is ready first". If one case must have priority over the other, change the other one to default
(runs if nothing else is ready):
select {
case msg1 := <-ch1:
fmt.Println(msg1)
default:
ch2 <- "To goTwo goroutine"
}