我怎样才能拥有一个 goroutine 函数来等待来自多个其他函数的值?

How can I have a single goroutine function that waits for values from multiple others?

我创建了一个 Go playground sample 来说明我在说什么。

在这个例子中,我创建了一个 goroutine,func2,我只是想通过它的通道等待输入并在它到达时打印值。

func func2(ch chan int) {
    fmt.Println("func2")
    v:=<-ch
    fmt.Println(v)
}

然后,在一个循环中,我为另一个函数创建了 goroutine,它们是 WaitGroup 的一部分。

func func1(ch chan int, wg *sync.WaitGroup) {
    fmt.Println("func1")
    ch <- 11032
    wg.Done()
}

在主要部分,我等待 WaitGroup。我 运行 陷入了僵局,我不确定如何解决它。为了清楚我要实现的目标,我希望 func2 在我调用它后作为线程保持打开状态,以处理 n 个值,其中 n 是我为 func1 调用的 goroutines 的数量。我考虑过在 func2 中使用 WaitGroup Wait,但我不希望它阻塞,因为它需要在发送新数据时处理来自 func1 的新数据。

您正在寻找的是一种在所有值流过后关闭通道的简洁方法。当新值出现时,您可以创建一个新频道并开始在其上流式传输值。我就是这样做的,也许有帮助

var wg sync.WaitGroup

toUpdate := make(chan *someType, BufferSize)

for i := 0; i < BufferSize; i++ {
    go processEvents(toUpdate, &wg)
}

// // wait till all the checks have come back
go func(toUpdate chan * someType, group *sync.WaitGroup) {
    group.Wait()
    close(toCreate)
}(toCreate, toUpdate, &wg)

我认为您陷入了僵局,因为您的 func2 仅消耗了 ch1 值,然后完成。然后其他 func1 goroutines 被卡住等待 ch 可以写入,他们不能这样做,因为在另一端没有其他 goroutine 可以从 ch 读取。

由于您希望 func2 持续使用 ch 中的值直到 ch 关闭,因此您需要在 func2 中创建一个循环,如下所示:

func func2(ch chan int) {
    fmt.Println("func2")
    for v := range ch {
        fmt.Println(v)
    }
}

这将保留 func2 "alive" 并从 ch 读取,直到您在其他地方执行 close(ch)。在您的示例中关闭 ch 的适当位置可能是 wg.Wait() 之后的 main

如果您希望确保在程序完成之前看到所有 Println 语句的结果,您还应该使用某种同步机制来等待 func2 完成。否则 main 将在 close(ch) 之后立即结束, 可能会也可能不会 func2 打印它收到的每个值之前。

一个常用的技术是 "done" 通道。例如:

func func2(ch chan int, done chan bool) {
    fmt.Println("func2")
    for v := range ch {
        fmt.Println(v)
    }
    done <- true
}

并在 main 中:

done := make(chan bool)
go func2(ch, done)
...
wg.Wait()
close(ch)
<-done

使用chan struct{}(空结构)也很常见,因为空结构不需要内存。