亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

去例行程序神秘地結束,頻道關閉而沒有達到關閉語句

去例行程序神秘地結束,頻道關閉而沒有達到關閉語句

Go
繁花如伊 2022-09-19 14:50:58
我創建了以下簡單程序來測試使用通道的扇入扇出模式。它的作用是生成一些 go 例程來計算來自輸入通道的數字的平方,并將該平方發送到輸出通道。然后,所有輸出通道將合并到一個通道中,以在 中打印正方形。mainfunc 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 0Sending num 1Sending num 2Sending num 3Closing outReceving num 0Receving num 1Receving num 2Sending square  4Closing outReceving num 3Final square 4Closing merge如果有人能向我解釋為什么被印刷但永遠不會來,我將不勝感激。此外,如果沒有打印,頻道是如何關閉的。我只看到2 ,但是,我合并結果的等待組結束了它。Receving num 1Sending square 1Sending square 1outputClosing outWait()我一定是在某個地方做錯了什么。
查看完整描述

2 回答

?
紅顏莎娜

TA貢獻1842條經驗 獲得超13個贊

要修復:

for _, out := range outs {
    wg.Add(1)

    out := out // <- add this

為什么?

https://golang.org/doc/effective_go 是一個很好的資源,涵蓋了通道部分末尾的確切關閉錯誤(@JimB提到):

寫起來可能看起來很奇怪

要求 := 要求

但它是合法的和慣用語在Go中這樣做。您將獲得具有相同名稱的變量的新版本,故意在局部隱藏循環變量,但對于每個 goroutine 是唯一的。


查看完整回答
反對 回復 2022-09-19
?
慕無忌1623718

TA貢獻1744條經驗 獲得超4個贊

您的問題在下面的代碼中,for 函數中的循環。fanIn


    for _, out := range outs {

        wg.Add(1)


        go func() {

            for result := range out {

                merge <- result

            }


            wg.Done()

        }()

    }

這樣做的原因是你在gofunc中使用迭代器變量,當gofunc要使用它時,循環就走到了它的盡頭。out


這在子主題下的 go/wiki/常見錯誤中進行了描述Using goroutines on loop iterator variables


有關更多示例 - 請閱讀此


校正后的循環應如下所示,


    for _, out := range outs {

        wg.Add(1)


        go func(c <- chan int) {

            for result := range c {

                merge <- result

            }


            wg.Done()

        }(out)

    }


查看完整回答
反對 回復 2022-09-19
  • 2 回答
  • 0 關注
  • 100 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號