Go协程中无法修改scores map问题求助
解决Go Goroutine中无法修改Map的问题
看起来你遇到的问题主要和WaitGroup的使用方式错误以及主goroutine未等待子goroutine完成有关,我来帮你拆解并修复这个问题:
核心问题分析
WaitGroup.Add的时机错误
你在goroutine内部调用wg.Add(1),这是不安全的:主goroutine可能在子goroutine执行到wg.Add(1)之前就调用了wg.Wait(),导致Wait直接返回,子goroutine还没完成逻辑就被终止,自然看不到scores的修改。缺少wg.Wait()调用
代码里没有在主goroutine中等待WaitGroup完成,这会导致主程序在子goroutine执行完之前就退出,子goroutine的修改操作还没执行完毕就被中断。错误被忽略
google(question)的返回错误被直接丢弃,如果google调用失败返回空body,strings.Count结果为0,也会让你误以为scores没被修改。
修复后的代码
scores := make(map[string]int) percentage := make(map[string]float64) total := 0 // 先统一转小写,这部分逻辑没问题 for i, ans := range answers { answers[i] = strings.ToLower(ans) } wg := sync.WaitGroup{} // 关键:把Add移到goroutine启动之前,确保WaitGroup计数正确 wg.Add(1) go func() { // 用defer确保Done一定会被调用,避免panic或提前返回导致WaitGroup一直阻塞 defer wg.Done() body, err := google(question) if err != nil { fmt.Printf("调用google接口失败: %v\n", err) return } for _, ans := range answers { count := strings.Count(body, ans) total += count scores[ans] += 5 // 现在这个修改会正常生效了 } }() // 主goroutine等待子goroutine完成所有操作 wg.Wait() // 这里可以正常访问修改后的scores fmt.Println(scores)
额外说明
- 因为你这里只有一个goroutine修改map,所以不需要用
sync.Map或者互斥锁;如果后续有多个goroutine同时读写map,才需要考虑并发安全的问题。 - 使用
defer wg.Done()是Go并发编程的最佳实践,能保证无论goroutine是正常结束还是遇到错误返回,都能正确标记WaitGroup完成。
内容的提问来源于stack exchange,提问作者Disco Broccoli
相关产品推荐
相关产品推荐

