Go错误处理核心是“值在前、error在后”的多返回值范式,要求显式检查error,不可忽略;支持自定义error类型以增强可判断性。

Go语言通过多返回值机制天然支持“值 + 错误”组合返回,这是其错误处理的核心范式。关键不是“如何返回”,而是“如何一致、清晰地判断和使用”——重点在于调用方对 error 的显式检查,以及合理组织返回值顺序(惯例:结果在前,error 在后)。
遵循“值在前,error在后”的约定
Go标准库和主流项目都采用此顺序,例如 os.Open(filename string) (*os.File, error)。这便于配合 if err != nil 快速判错,也利于使用短变量声明简洁赋值:
-
✅ 推荐写法:
f, err := os.Open("config.json")—— 可直接在下一行if err != nil处理 -
❌ 避免反序:
err, f := os.Open("config.json")—— 违背直觉,增加阅读负担,且无法利用 Go 的“_ 忽略单个值”特性(如_, err := ...)
必须显式检查 error,不可忽略
Go 不提供异常抛出/捕获机制,error 是普通值,不检查就等于默认成功。常见错误包括:
- 只检查
err == nil却未处理非 nil 情况(如漏写return或panic) - 用
_忽略error:data, _ := json.Marshal(v)—— 掩盖潜在序列化失败 - 在循环中忽略单次错误,导致部分数据处理失败却不报警
正确做法是:每次调用后立即判断,并决定继续、返回或终止:
立即学习“go语言免费学习笔记(深入)”;
result, err := doSomething()
if err != nil {
log.Printf("操作失败: %v", err)
return err // 或 return nil, err;或 panic(err)(慎用)
}
// 此处 result 可安全使用
组合多个返回值时保持逻辑清晰
当函数需返回多个业务值(如 id, name, err),仍坚持 error 放最后。调用时可用短声明一次性接收,也可用 _ 忽略不需要的值:
- 全接收:
id, name, err := getUserInfo(123) - 只关心错误:
_, _, err := getUserInfo(123) - 只关心某个值:
id, _, err := getUserInfo(123)
注意:若 err != nil,其他返回值通常为该类型的零值(如 0, "", nil),不应假设其有效。务必先判错再使用其他值。
自定义 error 类型增强可判断性
基础 error 接口仅含 Error() string,不利于程序化判断。可通过以下方式提升:
- 使用
errors.Is()和errors.As()(Go 1.13+)匹配预定义错误(如os.ErrNotExist) - 定义带字段的结构体错误类型,实现
Unwrap()支持链式错误 - 对关键错误添加方法(如
IsTimeout() bool),供调用方语义化判断
示例:
type ValidationError struct {
Field string
Msg string
}
func (e *ValidationError) Error() string { return "validation failed: " + e.Msg }
func (e *ValidationError) IsValidation() bool { return true }
// 调用方
if verr, ok := err.(*ValidationError); ok && verr.IsValidation() {
// 特殊处理校验错误
}










