首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将戈朗错误包装成不透明错误?

如何将戈朗错误包装成不透明错误?
EN

Stack Overflow用户
提问于 2021-12-17 02:08:19
回答 1查看 756关注 0票数 0

如何将错误包装为不透明错误(如Dave在https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully中所描述的)?另外,我希望不透明的错误有一个堆栈跟踪,并通过返回链来保留它。

errors.Wrap()用堆栈跟踪创建一个新的错误,但不是我的不透明类型。如何做到这两种方式(添加堆栈跟踪并使其成为一个临时的MyErr,如true)?

代码语言:javascript
复制
package main

import (
    "fmt"
    "github.com/pkg/errors"
)

type temporary interface {
    Temporary() bool
}

func IsTemporary(err error) bool {
    te, ok := err.(temporary)
    return ok && te.Temporary()
}

type MyError struct {
    error
    isTemporary bool
}

func (e MyError) Temporary() bool {
    return e.isTemporary
}

func f1() error {   // imitate a function from another package, that produces an error
    return fmt.Errorf("f1 error")
}

func f2() error {
    err := f1()
    myErr := errors.Wrap(err, "f2 error")   // Wrap() adds the stacktrace
    // how to wrap it as a temporary MyErr?
    return myErr
}

func f3() error {
    err := f2()
    return fmt.Errorf("f3 error: %+v", err) // don't Wrap() here or we get another stacktrace
}

func f4() error {
    err := f3()
    return fmt.Errorf("f4 error: %+v", err) // the '+' isn't needed here but does no harm
}

func main() {
    err := f4()
    if err != nil {
        if IsTemporary(err) {
            fmt.Println("temporary error")
        }
        fmt.Printf("oops: %+v\n", err)
    }
}

这将打印以下内容:

代码语言:javascript
复制
oops: f4 error: f3 error: f1 error
f2 error
main.f2
        /home/jlearman/projects/axon-internal/ibm/pocs/ibm-cloud/vmware-vms/err2.go:32
main.f3
        /home/jlearman/projects/axon-internal/ibm/pocs/ibm-cloud/vmware-vms/err2.go:38
main.f4
        /home/jlearman/projects/axon-internal/ibm/pocs/ibm-cloud/vmware-vms/err2.go:43
main.main
        /home/jlearman/projects/axon-internal/ibm/pocs/ibm-cloud/vmware-vms/err2.go:48
runtime.main
        /usr/local/go/src/runtime/proc.go:255
runtime.goexit
        /usr/local/go/src/runtime/asm_amd64.s:1581

这是正确的,但我想看到“临时错误”打印的第一。

假设f1实际上在第三方或内置代码中,返回一个标准的error类型。f2是我的代码中接收该错误的第一个函数,需要在适当的时候使它成为一个临时函数。(如果这是暂时的,那将是一个后续的问题,但我想我可以弄清楚。)

我希望处理代码返回的错误的模式在整个项目中保持一致,这将是相对较大的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-20 17:47:45

使用github.com/pkg/errors函数并不能真正做到这一点。这是因为用于包装的错误类型未导出,因此不能将其嵌入到您自己的自定义错误中。

但是,由于您不反对使用stdlib errors包以外的错误库,下面是如何使用juju错误包(因为它的错误类型是导出的):

代码语言:javascript
复制
package main

import (
    "fmt"

    "github.com/juju/errors"
)

type temporary interface {
    Temporary() bool
}

func IsTemporary(err error) bool {
    for {
        te, ok := err.(temporary)
        if ok {
            return te.Temporary()
        }

        er, ok := err.(*errors.Err)
        if ok {
            err = er.Underlying()
            continue
        }

        return false
    }
}

type MyError struct {
    errors.Err
    isTemporary bool
}

func (e MyError) Temporary() bool {
    return e.isTemporary
}

func f1() error { // imitate a function from another package, that produces an error
    return errors.Errorf("f1 error")
}

func f2() error {
    err := f1()
    wrappedErr := errors.Annotate(err, "f2 error")
    return &MyError{
        Err:         *wrappedErr.(*errors.Err),
        isTemporary: true,
    }
}

func f3() error {
    err := f2()
    return errors.Annotate(err, "f3 error")
}

func f4() error {
    err := f3()
    return errors.Annotate(err, "f4 error")
}

func main() {
    err := f4()
    if err != nil {
        if IsTemporary(err) {
            fmt.Println("temporary error")
        }
        if e, ok := err.(*errors.Err); ok {
            fmt.Printf("oops: %+v\n", e.StackTrace())
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70387666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档