如何等待 2 个通道并在它们都准备好读取时继续

how to wait on 2 channels and continue when they are both ready for read

假设我有 2 个缓冲通道,我如何等待它们,并且只有在两个通道中至少有一个项目时才继续?

看起来assemble一台机器有两个部分,只有两个部分都在手边,我才能继续工作。

Both queue are empty, wait.
-------------------
|     |     |     |   QUEUE A
-------------------

-------------------
|     |     |     |   QUEUE B
-------------------


Queue A has one element but Queue B empty, wait
-------------------
|     |     |  X  |   QUEUE A
-------------------

-------------------
|     |     |     |   QUEUE B
-------------------


Queue A has two elements but Queue B empty, still wait
-------------------
|     |  Y  |  X  |   QUEUE A
-------------------

-------------------
|     |     |     |   QUEUE B
-------------------


Both queue has item in it, consume one from each queue.
-------------------
|     |  Y  |  X  |   QUEUE A
-------------------

-------------------
|     |     |  Z  |   QUEUE B
-------------------


Now, Queue B empty again, wait ...
-------------------
|     |     |  Y  |   QUEUE A
-------------------

-------------------
|     |     |     |   QUEUE B
-------------------

从 2 个通道接收不是原子的。您可以使用内置 len() 函数检查通道缓冲区中排队的元素数量,但您不能执行 2 通道原子接收。

意思是当您从一个通道接收到值时,另一个通道可能还没有准备好接收(例如,另一个 goroutine 可能已经从它接收到)。

如果只有一个 goroutine 消费和处理这些值,简单地从两个通道接收一个值,如果一个值没有准备好它会阻塞(如果通道没有准备好接收):

v1 := <- ch1
v2 := <- ch2

// process v1 and v2

另请注意,如果频道关闭,接收也会成功。

这样的事情怎么样:

type Foo1 struct {}
type Foo2 struct {}

type Combination struct {
    foo1 *Foo1
    foo2 *Foo2
}

func mergeChan(chIn chan *Foo1, chIn2 chan *Foo2, chOut chan *Combination) {
    for foo1 := range chIn {
        chOut <- &Combination{
            foo1: foo1,
            foo2: <-chIn2,
        }
    }
}

收听 chOut 时,您总是会收到来自两个频道的组合。