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

如何让Go Channel工作池的结果数量与任务数量不同?

解决工作池结果数量与任务数量不一致的阻塞问题

你的问题核心是主 goroutine 固定等待与任务数相等的结果,但部分任务未向结果通道发送数据,导致永久阻塞。这里提供两种可行的解决思路:

方法一:用 WaitGroup 跟踪任务完成,关闭结果通道后读取所有结果

通过 sync.WaitGroup 监控所有任务的完成状态,待所有 worker 处理完任务后关闭结果通道,主 goroutine 用 range 遍历通道读取所有已发送的结果,不会阻塞。

修改后的代码如下:

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

type DemoResult struct {
    Name string
    Rate int
}

func random(min, max int) int {
    return rand.Intn(max-min) + min
}

func worker(id int, jobs <-chan int, results chan<- DemoResult, wg *sync.WaitGroup) {
    defer wg.Done() // 任务完成时标记WaitGroup计数减一
    for j := range jobs {
        fmt.Println("worker", id, "started  job", j)
        time.Sleep(time.Second)
        fmt.Println("worker", id, "finished job", j)
        myrand := random(1, 4)
        if myrand == 2 {
            results <- DemoResult{Name: "succ", Rate: j}
        }
        // 失败时不发送结果
    }
}

func main() {
    rand.Seed(time.Now().UTC().UnixNano()) // 只初始化一次随机数种子
    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan DemoResult)
    var wg sync.WaitGroup

    // 启动worker,每个worker对应一个WaitGroup计数
    for w := 1; w <= 3; w++ {
        wg.Add(1)
        go worker(w, jobs, results, &wg)
    }

    // 发送任务
    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs) // 关闭任务通道,worker会在读完所有任务后退出循环

    // 启动goroutine,等所有worker完成后关闭结果通道
    go func() {
        wg.Wait()
        close(results)
    }()

    // 遍历结果通道,读取所有已发送的结果,直到通道关闭
    for out := range results {
        if out.Name == "succ" {
            fmt.Printf("%v\n", out)
        }
    }
}

方法二:统一发送结果(成功/失败都发)

如果你可以接受每个任务都发送结果,哪怕是失败状态,只需要把注释的 else 分支打开,这样结果通道的元素数量就和任务数一致,主循环的固定次数读取就不会阻塞。这种方式更简单,但需要所有任务都产生结果。

另外注意:你原来的 random 函数每次调用都重新设置随机数种子,会导致生成的随机数重复,建议在 main 函数开头只初始化一次种子,就像上面代码里那样。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:51:22