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

Go中遍历缓冲通道出现阻塞问题咨询

Go语言缓冲通道遍历阻塞问题分析与修复

原问题与阻塞原因

启动两个goroutine向缓冲通道写入数据后,for range遍历通道的代码一直阻塞,后续代码无法执行。

原代码如下:

results := []search.Book{}
resultsStream := make(chan []search.Book, 2)
defer close(resultsStream)

// parallelize searches to optimize response time
for _, src := range sources {
    go src.Search(bookName, resultsStream)
}

counter := 0
for sourceResults := range resultsStream {
    counter = counter + 1
    results = append(results, sourceResults...)

    fmt.Println(counter)
}

fmt.Println("Never called")

程序输出:

1
2

阻塞原因:
Go语言中for range遍历通道时,会持续等待通道的新数据,直到通道被关闭才会退出循环。你代码里的defer close(resultsStream)要等到当前函数执行完毕才会触发,但函数卡在for range循环里永远走不到结尾,导致通道永远不会关闭,循环一直阻塞,后面的代码自然无法执行。

修复方案与代码说明

引入sync.WaitGroup等待所有goroutine完成写入后主动关闭通道,解决了阻塞问题:

var wg sync.WaitGroup
results := []search.Book{}
resultsStream := make(chan []search.Book, len(sources))
defer close(resultsStream)

// parallelize searches to optimize response time
for _, src := range sources {
    wg.Add(1)
    go src.Search(bookName, resultsStream, &wg)
}

wg.Wait()
close(resultsStream)
for sourceResults := range resultsStream {
    results = append(results, sourceResults...)
}

c.JSON(http.StatusOK, gin.H{
    "results": results,
})

关键修改点:

  • 用sync.WaitGroup跟踪所有goroutine:每个goroutine启动前调用wg.Add(1),src.Search执行完成后调用wg.Done()(需确保Search方法内部实现此步骤)
  • 调用wg.Wait()等待所有goroutine完成数据写入,之后主动关闭通道,for range遍历完通道内所有数据后会自动退出循环
  • 通道容量设为len(sources),保证每个goroutine都能顺利写入数据,不会因通道满而阻塞

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:55:30