如果不处理作为 goroutine 启动的函数的返回值,它们将被丢弃。看goroutine 返回值会发生什么 https://stackoverflow.com/questions/27868369/what-happens-to-return-value-from-goroutine/27870734#27870734.
您可以使用切片来收集结果,其中每个 goroutine 可以接收要放置结果的索引,或者元素的地址。看我可以同时写入不同的切片元素吗 https://stackoverflow.com/questions/49879322/can-i-concurrently-write-different-slice-elements/49879469#49879469。请注意,如果您使用此功能,则必须预先分配切片,并且只能写入属于 goroutine 的元素,您不能“触摸”其他元素,也不能追加到切片。
或者您可以使用一个通道,goroutine 在该通道上发送包含它们处理的项目的索引或 ID 的值,以便收集 goroutine 可以识别它们或对它们进行排序。看如何从按特定顺序执行的 N 个 goroutine 中收集值? https://stackoverflow.com/questions/37856337/how-to-collect-values-from-n-goroutines-executed-in-a-specific-order/37857863#37857863
如果处理应在遇到第一个错误时停止,请参阅如果 go 中的一个 goroutine 发生错误,则关闭多个 goroutine https://stackoverflow.com/questions/45500836/close-multiple-goroutine-if-an-error-occurs-in-one-in-go/45502591#45502591
下面是使用通道时的示例。请注意,这里不需要等待组,因为我们知道我们期望通道上的值与我们启动的 goroutine 一样多。
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}
}
输出(尝试一下去游乐场 https://play.golang.org/p/CL0-jF_Vu2V):
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}]