I am learning Go and was playing with Goroutines and channels. I was writing a very contrived and naive workerpool using two buffered channels one for inputs and one for outputs.
Now I am closing my inputs channel after I add jobs to it and then reading the output channel finally to read the results from it, however when I used for val := range ch
for the output program panics with a deadlock. Here is the sample code
package main
import (
"fmt"
"time"
)
func main() {
st := time.Now()
jobs := make(chan int, 100)
res := make(chan int, 100)
// Putting items to the jobs channel
for i := 0; i < 9; i++ {
jobs <- i
}
close(jobs)
go workerPool(jobs, res, 1)
// This causes the program to panic with deadlock
for v := range res {
fmt.Println(v)
}
// This works just fine and program does not panics
//for i := 0; i < 9; i++ {
// fmt.Println(<-res)
//}
ed := time.Now()
fmt.Println(ed.Sub(st))
}
func workerPool(ip <-chan int, op chan<- int, id int) {
for v := range ip {
fmt.Println("Worker", id, "working on ", v)
op <- 1
}
}
Here is the output I see
Worker 1 working on 0
Worker 1 working on 1
Worker 1 working on 2
Worker 1 working on 3
Worker 1 working on 4
Worker 1 working on 5
Worker 1 working on 6
Worker 1 working on 7
Worker 1 working on 8
1
1
1
1
1
1
1
1
1
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
I understand that when I use the conventional for loop
I am fetching the exact number of values (9) which I initially put into jobs
channel. But isn't for range
supposed to handle this automatically that when there is no more data to be read from the channel, the channel will send the false
value and the loop will terminate ?