Я учусь Го и играю с Горутинами и каналами.Я писал очень изобретательный и наивный рабочий пул, используя два буферизованных канала, один для входов и один для выходов.
Теперь я закрываю свой входной канал после добавления к нему заданий и затем, наконец, читая выходной канал, чтобы прочитатьрезультаты, однако, когда я использовал for val := range ch
для программы вывода паники с тупиком.Вот пример кода
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
}
}
Вот вывод, который я вижу
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()
Я понимаю, что при использовании обычного for loop
я получаю точное количество значений (9) который я изначально положил в jobs
канал.Но разве for range
не должен обрабатывать это автоматически, когда больше нет данных для чтения из канала, канал отправит значение false
, и цикл прекратится?