如何在管道

时间:2015-07-25 23:07:21

标签: multithreading go pipeline goroutine

我需要帮助才能理解为什么以下代码不起作用。我正在构建一个管道,并试图让一个步骤同步来自两个源通道的值。我的源代码/生产者代码看起来像下面(在我的实际代码中,我从文件中读取文本)。这些来源已经过排序,但不保证两个来源都有价值。

func Source() <-chan int{
    out := make(chan int, 5)

    go func() {
        defer reader.Close()

        out <- 1
        out <- 2
        out <- 3
        out <- 4
        out <- 5
        out <- 7

        close(out)
    }()

    return out
}

,同步代码如下所示:

func Sync(a, b <-chan int) <-chan int {
    out := make(chan int)

    go func() {
        av, ak:= <-a
        bv, bk:= <-b

        for ak || bk {

            if !ak || av < bv {
                out <- bv

                bv, bk = <-b
                continue
            }

            if !bk|| bv > av {
                out <- av

                av, ak = <-a
                continue
            }

            out <- av

            av, ak = <-a
            bv, bk = <-b
        }

        close(out)
    }()

    return out
}

我的程序看起来像这样:

func main() {
    os := Source()
    ns := Source()

    for val := range Sync(ns, os) {
        fmt.Printf("[SYNCED] %v \n", val)
    }
}

预期的行为是我的两个源缓冲值到通道中,我的同步首先从第一个源读取值。然后从第二个。比较它们,如果它们相等则继续在两个通道中的下一个。如果不同,我们将发送后面的值并将其替换为新的值并再次进行相同的比较。

发生的事情是,看起来同步代码对值运行了好几次,我会多次得到[SYNCED] 1这样的东西。为什么呢?

请帮我解决这个问题!

1 个答案:

答案 0 :(得分:2)

关于http://play.golang.org/p/uhd3EWrwEohttp://play.golang.org/p/Dqq7-cPaFq -

实际上,int的代码也会因类似的测试用例而失败:

os := Source([]int{1, 2, 3})
ns := Source([]int{1, 3, 4})

将整数版本置于无限循环中。

这是因为选中!aok || avalue > bvalue时,如果aok为真(某些元素仍在a中)并且bok为false,则不会考虑(b中没有更多元素),然后avalue > ""始终为真。所以它试图从b中获取另一个项目(这是空的)并进入无限循环。固定代码:http://play.golang.org/p/vYhuOZxRMl