error 接口与错误创建
本教程共 80 篇 · 第 51 篇 · 更新于 2026-07-27 · 约 7 分钟阅读
51. error 接口与错误创建
本节目标:搞懂 Go 的 error 接口,学会用 errors.New 和 fmt.Errorf 创建错误,理解「错误是值」的理念。
error 接口
Go 的错误处理方式和大多数语言不同。没有 try-catch,错误就是普通的返回值。
error 是一个内置接口,只有一个方法:
type error interface {
Error() string
}
任何实现了 Error() string 方法的类型都能当 error 用。Go 用这种方式把错误变成了值,你可以像处理其他返回值一样处理它。
基本错误处理模式
Go 函数通常把 error 作为最后一个返回值:
package main
import (
"errors"
"fmt"
)
func Divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}
func main() {
result, err := Divide(10, 0)
if err != nil {
fmt.Println("出错了:", err)
return
}
fmt.Println("结果:", result)
}
这就是 Go 最经典的错误处理模式:
- 函数返回
(result, error)两个值 - 成功时 error 为 nil
- 失败时 error 不为 nil,result 是零值
- 调用方检查
if err != nil
NoteGo 社区有句玩笑话:「如果你能接受 Go 的
if err != nil,你就算入门了。」这种写法确实啰嗦,但好处是每个错误都被显式处理,不会像异常那样被意外忽略。
创建错误:errors.New
errors.New 创建一个简单的错误:
err := errors.New("文件不存在")
fmt.Println(err) // 文件不存在
适合错误信息简单、不需要附加数据的场景。
创建错误:fmt.Errorf
fmt.Errorf 支持格式化,能嵌入变量信息:
package main
import "fmt"
func GetUser(id int) (string, error) {
if id <= 0 {
return "", fmt.Errorf("无效的用户ID: %d", id)
}
return "Alice", nil
}
func main() {
_, err := GetUser(-1)
fmt.Println(err) // 无效的用户ID: -1
}
fmt.Errorf 比 errors.New 更常用,因为错误信息里通常需要包含上下文数据。
错误是值
Go 的设计理念是「错误是值」。这意味着:
- 错误不是特殊的东西,就是一个普通的返回值
- 你可以选择处理它、传递它、或者忽略它(但不推荐忽略)
- 没有隐式的错误传播机制,每一步都要显式处理
// 错误传递:把收到的错误原样返回
func ProcessFile(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return err // 不处理,传给调用方
}
// 处理 data...
return nil
}
Tip如果你的函数不负责处理某个错误,就把它返回给调用方。让能处理错误的那一层来处理。
常见错误处理方式
直接返回
if err != nil {
return err
}
添加上下文后返回
if err != nil {
return fmt.Errorf("读取配置失败: %w", err)
}
Warning用
%w而不是%v来包装错误。%w保留错误链,调用方可以用errors.Is检查。%v只是把错误变成字符串,丢失了类型信息。下一章会详细讲。
记录日志后继续
if err != nil {
log.Printf("警告: %v", err)
// 继续执行,不中断
}
终止程序
if err != nil {
log.Fatal(err) // 打印错误后 os.Exit(1)
}
Note
log.Fatal只在不可恢复的错误时用,比如配置文件加载失败、数据库连接失败。大部分错误应该返回给调用方处理,不要直接退出程序。
不要忽略错误
Go 编译器不会强制你检查 error 返回值,但忽略错误是坏习惯:
// 坏:忽略了 error
result, _ := SomeFunction()
// 好:至少检查一下
result, err := SomeFunction()
if err != nil {
return err
}
Warning用
_忽略 error 时要特别小心。除非你确定错误不重要,否则一定要检查。很多 bug 就是因为忽略了错误返回值。
小结
错误创建和基本处理:
- error 是一个接口,只有一个
Error() string方法 errors.New创建简单错误,fmt.Errorf创建格式化错误- 经典模式:
if err != nil { return err } - 用
%w包装错误,保留错误链 - 不要忽略 error 返回值
下一章讲错误包装和 errors.Is/As/Join。