Если вы хотите дождаться, пока все процедуры завершатся sh, которые отправляют сообщения по каналу, и после этого вы хотите начать чтение сообщений, тогда у вас нет другого выбора, кроме как использовать буферизованный канал, который может "принимать" все сообщения, которые могут быть отправлены на него горутинами.
Это не что-то практичное. И даже если бы вы go пошли по этому пути, вы могли бы получать и распечатывать сообщения, но выполнение for range
l oop никогда не прекратится, потому что это прекращается только тогда, когда он получает все отправленные сообщения. на канале, прежде чем он был закрыт, но вы никогда не закроете канал. Вы можете проверить это «полуработающее» решение на Go Playground .
. Вместо этого запустите программу, которая ждет, пока другие завершат sh, а затем закройте канал:
go func() {
fmt.Println("WAITING")
wg.Wait()
close(messages)
}()
Так что теперь вы можете использовать for range
для получения сообщений в main
goroutine:
for message := range messages {
fmt.Println(message)
}
fmt.Println("DONE")
Попробуйте это на Go Playground .
Это решение все еще не идеально: оно сначала должно запустить все процедуры, и только затем оно пытается получить значения, и все запущенные программы будут заблокированы при отправке (до готовности main
). чтобы получить их).
Лучшим решением может быть запуск процедуры, которая получает значения, предпочтительно перед процедурами, которые отправляют сообщения по каналу (иначе они все равно будут заблокированы при отправке):
go func() {
for message := range messages {
fmt.Println(message)
}
}()
И дождитесь выполнения программ и закройте канал в конце main()
:
fmt.Println("WAITING")
wg.Wait()
close(messages)
Проблема в том, что когда main()
заканчивается, то и ваше приложение, оно не ждет других не main
Горутин до фини sh. А это значит, что он не будет ждать, пока «потребительская» программа получит сообщения.
Чтобы дождаться этого «потребителя», вы можете использовать дополнительные sync.WaitGroup
:
var wg2 sync.WaitGroup
wg2.Add(1)
go func() {
defer wg2.Done()
for message := range messages {
fmt.Println(message)
}
}()
// And the end of `main()`:
fmt.Println("WAITING")
wg.Wait()
close(messages)
fmt.Println("DONE")
wg2.Wait()
Попробуйте это на Go Детская площадка .