多Go协程同步屏障实现问题求助
问题排查与修复
先帮你拆解代码里的核心问题,再给出两种可行的修复方案:
核心错误分析
- 切片未初始化导致索引越界:你用
var ch []chan bool声明了一个nil切片,它的长度为0,直接通过ch[i] = make(chan bool)赋值会触发index out of rangepanic——切片里根本没有第i个位置的元素可以赋值。 - 未定义
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
相关产品推荐
相关产品推荐

