
本文详解 Go 中因闭包变量捕获导致的 goroutine 数据竞争问题,通过显式传参修复循环启动 goroutine 时的 item 变量误用,并结合 channel 收集结果、同步等待,实现安全高效的并发字符串拼接。
本文详解 go 中因闭包变量捕获导致的 goroutine 数据竞争问题,通过显式传参修复循环启动 goroutine 时的 `item` 变量误用,并结合 channel 收集结果、同步等待,实现安全高效的并发字符串拼接。
在 Go 并发编程中,一个常见却隐蔽的陷阱是:在 for 循环中直接启动 goroutine 并引用循环变量(如 item),由于该变量在整个循环作用域内复用,所有 goroutine 实际共享同一内存地址,最终可能读取到错误或已变更的值——这正是原代码中 str 未被正确拼接的根本原因。
? 问题定位:闭包捕获的是变量地址,而非值快照
原始代码中:
item
- 永远不要在 goroutine 闭包中直接引用循环变量;务必通过函数参数显式传递;
-
避免多个 goroutine 并发写同一变量(包括
string,int,slice等);优先采用 channel + 单写者模式; - 使用
len(list)控制接收次数,比基于atomic的轮询更简洁、高效、无忙等待; - 若需更健壮的错误处理或超时控制,可配合
sync.WaitGroup或context.Context; - 开发阶段建议启用
go run -race检测数据竞争问题。
通过以上重构,代码既解决了原始逻辑缺陷,又符合 Go 并发最佳实践:共享内存通过通信(channel)来完成,而非通过通信来共享内存。











