去例行程序神秘地结束,频道关闭而没有达到关闭语句

我创建了以下简单程序来测试使用通道的扇入扇出模式。它的作用是生成一些 go 例程来计算来自输入通道的数字的平方,并将该平方发送到输出通道。然后,所有输出通道将合并到一个通道中,以在 中打印正方形。main


func calculateSquare(in <-chan int) <-chan int {

    out := make(chan int)


    go func() {

       for num := range in {

           fmt.Printf("Receving num %v\n", num)

           out <- num * num

           fmt.Printf("Sending square %v\n", num * num)

       }

       fmt.Println("Closing out")

       close(out)

    }()


    return out

}


func fanOut(in <-chan int, workerCount int) []<-chan int {

    outs := make([]<-chan int, 0, workerCount)


    for i := 0 ; i < workerCount ; i++ {

        outs = append(outs, calculateSquare(in))

    }


    return outs

}


func fanIn(outs []<-chan int) <-chan int {

    var wg sync.WaitGroup


    merge := make(chan int)


    for _, out := range outs {

        wg.Add(1)


        go func() {

            for result := range out {

                merge <- result

            }


            wg.Done()

        }()

    }


    go func() {

        wg.Wait()

        fmt.Println("Closing merge")

        close(merge)

    }()


    return merge

}


func main() {

    in := make(chan int)


    go func() {

        for i := 0 ; i < 4 ; i++ {

            fmt.Printf("Sending num %v\n", i)

            in <- i

        }

        close(in)

    }()


    outs := fanOut(in, 5)

    merge := fanIn(outs)


    for num := range merge {

        fmt.Printf("Final square %v\n", num)

    }

}

在函数中,我将4个数字0 -> 3发送到输入通道,我希望看到控制台中打印的4个正方形。但是,当我运行该程序时,即使输出有点波动,但我从未见过控制台中打印的4个平方数字。main


下面是我看到的示例输出。


Sending num 0

Sending num 1

Sending num 2

Sending num 3

Closing out

Receving num 0

Receving num 1

Receving num 2

Sending square  4

Closing out

Receving num 3

Final square 4

Closing merge

如果有人能向我解释为什么被印刷但永远不会来,我将不胜感激。此外,如果没有打印,频道是如何关闭的。我只看到2 ,但是,我合并结果的等待组结束了它。Receving num 1Sending square 1Sending square 1outputClosing outWait()


我一定是在某个地方做错了什么。


繁花如伊
浏览 69回答 2
2回答

红颜莎娜

要修复:for&nbsp;_,&nbsp;out&nbsp;:=&nbsp;range&nbsp;outs&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;wg.Add(1) &nbsp;&nbsp;&nbsp;&nbsp;out&nbsp;:=&nbsp;out&nbsp;//&nbsp;<-&nbsp;add&nbsp;this为什么?https://golang.org/doc/effective_go&nbsp;是一个很好的资源,涵盖了通道部分末尾的确切关闭错误(@JimB提到):写起来可能看起来很奇怪要求 := 要求但它是合法的和惯用语在Go中这样做。您将获得具有相同名称的变量的新版本,故意在局部隐藏循环变量,但对于每个 goroutine 是唯一的。

慕无忌1623718

您的问题在下面的代码中,for 函数中的循环。fanIn&nbsp; &nbsp; for _, out := range outs {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for result := range out {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; merge <- result&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; }这样做的原因是你在gofunc中使用迭代器变量,当gofunc要使用它时,循环就走到了它的尽头。out这在子主题下的 go/wiki/常见错误中进行了描述Using goroutines on loop iterator variables有关更多示例 - 请阅读此校正后的循环应如下所示,&nbsp; &nbsp; for _, out := range outs {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(c <- chan int) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for result := range c {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; merge <- result&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; }(out)&nbsp; &nbsp; }
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go