返回介绍

自定义 Error

发布于 2024-10-12 12:35:57 字数 1690 浏览 0 评论 0 收藏 0

error 是一个 interface ,所以在实现自己的包的时候,通过定义实现此接口的结构,就可以实现自己的错误定义,请看来自 Json 包的示例:

type SyntaxError struct {
    msg    string // 错误描述
    Offset int64  // 错误发生的位置
}

func (e *SyntaxError) Error() string { return e.msg }

Offset 字段在调用 Error 的时候不会被打印,但可以通过类型断言获取错误类型,然后可以打印相应的错误信息,请看下面的例子:

if err := dec.Decode(&val); err != nil {
    if serr, ok := err.(*json.SyntaxError); ok {
        line, col := findLine(f, serr.Offset)
        return fmt.Errorf("%s:%d:%d: %v", f.Name(), line, col, err)
    }
    return err
}

需要注意的是,函数返回自定义错误时,返回值推荐设置为 error 类型,而非自定义错误类型,特别需要注意的是不应预声明自定义错误类型的变量。例如:

func Decode() *SyntaxError { // 错误,将可能导致上层调用者 err!=nil 的判断永远为 true。
    var err *SyntaxError     // 预声明错误变量
    if 出错条件 {
        err = &SyntaxError{}
    }
    return err               // 错误,err 永远等于非 nil,导致上层调用者 err!=nil 的判断始终为 true
}

原因见 http://golang.org/doc/faq#nil_error (需科学上网)

上面例子简单的演示了如何自定义 Error 类型。但是如果还需要更复杂的错误处理呢?此时,来参考一下 net 包采用的方法:

package net

type Error interface {
    error
    Timeout() bool   // Is the error a timeout?
    Temporary() bool // Is the error temporary?
}

在调用的地方,通过类型断言 err 是不是 net.Error ,来细化错误的处理,例如下面的例子,如果一个网络发生临时性错误,那么将会 sleep 1 秒之后重试:

if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
    time.Sleep(1e9)
    continue
}
if err != nil {
    log.Fatal(err)
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文