Go 语言里的 errors 错误包装处理

Go 语言在返回错误时,允许进行 Wrap 包装。比如,函数 f() 调用函数 g(),在遇到错误、但处理不了时,可以这样:

func e() {
    // ...
    if err := f(); err != nil {
        fmt.Printf("err: %v", err)
    }
}

func f() {
    // ...

    if err := g(); err != nil {
        //
        // 这里的 %w 用来处理这种情况,即把对应的 err
        // 包装到由 fmt.Errorf() 返回的 error 里面
        //
        return fmt.Errorf("f failed: %w", err)
    }

    return nil
}

func g() {
    // ...
    {
        return errors.New("g failed: something wrong")
    }

    return nil
}

这样,e() 在调用 f() 后,拿到的错误返回值是这样的:

err: f failed: g failed: something wrong

e() 里,有两种办法:如果能把错误解决掉,程序就继续运行;如果不能解决,程序无法继续运行了,那么从这样的错误里,可以清楚地看到错误发生的路径来源,类似于调用栈,方便开发和调试。

对于被包装的错误,可以使用 errors.Unwrap() 提取出来:

func e() {
    // ...
    if err := f(); err != nil {
        fmt.Printf("err: %v", err)

        err2 := errors.Unwrap(err)
        fmt.Printf("err: %v", err2)
    }
}

// Output:
// err: f failed: g failed: something wrong
// err: g failed: something wrong

Read More: