package main
import "fmt"
func square(numbers chan int, squares chan int) {
for n := range numbers {
squares <- n * n
}
close(squares)
}
func main() {
numbers := make(chan int)
squares := make(chan int)
go square(numbers, squares)
for i := 0; i < 10; i++ {
numbers <- i
}
close(numbers)
for s := range squares {
fmt.Println(s)
}
}
I mean, I understand that for this code to work, numbers should be sent to the numbers
channel in a separate goroutine like:
go func() {
for i := 0; i < 10; i++ {
numbers <- i
}
}
That said, I find it hard to explain why there is a deadlock. It's clear to me that the order of execution is not guaranteed by the scheduler. But isn't it the case that on the first send to numbers
channel in the loop, the main goroutine is blocked but then the scheduler might start executing the square
goroutine and then they will communicate back and forth?
The reason main goroutine blocked is that you don't read any value from squares channel after you send the data into squares channel in this case.
When you execute numbers <- i
, your go square
goroutine will receive the value and send it to squares channel. But, in the meantime, your main goroutine don't receive value from sqaures channel because your main goroutine still send the data into numbers channel.
That means your main goroutine never execute this line for s := range squares
, then it causes the deadlock.
In order to run this code correctly, you could modify it to like below.
package main
import "fmt"
func square(numbers chan int, squares chan int) {
for n := range numbers {
squares <- n * n
}
close(squares)
}
func main() {
numbers := make(chan int)
squares := make(chan int)
go square(numbers, squares)
go func() {
for i := 0; i < 10; i++ {
numbers <- i
}
close(numbers)
}()
for s := range squares {
fmt.Println(s)
}
}