error 包装与检查
如何包装错误? fmt.Errorf 与 %w 有何作用?
fmt.Errorf: 格式化并创建错误;%w: 包装原始错误并保留错误链;
import "fmt"
func load() error {
if err := read(); err != nil {
return fmt.Errorf("read config: %w", err)
}
return nil
}
- 上下文价值: 包装说明“哪一步失败”,原始错误保留“具体为什么失败”,调用者仍可通过 Is/As 作结构化判断;
err := fmt.Errorf("read config: %w", os.ErrNotExist)
println(errors.Is(err, os.ErrNotExist)) // true
// 此片段需要导入 fmt、os、errors。
如何判断错误? errors.Is 的作用是什么?
errors.Is: 判断错误链中是否存在目标错误;
if errors.Is(err, os.ErrNotExist) {
return nil
}
- 匹配边界:
errors.Is会检查包装关系,也支持错误类型自定义的 Is 匹配规则;直接err == target无法替代包装后的检查;
如何提取错误类型? errors.As 的作用是什么?
errors.As: 从错误链中提取可赋值给目标类型的错误;
var pathErr *os.PathError
if errors.As(err, &pathErr) {
println(pathErr.Path)
}
- 目标参数:
errors.As的 target 必须是非 nil 指针,指向错误类型或接口;传&pathErr才能让函数写入提取结果;
如何根据错误处理目标选择检查方式?
- 选择入口: 添加上下文同时保留原因走
%w,识别某个错误走errors.Is,读取某类错误的字段走errors.As;不要通过匹配错误字符串代替类型或身份检查;