Я пытаюсь больше узнать о каналах и горутинах go, поэтому я решил создать небольшую программу, которая подсчитывает слова из файла, читаемого объектом bufio.NewScanner
:
nCPUs := flag.Int("cpu", 2, "number of CPUs to use")
flag.Parse()
runtime.GOMAXPROCS(*nCPUs)
scanner := bufio.NewScanner(file)
lines := make(chan string)
results := make(chan int)
for i := 0; i < *nCPUs; i++ {
go func() {
for line := range lines {
fmt.Printf("%s\n", line)
results <- len(strings.Split(line, " "))
}
}()
}
for scanner.Scan(){
lines <- scanner.Text()
}
close(lines)
acc := 0
for i := range results {
acc += i
}
fmt.Printf("%d\n", acc)
Итак, в большинстве примеров, которые я нашел до сих пор, оба канала lines
и results
будут буферизированы, например make(chan int, NUMBER_OF_LINES_IN_FILE)
. Тем не менее, после запуска этого кода моя программа существует с сообщением об ошибке fatal error: all goroutines are asleep - deadlock!
.
В основном я думал, что мне нужны два канала: один для передачи горутине строк из файла (поскольку он может быть любого размера, мне не нравится думать, что мне нужно сообщить размер в вызове функции make(chan)
. Другой канал будет собирать результаты из горутины, и в основной функции я бы использовал его, например, для вычисления накопленного результата.
Каким должен быть лучший вариант программирования таким образом с помощью горутин и каналов? Любая помощь горячо приветствуется.