errors.Is用于判断错误链中是否包含指定错误,errors.As用于提取错误链中特定类型的错误。示例显示ErrNotFound被包装后仍可被Is识别,而As能成功提取*ValidationError类型并获取字段信息。使用%w包装错误可确保错误链完整,Is和As可穿透多层;建议公共错误用sentinel值,上下文错误用结构体,避免对非导出类型使用As。掌握二者可提升错误处理安全性与清晰度,尤其适用于大型项目或库开发。

在Go 1.13之后,标准库引入了errors.Is和errors.As,用来更方便地处理错误判断和类型断言。这两个函数解决了以往用==或type assertion判断错误时的局限性,尤其是在包装(wrap)错误的场景下。
当你需要判断一个错误是否等于某个已知的错误值时,使用errors.Is。它会递归地比较错误链中的每一个底层错误,而不仅仅是表面值。
常见于使用errors.New定义的 sentinel 错误(即预定义的错误变量)。
package main
import (
"errors"
"fmt"
)
var ErrNotFound = errors.New("not found")
func main() {
err := fmt.Errorf("wrap: %w", ErrNotFound)
// 使用 errors.Is 判断
if errors.Is(err, ErrNotFound) {
fmt.Println("error is ErrNotFound")
}
}
这里即使ErrNotFound被包装了一层,errors.Is依然能正确识别。
立即学习“go语言免费学习笔记(深入)”;
当你需要从一个错误中提取某个具体类型的错误(比如自定义结构体)时,使用errors.As。它会在错误链中查找能赋值给目标类型的错误,并将指针赋值给传入的变量。
package main
import (
"errors"
"fmt"
)
type ValidationError struct {
Field string
Msg string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error on %s: %s", e.Field, e.Msg)
}
func main() {
err := fmt.Errorf("outer: %w", &ValidationError{Field: "email", Msg: "invalid format"})
var ve *ValidationError
if errors.As(err, &ve) {
fmt.Printf("validation error on field: %s, msg: %s\n", ve.Field, ve.Msg)
}
}
errors.As会遍历错误链,尝试把每个底层错误赋值给ve,一旦成功就返回true。
var ErrXXX = errors.New("..."),以便其他包使用errors.Is判断。Error()方法,用errors.As提取。%w动词,否则错误链断裂,Is和As无法穿透。errors.As,避免耦合。基本上就这些。掌握errors.Is和errors.As,能让错误处理更安全、清晰,尤其在大型项目或库开发中尤为重要。
以上就是如何在Golang中使用errors.Is和errors.As的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号