当前位置:首页 > 文章列表 > Golang > Go问答 > Go errors.As 目标参数为什么必须是非空指针

Go errors.As 目标参数为什么必须是非空指针

来源:17golang原创 2026-09-27 21:37:28 0浏览 收藏

errors.As 的 target 必须是非空指针,因为它不只是检查类型,还要把错误树中找到的具体错误写进调用者提供的变量。最容易误解的一点是:目标变量本身可以是 nil,不能为 nil 的是传给 errors.As 的外层地址。

官方文档:https://pkg.go.dev/errors#As

要点速览
  • var target *MyError 初始为 nil 没问题,调用时应传 &target。
  • target 必须是非 nil 指针,且它指向的类型要实现 error,或者本身是接口类型。
  • errors.As 会检查整棵错误树,并把首个可赋值的匹配值写回目标变量。
  • 目标参数形状错误属于程序员错误,因此标准库选择 panic,而不是返回 false。

先用最小实验看懂双指针

我第一次写 errors.As 时也觉得 &target 多了一层。真正理解后就很简单:错误值通常是 *ValidationError,而目标变量也要保存这个指针;为了让函数修改目标变量,就必须再传目标变量自己的地址,于是参数类型自然变成 **ValidationError。

type ValidationError struct {
    Field string
}

func (e *ValidationError) Error() string {
    return "invalid field: " + e.Field
}

func validate() error {
    // 用 %w 保留底层错误,使 errors.As 能继续检查错误树
    return fmt.Errorf("save config: %w", &ValidationError{Field: "port"})
}

func main() {
    err := validate()
    var target *ValidationError // 目标值可以暂时是 nil

    // &target 是非 nil 的可写槽位,匹配值会写回 target
    if errors.As(err, &target) {
        fmt.Println(target.Field)
    }
}
errors.As 目标参数、非空指针、可写槽位和目标类型边界结构图
图1:errors.As 目标参数边界结构图,说明外层指针用于提供可写槽位,不是运行截图。

三个条件中任何一个不满足都会 panic

官方文档给出的约束可以拆成三项。第一,传入值必须是指针;第二,这个指针不能为 nil;第三,指针指向的类型必须实现 error,或者是任意接口类型。下面几种写法看似相近,运行意义完全不同:

var pointerTarget *ValidationError

// 错误:传入的是 nil 的 *ValidationError,不是目标变量的地址
// errors.As(err, pointerTarget)

var valueTarget ValidationError
// 错误:传入的是普通结构体,errors.As 没有位置写回结果
// errors.As(err, valueTarget)

// 正确:&pointerTarget 是 **ValidationError,提供了可写槽位
if errors.As(err, &pointerTarget) {
    fmt.Println(pointerTarget.Field)
}

这也是为什么参数错误会 panic:false 应只表示“错误树里没有匹配类型”,不能同时表示“调用方式本身无效”。把两类问题分开后,测试失败时更容易定位。

匹配发生在错误树,结果写进目标变量

errors.As 会先检查根错误,再深度优先检查由 Unwrap() error 或 Unwrap() []error 暴露的子节点。某个具体错误可赋值给目标指向的类型时就匹配成功;如果错误类型自定义了 As(any) bool,也可以参与匹配。找到首个匹配后,标准库把该值写入目标变量并返回 true。

errors.As 在根错误、包装错误和子错误中匹配目标类型的结构图
图2:errors.As 错误树匹配结构图,展示被检查节点与目标变量的类型关系。

接口目标也遵循同一规则,只是目标变量声明为接口。例如要识别可报告临时状态的错误,可以先定义最小接口,再传它的地址:

type temporary interface {
    Temporary() bool
}

var target temporary
// 指向接口变量的非 nil 指针同样可以接收匹配值
if errors.As(err, &target) && target.Temporary() {
    fmt.Println("retry later")
}

新版 Go 可以考虑 errors.AsType

在提供 errors.AsType 的 Go 版本中,大多数只想取得具体错误值的场景可以直接接收返回值,不再手动准备双指针。它仍然检查错误树和自定义 As 方法,但把类型参数和返回值放在调用表达式里,误传 nil target 的机会更少。

// 泛型参数直接表达要查找的错误类型,返回值就是匹配结果
if target, ok := errors.AsType[*ValidationError](err); ok {
    fmt.Println(target.Field)
}

如果项目需要兼容较早的 Go 工具链,继续使用 errors.As 即可。我的做法是把 var target *T 与 errors.As(err, &target) 紧挨着写,并在测试中覆盖直接错误、单层包装、多层包装和无匹配四种情况。

target 变量为 nil 为什么还能成功?

因为 nil 是 *ValidationError 的零值,而传入的 &target 是一个真实、非 nil 的地址,函数可以把匹配到的指针写进去。

能不能传 new(ValidationError)?

这只是 *ValidationError,而指针错误类型通常需要 **ValidationError 作为写回位置。最清楚的写法仍是先声明目标变量,再传它的地址。

errors.As 返回 false 后能使用 target 吗?

不应依赖它。把目标变量视为只有在返回 true 时才有效,可以避免复用旧变量时误读残留值。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
artworkout有哪些绘画课程?阴影、动物与Loomis课程入口说明artworkout有哪些绘画课程?阴影、动物与Loomis课程入口说明
上一篇
artworkout有哪些绘画课程?阴影、动物与Loomis课程入口说明
RAG 重排器的候选数量和最终 TopK 怎么设置
下一篇
RAG 重排器的候选数量和最终 TopK 怎么设置
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    240次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    289次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    255次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    238次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    46次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码