Ваша основная проблема заключается в том, что все в этом «мёртвом расчёте»: они ожидают увидеть фиксированное количество сообщений, но это не обязательно совпадает с реальностью.Вы должны настроить каналы так, чтобы они закрывались после получения всех их данных.
Это, вероятно, означает настройку промежуточной функции для управления отправкой:
func Sender(from, to int, c chan<- int) {
for i := from; i < to; i++ {
c <- i
}
}
func SendEverything(c chan<- int) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
Sender(0, 20, c)
}()
go func() {
defer wg.Done()
Sender(11, 20, c)
}()
wg.Wait()
close(c)
}
Создание диспетчераФункция работает со всем в канале:
func Receive(c <-chan int, odds, evens chan<- int) {
for n := range c {
if n%2 == 0 {
evens <- n
} else {
odds <- n
}
}
close(odds)
close(evens)
}
И затем вы можете поделиться единственной функцией печати:
func Printer(prefix string, c <-chan int) {
for n := range c {
fmt.Printf("%s: %d\n", prefix, n)
}
}
Наконец, у вас есть основная функция, которая объединяет все вместе:
func main() {
var wg sync.WaitGroup
inputs := make(chan int)
odds := make(chan int)
evens := make(chan int)
wg.Add(4)
go func() {
defer wg.Done()
SendEverything(inputs)
}()
go func() {
defer wg.Done()
Receive(inputs, odds, evens)
}()
go func() {
defer wg.Done()
Printer("odd number", odds)
}()
go func() {
defer wg.Done()
Printer("even number", evens)
}()
wg.Wait()
}
Полный пример приведен по адресу https://play.golang.org/p/qTUqlt-uaWH.
Обратите внимание, что я полностью воздержался от использования каких-либо глобальных переменных, и, как мы надеемся, каждое из них имеет самоочевидное очень короткое имя (i
и n
- простые целые числа, c
- канал) или полные слова (odds
, evens
).Я обычно держу sync.WaitGroup
объекты локально в том месте, где они были созданы.Поскольку все передается как параметры, мне не нужны две копии одной и той же функции для работы с разными глобальными переменными, и если я решу написать тестовый код для этого, я могу создать свои собственные локальные каналы.