Go语言用WaitGroup协程+Channel填充数组时程序无响应问题求助
问题分析与修复
你的代码存在几个关键问题,导致程序无法正常返回:
1. 无缓冲通道阻塞goroutine
你创建的c是无缓冲通道(make(chan [3][4]string)),goroutine执行c <- values时,必须有接收方接收数据才能完成发送操作,但代码里没有任何接收通道数据的逻辑,导致所有goroutine都卡在发送步骤,无法执行到defer wg.Done(),最终wg.Wait()会一直等待,程序永远无法结束。
2. goroutine参数传递错误
循环启动goroutine时,你传入的第一个参数是未定义的name,应该传入循环变量idx,否则编译都无法通过。
3. 并发操作共享变量的潜在风险
多个goroutine同时修改同一个数组实例,即便当前修改的是不同索引,这种写法也不符合Go并发安全的最佳实践。另外数组是值类型,每次向通道发送values都会拷贝整个数组,效率极低。
修复后的代码示例
package main import ( "sync" ) func main() { // 使用有缓冲通道,缓冲大小匹配goroutine数量,避免发送阻塞 c := make(chan [3][4]string, 4) mymap := map[int]string{ 0: "www.foo.com", 1: "www.bar.com", 2: "www.baz.com", 3: "www.faz.com", } values := [3][4]string{{"A", "B", "C", "D"}} var wg sync.WaitGroup wg.Add(4) for idx := range mymap { go func(idx int) { defer wg.Done() // 修改对应索引的元素 values[1][idx] = "someone" values[2][idx] = "something" // 发送到通道 c <- values }(idx) // 修正参数传递错误 } // 单独启动goroutine,等待所有任务完成后关闭通道 go func() { wg.Wait() close(c) }() // 接收通道中的数据(按需处理结果) for val := range c { _ = val // 这里可添加具体处理逻辑 } }
优化建议
- 如果不需要收集每个goroutine修改后的数组副本,完全可以去掉通道,仅用WaitGroup等待所有goroutine完成修改即可,通道属于多余设计。
- 优先使用切片代替数组,切片是引用类型,修改和传递更高效。
- 若必须在goroutine中操作共享变量,建议使用
sync.Mutex保证并发安全(即使当前场景无数据竞争,也需养成良好习惯)。
内容的提问来源于stack exchange,提问作者Ufder
相关产品推荐
相关产品推荐

