为了账号安全,请及时绑定邮箱和手机立即绑定

数据通道关闭时 Goroutines 不退出

数据通道关闭时 Goroutines 不退出

Go
回首忆惘然 2021-08-10 20:43:47
我正在尝试遵循http://blog.golang.org/pipelines/bounded.go上发布的有界 goroutine 示例。我遇到的问题是,如果有更多的工作人员投入工作,那么工作量就会增加,额外的工作人员永远不会被取消。其他一切似乎都有效,值被计算并记录下来,但是当我关闭groups通道时,工作人员只是挂在 range 语句上。我想我不明白(在我的代码和示例代码中)是工人如何知道何时没有更多工作要做以及他们应该退出?更新一个工作(即非工作)示例发布在http://play.golang.org/p/T7zBCYLECp。它显示了工人的僵局,因为他们都睡着了,没有工作要做。我感到困惑的是,我认为示例代码也会有同样的问题。这是我目前使用的代码:// Creates a pool of workers to do a bunch of computationsfunc computeAll() error {    done := make(chan struct{})    defer close(done)    groups, errc := findGroups(done)    // start a fixed number of goroutines to schedule with    const numComputers = 20         c := make(chan result)    var wg sync.WaitGroup    wg.Add(numComputers)    for i := 0; i < numComputers; i++ {        go func() {            compute(done, groups, c)            wg.Done()        }()    }    go func() {        wg.Wait()        close(c)    }()    // log the results of the computation    for r := range c { // log the results }    if err := <-errc; err != nil {        return err    }    return nil}这是用数据填充通道的代码:// Retrieves the groups of data the must be computedfunc findGroups(done <-chan struct{}) (<-chan model, <-chan error) {    groups := make(chan model)    errc := make(chan error, 1)    go func() {        // close the groups channel after find returns        defer close(groups)        group, err := //... code to get the group ...        if err == nil {            // add the group to the channel            select {                case groups <- group:            }        }    }()    return groups, errc}这是读取通道以进行计算的代码。// Computes the results for the groups of datafunc compute(done <-chan struct{}, groups <-chan model, c chan<- result) {    for group := range groups {        value := compute(group)        select {        case c <- result{value}:        case <-done:            return        }    }}
查看完整描述

2 回答

?
MM们

TA贡献1886条经验 获得超2个赞

因为您正在尝试读取errc并且它是空的,除非出现错误。


//编辑


computeAll()<- errc如果没有错误,将始终阻止,另一种方法是使用类似的方法:


func computeAll() (err error) {

    .........

    select {

    case err = <-errc:

    default: //don't block

    }

    return

}


查看完整回答
反对 回复 2021-08-10
?
繁星coding

TA贡献1797条经验 获得超4个赞

尝试像 OneOfOne 所说的那样关闭错误


go func() {

    wg.Wait()

    close(c)

    close(errc)

}()


// log the results of the computation

for r := range c { // log the results }


if err := range errc {

   if err != nil {

    return err

   }

}


查看完整回答
反对 回复 2021-08-10
  • 2 回答
  • 0 关注
  • 193 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信