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









暂无评论内容