【go语言】错误处理 error、panic、recover

Go 语言通过普通的返回值传递错误,而不是异常机制。惯用法是函数把 error 作为最后一个返回值,调用方检查并处理。

1. error 接口

error 是一个内置接口,只有一个 Error() 方法:

type error interface {
    Error() string
}

标准库 errors 包提供了创建错误的常用函数:

// 创建静态错误
err := errors.New("文件不存在")

// 带格式化的错误
err = fmt.Errorf("读取 %s 失败: %w", "a.txt", someErr)

// 包装错误,%w 保留原始错误链

2. 自定义错误类型

type PathError struct {
    Path string
    Op   string
    Err  error
}

func (e *PathError) Error() string {
    return e.Op + " " + e.Path + ": " + e.Err.Error()
}

自定义错误可以携带结构化信息,调用方能用类型断言或 errors.As 提取细节。

3. 错误的判断与解包

// 判断是否为特定错误
if errors.Is(err, os.ErrNotExist) { ... }

// 从错误链中提取自定义类型
var pathErr *PathError
if errors.As(err, &pathErr) {
    fmt.Println(pathErr.Path)
}

errors.Is 和 errors.As 会沿着 %w 包装的错误链逐层查找,是 Go 1.13 之后推荐的方式,不再推荐直接用 == 比较错误。

4. panic 与 recover

panic 表示程序遇到了无法继续的错误,会中断当前函数并向上传播,逐层执行 defer。recover 只能在 defer 的函数中生效,用于捕获 panic:

func safeDivide(a, b int) (result int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("捕获panic:", r)
            result = 0
        }
    }()
    return a / b // b为0时panic
}

fmt.Println(safeDivide(1, 0)) // 捕获panic: runtime error: integer divide by zero  输出 0

5. 使用原则

可预期的失败(文件不存在、网络超时、参数非法)用 error 返回;真正不可恢复的程序错误(数组越界、空指针、初始化失败)才用 panic。库代码尽量不要主动 panic,把错误返回给调用方决定如何处理;recover 一般只在程序入口和每个 goroutine 的最外层使用。

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容