Go语言如何并发对切片所有元素执行计算密集型操作?
Go并发处理切片元素的正确实现方案
问题背景
现有切片:
problemArray := []int{77,44,34,752,12}
需对切片中每个元素执行支持并发的计算密集型操作,操作函数定义如下:
func ComputeHeavyOperation(num int) int { time.Sleep(time.Second * 2) return num * 2 }
期望通过SomeNewFunc(problemArray, ComputeHeavyOperation)获取结果,预期输出为[154, 88, 68, 1504, 24](注:原预期中的144为笔误,77*2实际应为154)。
你原有代码的问题分析
你尝试的代码存在两个核心问题:
- 循环变量捕获错误:goroutine中直接引用循环变量
n,由于goroutine执行时机滞后,所有goroutine最终捕获的都是循环结束后的n值(即切片最后一个元素5),因此输出全为10。 - 通道关闭时机错误:
mathematicalCompute启动goroutine后立刻执行defer close(c),此时goroutine还未开始发送数据,主goroutine遍历通道时直接结束,导致仅输出Hello World;注释掉close后,所有goroutine发送完数据后,主goroutine仍在等待通道数据,触发死锁。
正确实现方案
保持原顺序的实现(推荐)
该方案通过sync.WaitGroup等待所有goroutine完成,同时保证结果顺序与原切片一致:
package main import ( "fmt" "sync" "time" ) func ComputeHeavyOperation(num int) int { time.Sleep(time.Second * 2) return num * 2 } func SomeNewFunc(arr []int, op func(int) int) []int { result := make([]int, len(arr)) var wg sync.WaitGroup for i, n := range arr { wg.Add(1) // 将当前索引和元素值作为参数传入goroutine,避免循环变量捕获问题 go func(idx int, num int) { defer wg.Done() result[idx] = op(num) }(i, n) } // 等待所有goroutine执行完毕 wg.Wait() return result } func main() { problemArray := []int{77, 44, 34, 752, 12} output := SomeNewFunc(problemArray, ComputeHeavyOperation) fmt.Println(output) // 输出: [154 88 68 1504 24] }
流式通道实现(结果顺序随机)
如果不需要保持原顺序,可通过通道流式接收结果:
func SomeNewFuncWithChan(arr []int, op func(int) int) []int { result := make([]int, 0, len(arr)) c := make(chan int, len(arr)) var wg sync.WaitGroup for _, n := range arr { wg.Add(1) go func(num int) { defer wg.Done() c <- op(num) }(n) } // 单独启动goroutine,等待所有任务完成后关闭通道 go func() { wg.Wait() close(c) }() // 遍历通道收集结果 for val := range c { result = append(result, val) } return result }
内容的提问来源于stack exchange,提问作者Hassan Shahzad
相关产品推荐
相关产品推荐

