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

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

從嵌套在循環中的 goroutines 中收集錯誤

從嵌套在循環中的 goroutines 中收集錯誤

Go
慕的地8271018 2023-03-15 14:30:02
我正在嘗試從循環中的 goroutines 收集錯誤,但不明白它必須如何正確工作 https://go.dev/play/p/WrxE0vH6JSGfunc init() {    rand.Seed(1500929006430687579)}func goroutine(n int, wg *sync.WaitGroup, ch chan error) {    defer wg.Done()    defer fmt.Println("defer done")    fmt.Println("num ", n)    if n == 1 {        ch <- fmt.Errorf("error")    } else {        ch <- nil    }}func main() {    var wg sync.WaitGroup    var err error    errs := make(chan error)    platforms := 2    types := 3    for j := 0; j < platforms; j++ {        wg.Add(1)        for k := 0; k < types; k++ {            wg.Add(1)            n := rand.Intn(2)            go goroutine(n, &wg, errs)        }        for k := 0; k < types; k++ {            wg.Add(1)            n := rand.Intn(2)            go goroutine(n, &wg, errs)        }    }    wg.Wait()    err = <-errs    fmt.Println(err)}我應該如何正確收集錯誤數組并完成所有等待組?
查看完整描述

1 回答

?
撒科打諢

TA貢獻1934條經驗 獲得超2個贊

在 Golang 中,通道類似于 bash ( |) 中的管道。但與用于將一個命令的輸出傳輸到另一個命令的輸入的 bash 管道不同,Go 通道用于在 goroutine 之間傳輸一些數據。您可以在此處閱讀有關頻道的更多信息。渠道有容量。當您沒有為通道指定容量時,go 假定它的容量為 0。容量為零的信道通常稱為unbuffered信道,而容量非零的信道稱為buffered。當通道已滿(通道中的元素數等于通道的容量)時,通道上的所有寫操作 ( ->errs) 都會阻塞執行流程,直到<-errs出現讀操作 ( ) 。


在您的特定示例中,您有無緩沖通道(容量為 0 的通道)。因此,您通道上的任何寫入操作 ( ->errs) 都將阻止執行,直到提供某些讀取操作為止,因此您啟動的所有 goroutine 都將被阻止,盡管只有一個 goroutine 能夠在函數流移動時繼續進行寫入main操作轉發讀取操作 ( err = <-errs)。


要解決您的問題,您可以創建一個額外的 goroutine,該 goroutine 會同時從通道讀取數據,同時 goroutines 會寫入通道。它看起來像這樣:


func init() {

    rand.Seed(1500929006430687579)

}


func goroutine(n int, wg *sync.WaitGroup, ch chan error) {

    defer fmt.Println("defer done")

    defer wg.Done()


    fmt.Println("num ", n)

    if n == 1 {

        ch <- fmt.Errorf("error")

    }

}


func main() {

    var wg sync.WaitGroup

    errs := make(chan error)

    platforms := 2

    types := 3


    go func() {

        for e := range errs {

            fmt.Println(e)

        }

    }()


    for j := 0; j < platforms; j++ {

        for k := 0; k < types; k++ {

            wg.Add(1)

            n := rand.Intn(2)

            go goroutine(n, &wg, errs)

        }


        for k := 0; k < types; k++ {

            wg.Add(1)

            n := rand.Intn(2)

            go goroutine(n, &wg, errs)

        }

    }

    wg.Wait()

}

此外,我在您的代碼中重構了一些錯誤和不準確之處:

  1. 你不應該在有錯誤的頻道中寫 nil 。如果你希望errschan 只包含錯誤,那么只有當你的函數執行時出現非零錯誤時才寫在那里。

  2. 您有一個額外的 wd.Add(1) 作為循環的開始,因此函數和函數j之間存在不平衡。3.AddDone

  3. 此外,您添加defer fmt.Println("defer done")after defer wg.Done()but defers 構造的執行順序與指定的順序相反,因此放在defer fmt.Println("defer done")before 之前會更正確defer wg.Done(),這樣“延遲完成”將真正表明所有先前的defers 已被執行。


查看完整回答
反對 回復 2023-03-15
  • 1 回答
  • 0 關注
  • 106 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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