如何使用 errors.Is 检测 json.SyntaxError

Cir*_*i94 1 go

在检查从失败的decoder.Decode 操作返回的错误时,我无法检测到 json.SyntaxError!

在这里,您可以在操场上看到一个工作示例。

正如您所看到的,调试器向我确认它是一个指向 json.SyntaxError 的指针,但 errors.Is 无法检测到它。

在此处输入图片说明

我检查了错误。是实现:

func Is(err, target error) bool {
    if target == nil {
        return err == target
    }

    isComparable := reflectlite.TypeOf(target).Comparable()
    for {
        if isComparable && err == target {
            return true
        }
        if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
            return true
        }
        // TODO: consider supporting target.Is(err). This would allow
        // user-definable predicates, but also may allow for coping with sloppy
        // APIs, thereby making it easier to get away with them.
        if err = Unwrap(err); err == nil {
            return false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并且它们是可比较的(isComparable 变量为真)但是,当我希望它继续执行时它会返回真if isComparable && err == target {......

我究竟做错了什么?提前致谢。

xar*_*lus 6

当前发生的事情是将 new 的内存地址与json.SyntaxErrorDecode. 正如你所注意到的,这永远不会是真的。

您想要做的有点不同:检查是否err属于类型SyntaxError,然后直接使用该对象。这可以使用type assertions,它基本上检查接口的基础类型(error在这种情况下)是否是更具体的类型。

这就是错误。就像那样。它填充您指定的特定错误类型。使用这种方法,可以看到以下代码:

if err != nil {
    var serr *json.SyntaxError
    
    if errors.As(err, &serr) {
        fmt.Println("Syntax error:", serr)
        fmt.Println("Offset:", serr.Offset)
    } else {
        fmt.Println("Other error:", err)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Cirelli94 `errors.Is` 通常用于与包定义的特定错误值进行比较,例如[由 `fs` 包声明的错误值](https://pkg.go.dev/io/fs#pkg -变量)。它还与所谓的“包装”错误进行比较,后者允许包含更多信息,同时仍然准确地包含要比较的一个定义的错误。[这篇博文](https://blog.golang.org/go1.13-errors) 详细介绍了使用错误的不同方式。`errors.Is` 适用于各种错误,但它们需要是内存中的同一对象,而不仅仅是同一类型 (2认同)