You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go 1.20中如何统计errors.Join()合并的错误数量?

如何统计Go中errors.Join返回的错误数量

核心思路

Go标准库的errors.Join返回的错误类型是私有实现(joinError),内部错误切片无法直接访问。要统计错误数量,只能通过标准库提供的公开API(errors.As/errors.Unwrap)来遍历或断言所有错误。

实现方式

1. 基础统计(非嵌套Join场景)

如果你的错误没有嵌套errors.Join的结果,可以直接用errors.As断言获取所有错误切片,再取长度:

import "errors"

func getErrorCount(err error) int {
	if err == nil {
		return 0
	}
	var errs []error
	if errors.As(err, &errs) {
		return len(errs)
	}
	// 处理单个错误的Unwrap链
	count := 1
	for unwrapErr := errors.Unwrap(err); unwrapErr != nil; unwrapErr = errors.Unwrap(unwrapErr) {
		count++
	}
	return count
}

2. 递归统计(支持嵌套Join场景)

如果存在errors.Join嵌套的情况(比如Join(err1, Join(err2, err3))),需要递归遍历所有层级的错误:

import "errors"

func countAllErrors(err error) int {
	if err == nil {
		return 0
	}

	// 尝试断言是否为Join返回的错误集合
	var joinErrs []error
	if errors.As(err, &joinErrs) {
		total := 0
		for _, e := range joinErrs {
			total += countAllErrors(e)
		}
		return total
	}

	// 处理单个错误的Unwrap链
	total := 1
	for unwrapErr := errors.Unwrap(err); unwrapErr != nil; unwrapErr = errors.Unwrap(unwrapErr) {
		total += countAllErrors(unwrapErr)
	}
	return total
}

你的测试代码修改

针对示例中的test_doSomething,可以直接调用上面的统计函数:

func test_doSomething(t *testing.T) {
   actual := doSomething()
   assert.Equal(t, 2, countAllErrors(actual))
}

注意事项

  • 不要依赖错误字符串的格式(比如"3 errors occurred"):标准库的错误输出格式属于实现细节,不保证向后兼容,业务逻辑或测试中不应以此作为统计依据。
  • 示例中doSomething的逻辑问题:当前代码第二次调用errors.Join(err2, err1)会覆盖之前的multierror,最终仅返回2个错误。如果需要累积错误,应改为multierror = errors.Join(multierror, err2),此时统计结果会是3个错误(原2个err1 + 1个err2)。

内容的提问来源于stack exchange,提问作者Philipp Pixel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 23:25:55