Понимание каналов Голанга: тупик - PullRequest
0 голосов
/ 09 декабря 2018

Следующий код:

package main

import (
    "fmt"
    "strings"
)

var data = []string{
    "The yellow fish swims slowly in the water",
    "The brown dog barks loudly after a drink ...",
    "The dark bird bird of prey lands on a small ...",
}

func main() {
    histogram := make(map[string]int)
    words := make(chan string)

    for _, line := range data {
        go func(l string) {
            for _, w := range strings.Split(line, " ") {
                words <- w
            }
        }(line)
    }

    defer close(words)
    for w := range words {
        histogram[w]++
    }

    fmt.Println(histogram)
}

оканчивается тупиком:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
    /tmp/sandbox780076580/main.go:28 +0x1e0

Насколько я понимаю, слова канала будут блокировать авторов и читателей для достижения некоторой синхронизации.Я пытаюсь использовать один канал для всех goroutines (писателей) и один читатель в основном (с помощью команды «range»).Я пробовал также с буферизованными каналами - подобные сбои.У меня есть проблемы, чтобы понять, почему это не работает.Любые советы для понимания?
Спасибо.

1 Ответ

0 голосов
/ 09 декабря 2018

Как указано в комментариях к вопросу, отсрочка не выполняется до возвращения основной суммы.В результате диапазон свыше words блокируется навсегда.

Чтобы устранить эту проблему, приложение должно закрыть words, когда все процедуры завершены.Один из способов сделать это - использовать группу ожидания .Группа ожидания увеличивается для каждой программы, уменьшается при выходе из программы.Еще одна программа ожидает группу и закрывает канал.

func main() {
    histogram := make(map[string]int)
    words := make(chan string)

    var wg sync.WaitGroup
    for _, line := range data {
        wg.Add(1)
        go func(l string) {
            for _, w := range strings.Split(l, " ") {
                words <- w
            }
            wg.Done()
        }(line)
    }

    go func() {
        wg.Wait()
        close(words)
    }()

    for w := range words {
        histogram[w]++
    }

    fmt.Println(histogram)
}

Исправление бонуса: процедура в вопросе ссылалась на переменную цикла iine вместо аргумента l.FAQ объясняет, почему это проблема .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...