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

多Go协程同步屏障实现问题求助

问题排查与修复

先帮你拆解代码里的核心问题,再给出两种可行的修复方案:

核心错误分析

  1. 切片未初始化导致索引越界:你用var ch []chan bool声明了一个nil切片,它的长度为0,直接通过ch[i] = make(chan bool)赋值会触发index out of range panic——切片里根本没有第i个位置的元素可以赋值。
  2. 未定义nb变量:代码里的nb没有声明值,编译阶段就会报错,需要先明确它的取值(比如const nb = 5)。

修复Channel实现的版本

先修正切片初始化的问题,给切片分配足够长度后再逐个创建Channel:

package main

import "fmt"

func goroutine(i int, ch []chan bool) {
    fmt.Printf("协程%d执行中\n", i)
    // 模拟业务逻辑
    // do stuff
    ch[i] <- true
}

func main() {
    const nb = 5 // 先明确协程数量
    ch := make([]chan bool, nb) // 初始化切片,长度为nb
    for i := 0; i < nb; i++ {
        ch[i] = make(chan bool) // 给每个切片元素创建独立Channel
        go goroutine(i, ch)
    }

    // 等待所有协程完成
    for i := 0; i < nb; i++ {
        <-ch[i]
        fmt.Printf("已收到协程%d的完成信号\n", i)
    }

    fmt.Println("所有协程执行完毕,main函数继续执行")
}

更推荐的方案:使用sync.WaitGroup

Go标准库专门提供了sync.WaitGroup用于等待多个协程完成,比手动维护一堆Channel更简洁优雅,可读性也更高:

package main

import (
    "fmt"
    "sync"
)

func goroutine(i int, wg *sync.WaitGroup) {
    defer wg.Done() // 协程结束时自动减少计数,确保即使出错也能正确通知
    fmt.Printf("协程%d执行中\n", i)
    // 模拟业务逻辑
    // do stuff
}

func main() {
    const nb = 5
    var wg sync.WaitGroup

    wg.Add(nb) // 先设置需要等待的协程总数
    for i := 0; i < nb; i++ {
        go goroutine(i, &wg)
    }

    wg.Wait() // 阻塞直到所有协程调用Done,计数归0
    fmt.Println("所有协程执行完毕,main函数继续执行")
}

这里要注意两个关键点:

  • wg.Add(nb)必须在启动协程前调用,避免协程已经执行完Done,Wait还没开始等待
  • 必须传递WaitGroup的指针,值传递会复制一个新的结构体,导致原WaitGroup无法收到完成信号

内容的提问来源于stack exchange,提问作者iAmoric

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:53:06