您的位置:首页 >Golang errors.Is用法及错误判断技巧
发布于2026-01-28 阅读(0)
扫一扫,手机访问
errors.Is不能判断自定义错误底层类型,因其仅通过调用错误链中各错误的Is方法判断语义相等,不进行类型断言或反射;若自定义错误未实现Is方法,则errors.Is恒返回false。

errors.Is 只检查错误链中是否存在「语义相等」的错误,即调用 Is(error) 方法返回 true 的错误。它不关心底层结构体类型,也不做类型断言或反射比对。
常见误解是以为 errors.Is(err, myErr) 能识别你定义的 *MyError 类型 —— 实际上,除非你显式实现了 Is 方法并让它返回 true,否则它永远返回 false。
os.ErrNotExist、io.EOF 等能被 errors.Is 识别,是因为它们本身实现了 Is 方法fmt.Errorf("xxx: %w", err) 包装后的错误,仍保留原错误的 Is 行为(前提是被包装的 err 支持)errors.New("xxx") 或 fmt.Errorf("xxx") 创建的错误,不支持 Is 比较,只能靠 errors.As 或类型断言当你需要获取错误的具体值(比如访问字段、调用方法),而不是只判断「是否等于某个哨兵错误」时,errors.As 是唯一选择。
例如:你定义了带状态码和消息的错误类型 *HTTPError,想取出它的 Code 字段 —— 这必须用 errors.As 提取指针,errors.Is 完全无能为力。
errors.Is 返回 bool,适合 if/else 分支逻辑(如「如果文件不存在就创建」)errors.As 返回 bool + 填充目标变量,适合需进一步操作错误值的场景errors.As 找到第一个匹配的并停止;不会继续向上遍历var httpErr *HTTPError
if errors.As(err, &httpErr) {
log.Printf("HTTP error code: %d", httpErr.Code)
}
要让自己的错误能被 errors.Is 正确识别,必须在错误类型上实现 Is(target error) bool 方法,并确保逻辑可传递、无环、不依赖地址比较。
== 直接比较接收者和 target(地址不同就失败)errors.As 尝试将 target 转成你的类型,再做字段级比较(如错误码、字符串消息)ErrTimeout),可直接返回 target == ErrTimeout,但必须保证它是包级变量且永不重分配type MyError struct {
Code int
Msg string
}
func (e *MyError) Error() string { return e.Msg }
func (e *MyError) Is(target error) bool {
var t *MyError
if errors.As(target, &t) {
return e.Code == t.Code
}
return false
}
errors.Is 会沿着 %w 包装链逐层调用 Unwrap(),直到遇到 nil 或某层返回 true。但它不会进入非标准包装(如自定义 WrappedError 但没实现 Unwrap)。
Unwrap() 返回 nil,链就断了,后续错误不可达Unwrap() 返回自身(造成循环),errors.Is 会 panic(Go 1.20+ 加了检测)fmt.Errorf("wrap: %w", err) 是安全的;但手动实现 Unwrap 时务必确保返回的是另一个错误,不是自己真正容易被忽略的是:即使你用了 %w,如果被包装的错误本身不支持 Is(比如纯字符串错误),那整条链对 errors.Is 来说仍是“不可识别”的 —— 它不会自动比对错误消息字符串。
上一篇:WPS公式插入极限符号技巧
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
9