You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:15:40