drq61040 2019-09-20 10: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 12: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.

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

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?