This example is taken from http://blog.golang.org/pipelines. It runs and gives correct answer but it shows following runtime error: "fatal error: all goroutines are asleep - deadlock!". Could anyone help me understand why this is happening? package main
import (
"fmt"
)
func gen(nums ...int) <- chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
}()
return out
}
func sq(in <- chan int) <- chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
func main() {
for n := range sq(gen(2,3)) {
fmt.Println(n)
}
}
However the following modification doesn't.
func main() {
// Set up the pipeline.
c := gen(2, 3)
out := sq(c)
// Consume the output.
fmt.Println(<-out) // 4
fmt.Println(<-out) // 9
}
The for n := range in
of the sq()
function never exits, and start blocking (after reading 2 values), because gen()
never closed its channel.
Adding close(out)
to the go func
of gen()
would make it work: see playground.
With channel, the receiver blocks until receiving a value.
The range keyword, when used with a channel, will wait on the channel until it is closed.
sq()
is blocked, which means close(out)
is never called, and in turn main()
blocks on range sq()
(since the channel sq
isn't closed).
In your second example, main()
itself exits, which means even though sq()
is blocked, everything still stops.