I am new to golang and have a hard time understanding how the channels work. My understanding is that by default, channels are supposed to be blocking, so I expect a goroutine that writes into a channel to be frozen by the scheduler until an other goroutine reads the channel content. So I tried the following code, which gives the corresponding output:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
var v int
func main() {
ch := make(chan string)
wg.Add(2)
go func(ch chan string) {
fmt.Println("Ready to receive")
for msg := range ch {
fmt.Println("received: ", msg)
fmt.Println(v)
}
wg.Done()
}(ch)
go func(ch chan string) {
fmt.Println("Will send the SMS to mama")
ch <- "msg 1"
v += 1
fmt.Println("Done! sent the message 1")
ch <- "msg 2"
v += 1
fmt.Println("Done! sent the message 2")
ch <- "msg 3"
v += 1
fmt.Println("Done! sent the message 3")
close(ch)
wg.Done()
}(ch)
wg.Wait()
}
output:
Will send the SMS to mama
Ready to receive
received: msg 1
0
Done! sent the message 1
Done! sent the message 2
received: msg 2
2
received: msg 3
2
Done! sent the message 3
I am a bit surprised as I was expecting the following order:
and so on. But this is obviously not the case.
Does someone have any idea on why Go behaves this way? Many thanks,
Here is a link to the code https://play.golang.org/p/O6SXf0CslPf. And here are my sources for stating what I said earlier: https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb https://rakyll.org/scheduler/
This behaviour is completely normal so to answer your question
so I expect a goroutine that writes into a channel to be frozen by the scheduler until an other goroutine reads the channel content
Schedular may or may not continue that same goroutine after value is sent through channel unless further synchronization is needed.
So for example After "msg 2" is sent to ch
and is read in another goroutine in the following line
ch <- "msg 2"
goroutine can continue to execute v += 1
and call fmt.Println
before other goroutine calls it.
Also calls to fmt.Println
from different goroutines requires synchronization and possibly mutex
calls which may also reorder print statements.
Further more there is data race on variable v