I have a snippet of code that I am trying to understand based on how I put the close
call and the location
func main() {
ch := make(chan int, 2)
go func(ch chan int) {
for i := 1; i <= 5; i++ {
ch <- i
fmt.Println("Func goroutine sends data: ", i)
}
//Pos1 - Works perfectly
//close(ch)
}(ch)
fmt.Println("Main goroutine sleeps 2 seconds")
time.Sleep(time.Second * 2)
fmt.Println("Main goroutine begins receiving data")
//Pos2 - Puts in only 2 ints 1 and 2 and then prints only that
//close(ch)
for d := range ch {
fmt.Println("Main goroutine received data:", d)
}
//Pos3 - Throws fatal error
close(ch)
}
I have been trying to understand and read blogs on this but not able to understand somethings still
- When I place the close at Pos1, it works fine. But I am not sure why
it works. The buffer cannot hold more than 2 elements at any given
time, so when 2 elements are written, the loop will block until the
main routing does a read. But I thought to do a range over a
buffered channel, the range function has to know beforehand how many
elements to iterate over and for that channel must be closed. Why
does
close
work at this position? - When I put it as position 2, it prints only 2 elements which kind of makes sense but why is the
for loop
not throwing an exception when it is trying to write more elements to the channel that is closed? - When I close at Pos3, I get an exception
fatal error: all goroutines are asleep - deadlock!
though all 5 ints are printed. Why is that?