Что касается небуферизованных каналов, вы, кажется, понимаете концепцию, то есть она используется для передачи сообщений между программами, но не может их содержать. Поэтому запись в небуферизованном канале будет блокироваться до тех пор, пока другая программа не будет считывать данные с канала, а чтение из канала будет блокироваться до тех пор, пока другая программа не выполнит запись в этот канал.
В вашем случае вы, кажется, хотите читать с 2 каналов одновременно в одной и той же программе. Так как каналы работают, вы не можете располагаться на незакрытом канале и дальше в том же диапазоне подпрограмм на другом канале. Пока первый канал не закроется, вы не достигнете второго диапазона.
Но это не значит, что это невозможно! Вот где приходит оператор select
.
Оператор select
позволяет выборочно читать по нескольким каналам, что означает, что он будет читать первый, который имеет что-то доступное для чтения.
Имея это в виду, вы можете использовать for
в сочетании с select
и переписать свою программу следующим образом:
go func() {
for {
select {
case err := <- errs: // you got an error
fmt.Println(err)
case res := <- results: // you got a result
fmt.Println(res)
}
}
}()
Кроме того, вам здесь не нужна группа ожидания, потому что вы знаете, сколько рабочих вы запускаете, вы можете просто посчитать, сколько ошибок и результатов вы получите и остановить, когда достигнете числа рабочих.
Пример:
go func() {
var i int
for {
select {
case err := <- errs: // you got an error
fmt.Println(err)
i++
case res := <- results: // you got a result
fmt.Println(res)
i++
}
// all our workers are done
if i == len(toProcess) {
return
}
}
}()