The following piece of code try to send to the channel on the main goroutine and receive from another goroutine but a few times it returns as expected but a few times it exits without printing any on the console screen
package main
import "fmt"
func main() {
ch := make(chan bool)
go func() {
data := <-ch
fmt.Printf("Received: %t", data)
}()
ch <- true
}
At the same time, the following piece of code works as expected everytime, one difference is that an additional check has been added to check if the channel is closed or not which always throws the same expected output. Does this ensure that a check on the channel is a must than optional ? or anything wrong with the code
package main
import "fmt"
func main() {
ch := make(chan bool)
go func() {
data, ok := <-ch
if !ok {
fmt.Println("Channel closed")
return
}
fmt.Printf("Received: %t", data)
}()
ch <- true
}
CodePudding user response:
You should wait for goroutine to complete before main routine exit.
package main
import (
"fmt"
"sync"
)
func main() {
ch := make(chan bool)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
data := <-ch
fmt.Printf("Received: %t", data)
}()
ch <- true
wg.Wait()
}
CodePudding user response:
the code is written upside down.
The push operation blocks on the future read but does not synchronize the execution of the on going routine with the caller thread (main).
If it had pushed async and read sync, it would have worked out of the box.
package main
import "fmt"
func main() {
ch := make(chan bool)
go func() {
ch <- true
}()
data := <-ch
fmt.Printf("Received: %t", data)
}
The problem you describe does not relate to channels, but rather to, synchronizaton mechanisms required to execute in a controlled fashion multiple concurrent routines.
This question specifically does not have a dedicated blog entry to read and learn from, but i guess a careful read of this entry https://go.dev/blog/pipelines or maybe https://go.dev/blog/io2013-talk-concurrency should help you grasp this fundamental concept, among others, along the way.
CodePudding user response:
The thing is your second piece of code doesn't print Received: true every time. I tested it several times.
As @jub0bs mentioned there is no guarantee that your goroutine finishes before the main routine. You must control it yourself.
