【问题标题】:How to write to the same channel from multiple goroutines如何从多个 goroutine 写入同一个通道
【发布时间】:2019-10-08 16:47:14
【问题描述】:

我需要几个 goroutine 在同一个频道中编写。然后在一个地方读取所有数据,直到所有 goroutine 完成该过程。但我不确定如何最好地关闭此频道。

这是我的示例实现:

func main() {
    ch := make(chan data)
    wg := &sync.WaitGroup{}
    for instance := range dataSet {
        wg.Add(1)
        go doStuff(ch, instance)
    }
    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch { //range until it closes
        //proceed v
    }
}

func doStuff(ch chan data, instance data) {
    //do some stuff with instance...
    ch <- instance
}

但我不确定它是否惯用。

【问题讨论】:

  • 只有一种方式可以写入通道,因此从多个 goroutine 写入通道只有一种方式,即从多个 goroutine 写入通道。所以我不太明白你的问题。
  • 你所做的一切都很好。查看可能的重复项:Closing channel of unknown length。一般来说,发送者应该关闭通道。如果有多个发件人,您需要协调以仅在一个地方关闭通道,仅一次,并且仅在所有发件人都完成工作时才关闭。
  • 您在代码中忘记的一件事:doStuff() 应该调用wg.Done(),最好是延迟。
  • 谢谢!是的,我的方法很好(当然,有 wg.Done() 缺席)。我只想知道它是惯用的吗?还是有更优雅的方式存在?

标签: go concurrency


【解决方案1】:

当你使用WaitGroup并在启动新的goroutine时增加计数器,你必须通过调用Done()方法在goroutine完成时通知WaitGroup。您还必须将相同的 WaitGroup 传递给 goroutine。您可以通过传递WaitGroup 的地址来实现。否则,每个 goroutine 将使用它自己的 WaitGroup,这将在不同的范围内。

func main() {
    ch := make(chan data)
    wg := &sync.WaitGroup{}
    for _, instance := range dataSet {
        wg.Add(1)
        go doStuff(ch, instance, wg)
    }
    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch { //range until it closes
        //proceed v
    }
}

func doStuff(ch chan data, instance data, wg *sync.WaitGroup) {
    //do some stuff with instance...
    ch <- instance

    // call done method to decrease the counter of WaitGroup
    wg.Done()
}

【讨论】:

    猜你喜欢
    • 2015-06-03
    • 2021-09-27
    • 2020-08-02
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多