go channel doesn't output the data it passed [duplicate]
Behavior cannot be predicted. Sometimes your program would work, sometimes it won't. I have explained the code (with comments) where the problem is happening.
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
fmt.Println("initialized channel")
// This is a receiver receiving from c (spawned goroutine)
go receiver(c)
// This is a sender (spawned goroutine)
go helper(c)
// This is again a receiver receiving from c
// NOTE: As reciever and helper are spawned in
// separate goroutine, control eventually reaches
// here.
// Behaviour is unpredictable as sometimes the data
// sent to the channel might be recieved here and
// sometimes it might be recieved by the receiver function.
for x := range c {
fmt.Println(x)
}
}
func helper(c chan int) {
time.Sleep(time.Second * 3)
c <- 5
time.Sleep(time.Second * 3)
c <- 4
// When this close is triggered, the receiver in main
// could get exited as the signal to stop ranging is sent
// using signal. Right after that the main function ends
// such that data recieved by the receiver couldn't get
// printed (sometimes it would work as well) i.e., main
// exited right before fmt.Println(x) in receiver function.
close(c)
}
func receiver(c chan int) {
for x := range c {
fmt.Println(x)
}
}
To fix it, you can try this. There are more possible solutions, but this is good enough. I have removed time.Sleep
calls as they are not relevant to us and for brevity.
package main
import (
"fmt"
)
func main() {
// Initialize the channel
c := make(chan int)
// Spawn a goroutine that sends data to the
// channel. Also, it is expected from the sender
// only to close the channel as it only knows
// when then send stops. Send to a closed
// channel would panic.
go send(c)
// As send is running asynchronously, control
// reaches here i.e., the receiver. It ranges until
// c is closed and is guaranteed to receive every
// date sent to channel c and then exit.
for x := range c {
fmt.Println(x)
}
}
// send data to c
func send(c chan int) {
c <- 5
c <- 4
close(c)
}