Go 错误包装
fmt.Errorf + %w 包装错误、errors.Is/As 判断链 · 难度:高级 · +20XP
错误包装(Go 1.13+)
fmt.Errorf("%w", err) 可以包装底层错误,保留原始错误信息供上层判断。用 errors.Is 和 errors.As 检查错误类型。
包装错误
var ErrNotFound = errors.New("not found")
func getUser(id int) (*User, error) {
u, err := db.FindUser(id)
if err != nil {
// 包装底层错误,添加上下文信息
return nil, fmt.Errorf("获取用户 %d 失败: %w", id, err)
}
return u, nil
}
判断错误类型
u, err := getUser(42)
if err != nil {
// 判断是否为特定错误
if errors.Is(err, ErrNotFound) {
fmt.Println("用户不存在")
}
// 提取特定错误类型
var vErr *ValidationError
if errors.As(err, &vErr) {
fmt.Println("验证失败:", vErr.Field)
}
}
最佳实践
- 用 %w 包装:保留原始错误链
- 用 errors.Is 判断:检查错误链中是否有特定错误
- 用 errors.As 提取:获取特定类型的错误详情
- 不要吞掉错误:每个错误都要处理或向上传播