Golang测试中如何断言错误类型

6次阅读

errors.Is 用于安全判断错误链中是否包含特定错误,errors.As 用于提取具体错误类型;二者均递归遍历错误链,避免直接比较或字符串匹配;自定义错误需实现 Unwrap 方法。

Golang 测试中如何断言错误类型

用 errors.Is 判断是否为特定错误

Go 1.13 引入的 errors.Is 是最常用、也最安全的方式,用于判断一个错误是否「等于」某个已知错误(包括底层包装链中的目标错误)。它不依赖指针相等,而是递归检查错误链中是否存在匹配项。

err := doSomething() if !errors.Is(err, io.EOF) {t.Fatal("expected io.EOF, got:", err) }

常见误用是直接用 == 比较,这在错误被 fmt.Errorf("wrap: %w", err) 包装后必然失败。只要错误可能被包装(绝大多数 标准库 和现代 Go 库都这么做),就必须用 errors.Is

用 errors.As 提取具体错误类型

当需要访问错误的字段或方法(比如 *os.PathErrorPath 字段),就得用 errors.As 将错误解包成具体类型:

var pathErr *os.PathError if errors.As(err, &pathErr) {if pathErr.Path == "/tmp/data.txt" {         // 处理特定路径的错误} }

注意三点:

立即学习go 语言免费学习笔记(深入)”;

  • 第二个参数必须是指向目标类型的指针(&pathErr
  • errors.As 同样遍历整个错误链,找到第一个匹配的类型即返回 true
  • 如果只是想确认类型存在而不需变量,仍得声明变量并传地址,无法跳过

避免用 reflect.TypeOf 或 error.Error() 做类型判断

有人会写 strings.Contains(err.Error(), "permission denied")reflect.TypeOf(err).Name() == "PathError",这两种方式都不可靠:

  • Error() 返回字符串可能被多层包装修改,且不同语言环境输出不同
  • reflect.TypeOf 只看最外层类型,对 fmt.Errorf("failed: %w", &os.PathError{}) 会返回 errorString,而非 PathError
  • 标准库错误类型(如 os.ErrNotExist)本身是变量,应优先用 errors.Is 对比,而不是靠名字或字符串猜

自定义错误类型要实现 Unwrap 方法才能被正确识别

如果你自己定义了带包装能力的错误类型,必须显式实现 Unwrap() error 方法,否则 errors.Iserrors.As 无法穿透到内层:

type MyError struct {msg  string     orig error} 

func (e MyError) Error() string { return e.msg} func (e MyError) Unwrap() error { return e.orig} // 必须有这一行

漏掉 Unwrap 是测试中错误断言失效的高频原因——外部调用方根本「看不到」你包装的原始错误。

星耀云
版权声明:本站原创文章,由 星耀云 2026-01-08发表,共计1252字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。