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

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

慣用的 goroutine 并發和錯誤處理

慣用的 goroutine 并發和錯誤處理

Go
慕工程0101907 2022-12-19 21:38:26
在下面的代碼塊中,我試圖運行幾個例程并為所有例程獲取結果(無論是成功還是錯誤)。package main        import (        "fmt"        "sync"    )        func processBatch(num int, errChan chan<- error, resultChan chan<- int, wg *sync.WaitGroup) {        defer wg.Done()            if num == 3 {            resultChan <- 0            errChan <- fmt.Errorf("goroutine %d's error returned", num)        } else {            square := num * num                resultChan <- square                errChan <- nil        }        }        func main() {        var wg sync.WaitGroup            batches := [5]int{1, 2, 3, 4, 5}            resultChan := make(chan int)        errChan := make(chan error)            for i := range batches {            wg.Add(1)            go processBatch(batches[i], errChan, resultChan, &wg)        }            var results [5]int        var err [5]error        for i := range batches {            results[i] = <-resultChan            err[i] = <-errChan        }        wg.Wait()        close(resultChan)        close(errChan)        fmt.Println(results)        fmt.Println(err)    }游樂場:https ://go.dev/play/p/zA-Py9gDjce 此代碼有效,我得到了我想要的結果,即:[25 1 4 0 16][<nil> <nil> <nil> goroutine 3's error returned <nil>]我想知道是否有更慣用的方法來實現這一目標。我瀏覽了 errgroup 包:https ://pkg.go.dev/golang.org/x/sync/errgroup但沒能在這里找到對我有幫助的東西。歡迎提出任何建議。
查看完整描述

1 回答

?
SMILET

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

Waitgroup 在此代碼中是多余的。執行與等待通道結果的循環完美同步。在所有功能完成工作并從通道讀取發布的結果之前,代碼不會向前移動。僅當您的函數需要在結果發布到通道后執行任何工作時才需要 Waitgroup。


我也更喜歡稍微不同的實現。在發布的實現中,我們不會在每次執行函數時將結果和錯誤都發送到通道中。相反,我們可以只發送成功執行的結果,并在代碼失敗時只發送錯誤。


優點是簡化了結果/錯誤處理。我們在沒有nils.


在這個例子中,函數返回一個數字,我們發送它的默認值0以防出錯。如果零可能是合法的函數執行結果,則從成功中過濾出不成功的執行結果可能會很復雜。


與錯誤相同。要檢查我們是否有任何錯誤,我們可以使用像if len(errs) != 0.


package main


import (

    "fmt"

)


func processBatch(num int, errChan chan<- error, resultChan chan<- int) {

    if num == 3 {

        // no need to send result when it is meanenless

        // resultChan <- 0

        errChan <- fmt.Errorf("goroutine %d's error returned", num)

    } else {

        square := num * num


        resultChan <- square


        // no need to send errror when it is nil

        // errChan <- nil

    }


}


func main() {

    batches := [5]int{1, 2, 3, 4, 5}


    resultChan := make(chan int)

    errChan := make(chan error)


    for i := range batches {

        go processBatch(batches[i], errChan, resultChan)

    }


    // use slices instead of arrays because legth varry now

    var results []int

    var errs []error


    // every time function executes it sends singe piece of data to one of two channels

    for range batches {

        select {

        case res := <-resultChan:

            results = append(results, res)

        case err := <-errChan:

            errs = append(errs, err)

        }

    }


    close(resultChan)

    close(errChan)


    fmt.Println(results)

    fmt.Println(errs)

}

https://go.dev/play/p/SYmfl8iGxgD


[25 1 16 4]

[goroutine 3's error returned]

如果你可以使用外部包,我們可以從一些multierr包中獲益。例如,github.com/hashicorp/go-multierror。


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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