Если вы не обрабатываете возвращаемые значения функции, запущенной как процедура, они отбрасываются.См. Что происходит с возвращаемым значением из goroutine .
. Вы можете использовать срез для сбора результатов, где каждая goroutine может получить индекс для помещения результатов или, альтернативно, адресэлемент.См. Могу ли я одновременно написать разные элементы среза .Обратите внимание, что если вы используете это, срез должен быть предварительно выделен, и может быть записан только элемент, принадлежащий процедуре, вы не можете «трогать» другие элементы и не можете добавлять к срезу.
Или вы можете использовать канал, по которому goroutines отправляют значения, включающие индекс или ID предмета, который они обработали, чтобы goroutine могла идентифицировать или упорядочить их.См. Как собрать значения из N подпрограмм, выполненных в определенном порядке?
Если обработка должна прекратиться при первой обнаруженной ошибке, см. Закрыть несколько прогонов, если в одной из них произошла ошибкаgo
Вот пример того, как это может выглядеть при использовании канала.Обратите внимание, что здесь не нужна группа ожидания, потому что мы знаем, что ожидаем столько значений на канале, сколько мы запускаем подпрограмм.
type result struct {
task int32
data int32
err error
}
func main() {
tasks := []int32{1, 2, 3, 4}
ch := make(chan result)
for _, task := range tasks {
go calcTask(task, ch)
}
// Collect results:
results := make([]result, len(tasks))
for i := range results {
results[i] = <-ch
}
fmt.Printf("Results: %+v\n", results)
}
func calcTask(task int32, ch chan<- result) {
if task > 2 {
// Simulate failure
ch <- result{task: task, err: fmt.Errorf("task %v failed", task)}
return
}
// Simulate success
ch <- result{task: task, data: task * 2, err: nil}
}
Вывод (попробуйте на Go Playground ):
Results: [{task:4 data:0 err:0x40e130} {task:1 data:2 err:<nil>} {task:2 data:4 err:<nil>} {task:3 data:0 err:0x40e138}]