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

为何仅在测试代码中出现“errors.As第二个参数不应为*error”编译错误?

Go中errors.As在测试与main函数中表现差异的原因

测试代码编译报错场景

以下测试代码运行时会触发编译错误:

import (
    "errors"
    "fmt"
    "testing"
)

func TestError(t *testing.T) {
    err := &MyError{}
    var target error
    fmt.Println(errors.As(err, &target))
}

type MyError struct{}

func (err *MyError) Error() string {
    return "oops!"
}

错误提示:second argument to errors.As should not be *error

main函数正常运行场景

将完全相同的逻辑放在main函数中,程序可正常执行:

package main

import (
    "errors"
    "fmt"
)

func main() {
    err := &MyError{}
    var target error
    fmt.Println(errors.As(err, &target))
}

type MyError struct{}

func (err *MyError) Error() string {
    return "oops!"
}

我在Go 1.20版本的Playground和本地开发环境中都复现了该现象,这是Go的Bug吗?

绕过测试编译错误的方法

可以通过自定义Error类型来绕过这个检查:

package main

import (
    "errors"
    "fmt"
    "testing"
)

type Error error // 新增自定义Error类型

func TestError(t *testing.T) {
    err := &MyError{}
    var target Error // 使用自定义类型
    fmt.Println(errors.As(err, &target))
}

type MyError struct{}

func (err *MyError) Error() string {
    return "oops!"
}

本质原因:这不是Go的Bug

出现差异的核心原因是测试函数会自动执行vet代码检查工具,而main函数默认不会触发该检查。

vet工具会检测errors.As的参数合理性:errors.As的设计目的是将错误断言转换为具体的错误类型,直接传入*error没有实际意义——如果只是要将错误赋值给另一个error变量,直接赋值即可,完全不需要调用errors.As。

自定义type Error error后,*Error与原生*error属于不同类型,vet不会再触发这个检查,因此可以绕过,但这种写法并不符合errors.As的设计初衷。正确的用法应该是传入具体错误类型的指针,比如:

var target *MyError
fmt.Println(errors.As(err, &target))

内容的提问来源于stack exchange,提问作者Sam Herrmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 06:21:37