如何测量Go并发process函数执行时间?错误排查与修正
问题分析与修正方案
核心错误点
循环变量引用问题
Go的for循环里,photo是复用的同一个变量,所有goroutine都会指向这个变量的内存地址。如果goroutine启动后没立刻执行,循环已经迭代了好几轮,此时photo的值已经变成后续甚至最后一个元素,导致多个goroutine处理同一个photo,计时自然对应不上正确的任务,结果失真。程序提前终止风险
最后那段go func() { wg.Wait() }()完全多余,主goroutine不会等这个匿名goroutine,会直接继续执行(如果后面没别的代码就直接退出),导致所有正在跑的worker goroutine被强制结束,计时结果会被截断,显示的时间远短于实际耗时。输出格式错误
fmt.Println("took %s", time.Since(start))不会解析占位符,会直接把两个参数都输出,结果会是took %s 1.2s这种错误格式,根本看不到正确的计时展示。
修正后的代码
var wg sync.WaitGroup for _, photo := range photos { // 复制当前迭代的photo值,每个goroutine持有独立副本 currentPhoto := photo wg.Add(1) go func() { defer wg.Done() start := time.Now() result := process(currentPhoto) // 用Printf正确格式化输出耗时 fmt.Printf("处理完成,耗时: %s\n", time.Since(start)) }() } // 主goroutine直接等待所有任务完成,避免程序提前退出 wg.Wait()
修正说明
- 复制循环变量:在循环体内新增
currentPhoto := photo,创建当前迭代元素的副本,确保每个goroutine处理的都是本轮循环的正确元素,计时也能对应到真实任务。 - 移除多余的Wait goroutine:直接在主goroutine调用
wg.Wait(),保证所有worker goroutine都执行完毕后,程序才会退出,不会出现任务被中途打断的情况。 - 修正输出方式:改用
fmt.Printf解析占位符,正确输出格式化的耗时信息。
内容的提问来源于stack exchange,提问作者neo
相关产品推荐
相关产品推荐

