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

如何退出频道范围/收集结果

如何退出频道范围/收集结果

Go
一只名叫tom的猫 2021-09-27 10:29:10
我需要同时处理多个任务,然后“收集”结果。下面是我想出的代码,但我想知道这是否是正确的方法(即惯用/最佳实践),或者是否有我可能会错过的错误。package mainimport "fmt"import "sync"func main() {    // ch is the int provider. Cap is 99 but it should     // really be 3    ch := make(chan int, 99)    var wg sync.WaitGroup    for i := 0; i < 3; i++ {        wg.Add(1)        go func(i int) {            defer wg.Done()            ch <- i        }(i)    }    wg.Wait()    for v := range ch {        fmt.Println("consume ", v)        if len(ch) == 0 {            close(ch)        }    }    fmt.Printf("All done")}
查看完整描述

2 回答

?
繁华开满天机

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

没有任何问题......它有效。但是,关闭通道确实应该是生产者的工作(而不是消费者)。


为此..我建议您将整个生产者进程移动到一个goroutine中并等待..然后关闭通道:


package main


import "fmt"

import "sync"


func main() {

    ch := make(chan int, 3)

    var wg sync.WaitGroup


    go func() {

        for i := 0; i < 3; i++ {

            wg.Add(1)

            go func(i int) {

                defer wg.Done()

                ch <- i

            }(i)

        }

        wg.Wait()

        close(ch) // producer is now closing the channel

    }()


    // Consumer has the single responsibility of iterating over the channel

    for v := range ch {

        fmt.Println("consume ", v)

    }

    fmt.Printf("All done")

}

See it in the Go Playground


查看完整回答
反对 回复 2021-09-27
?
开满天机

TA贡献1786条经验 获得超13个赞

我相信你的例子是人为的,但你的例子可以变得更简单:


ch := make(chan int, 99)

for i := 0; i < 3; i++ {

    go func(i int) {

        ch <- i

    }(i)

}

for i := 0; i < 3; i++ {

    v := <- ch

    fmt.Println("consume ", v)

}

fmt.Println("All done")

您的实际代码可能更复杂,并且需要诸如 waitGroup 之类的东西,如果是这种情况,请尽您所能来解释您的具体问题。


关闭一个范围内的通道以退出该范围似乎是不惯用的围棋。


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

添加回答

举报

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