drq61040 2019-09-20 02:39
浏览 28
已采纳

当错误已返回时,从延迟函数返回错误

Update: I think now that there is no universal answer to this question. We can return both errors using the technique explained in the answer. I think that the most important thing here is not to forget the case when we have two errors and somehow handle it.

Notes: There are many questions on SO about how to return an error from deferred function. This is not a question here.

(In Go) What is the proper way to return an error from a deferred function when the function is already returning an error. For example

func errorMaker() (err error) {
    defer func() {
        err = errors.New("Deferred error")
    }()

    err = errors.New("Some error")
    return
}
func main() {
    err := errorMaker()
    fmt.Printf("Error: %v
", err)
}

In the code above the error returned by the deferred function overwrites the error returned by the function. What is the canonical way to return both errors? If another programmer uses my function what result might she expect from the function when the function returns 'two errors'?

Should I use Error wrapping for this?

Additional notes:

  1. As @Volker says in his comment I write some application specific handling for this error. Because I know what should be done based on nature of the errors.
  2. I think my question is - if I want to return all errors from the function what is the best way to combine them in my scenario?
  • 写回答

1条回答 默认 最新

  • douqian1975 2019-09-20 04:27
    关注

    Disclaimer: I don't know if the following advice can be seen as "standard" or "widely-accepted".

    Should I use Error wrapping for this?

    Short answer: yes (I would do so).


    Go 1.12 and earlier

    What I do when I need my errors to convey some specific meaning, without foregoing the error interface, I create a wrapper that implements the error interface - Error() string -. This wrapper contains all extra information I need.

    If the caller is aware of the existence of those extra info, it can unwrap the error with a cast and find those info. With the added benefit that unaware callers can just handle the error as a generic error.

    type MyError struct {
        DeferredError error
    }
    
    // Implements 'error' interface
    func (e MyError) Error() string {
        // format to string
    }
    
    func someFunc() error {
        // might return an instance of MyError
    }
    
    ...
    
    // Caller code
    err := someFunc()
    if err != nil {
        if myErr, ok := err.(*MyError); ok {
            // here you can access the wrapped info
            fmt.Println(myErr.DeferredError)
    
        } else {
            // otherwise handle the error generically
        }
    }
    
    

    Go 1.13 onwards

    With Go.13 you can use errors.As to unwrap an error. From the official docs:

    [The method] As finds the first error in err's chain that matches target, and if so, sets target to that error value and returns true. The chain consists of err itself followed by the sequence of errors obtained by repeatedly calling Unwrap.

    var myErr *MyError
    if errors.As(err, &myErr) {
        // here you can access the wrapped info
        fmt.Println(myErr.DeferredError)
    } else {
        // otherwise handle the error generically 
    }
    

    As the docs say the myErr variable is populated as a side-effect of calling As.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

悬赏问题

  • ¥30 SD中的一段Unet下采样代码其中的resnet是谁跟谁进行残差连接
  • ¥15 Unet采样阶段的res_samples问题
  • ¥60 Python+pygame坦克大战游戏开发实验报告
  • ¥15 R语言regionNames()和demomap()无法选中中文地区的问题
  • ¥15 Open GL ES 的使用
  • ¥15 我如果只想表示节点的结构信息,使用GCN方法不进行训练可以吗
  • ¥15 QT6将音频采样数据转PCM
  • ¥15 下面三个文件分别是OFDM波形的数据,我的思路公式和我写的成像算法代码,有没有人能帮我改一改,如何解决?
  • ¥15 Ubuntu打开gazebo模型调不出来,如何解决?
  • ¥100 有chang请一位会arm和dsp的朋友解读一个工程