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

时间:2017-07-12 15:13:31

标签: go channel

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

看起来像装配一个有两个部分的机器,只有当两个部分都在手边时我才能继续工作。

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 个答案:

答案 0 :(得分:2)

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

当您从一个频道收到一个频道时,另一个频道可能无法接收(例如,另一个goroutine可能已经从该频道收到)。

如果只有一个goroutine消耗并处理这些值,只需从两个通道接收一个值,如果某个值未就绪(如果通道未准备接收),它将阻止:

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

// process v1 and v2

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

答案 1 :(得分:0)

这样的事情怎么样:

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,您将始终收到两个频道的组合。