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

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

如何盡早從循環內的古魯特返回錯誤?

如何盡早從循環內的古魯特返回錯誤?

Go
皈依舞 2022-09-05 15:26:33
我在一個循環中有一個goroutine,我處理錯誤的方式是,我將其添加到一個通道,在所有goroutines完成后,我檢查是否有錯誤,然后相應地返回。這樣做的問題是,我想在收到錯誤后立即返回錯誤,這樣我就不會花時間等待所有goroutines完成,因為它效率低下。我嘗試添加語句,但它不起作用,我無法在goroutines中添加語句,因為我也想退出for循環和函數。selectselecttry我該怎么做?代碼如下:package mainimport (    "sync"    "runtime"    "fmt"    "errors")func try() (bool, error) {    wg := new(sync.WaitGroup)    s := []int{0,1,2,3,4,5}    ec := make(chan error)        for i, val := range s {    /*        select {             case err, ok := <-ec:        if ok {            println("error 1", err.Error())            return false, err        }            default:            }    */        wg.Add(1)        i := i        val := val        go func() {            err := func(i int, val int, wg *sync.WaitGroup) error {                defer wg.Done()                                if i == 3 {                    return errors.New("one error")                } else {                    return nil                }                            }(i, val, wg)            if err != nil {                ec <- err                return            }        }()    }    wg.Wait()        select {    case err, ok := <-ec:        if ok {            println("error 2", err.Error())            return false, err        }    default:    }        return true, nil}func main() {    runtime.GOMAXPROCS(runtime.NumCPU())    b, e := try()    if e != nil {        fmt.Println(e.Error(), b)    }     }
查看完整描述

2 回答

?
繁星淼淼

TA貢獻1775條經驗 獲得超11個贊

在你的陳述之前,你實際上是在等待所有的goroutines回來。wg.Wait()select

這樣做的問題是,我想在收到錯誤后立即返回錯誤

我假設您的意思是,一旦其中任何一個返回錯誤,就停止運行goroutines。

在這種情況下,您可以使用來管理取消,但更好的是錯誤組。組,它很好地結合了上下文功能和同步:context.Context

包錯誤組為處理常見任務的子任務的 goroutine 組提供同步、錯誤傳播和上下文取消。

特別是Group.Go

返回非 nil 錯誤的第一個調用將取消該組;其錯誤將由 Wait 返回。

import (

    "sync"

    "runtime"

    "fmt"

    "errors"

    "golang.org/x/sync/errgroup"

)


func try() (bool, error) {

    errg := new(errgroup.Group)


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

    

    for i, val := range s {       

        i := i

        val := val


        errg.Go(func() error {

            return func(i int, val int) error {

                if i == 3 {

                    return errors.New("one error")

                } else {

                    return nil

                }

            }(i, val)

        })

    }

    

    if err := errg.Wait(); err != nil {

        // handle error

    }

    

    return true, nil

}

https://play.golang.org/p/lSIIFJqXf0W


查看完整回答
反對 回復 2022-09-05
?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

我發現墳墓對此很有用。下面是一個精簡的非工作示例,它顯示了要點,而無需在循環中處理變量封裝之類的事情。它應該給你這個想法,但我很樂意澄清任何一點。


package main


import (

    "fmt"

    "gopkg.in/tomb.v2"

    "sync"

)


func main() {

    ts := tomb.Tomb{}

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


    for i, v := range s {

        ts.Go(func() error {

            // do some work here or return an error, make sure to watch the dying chan, if it closes, 

            //then one of the other go-routines failed.

            select {

            case <- ts.Dying():

                return nil

            case err := <- waitingForWork():

                if err != nil {

                    return err

                }

                return nil

            }

        })

    }


    // If an error appears here, one of the go-routines must have failed

    err := ts.Wait()

    if err != nil {

        fmt.Println(err)

    }

}


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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