Go 如何检查函数的返回值是否满足错误接口

Go 如何检查函数的返回值是否满足错误接口,go,reflection,go-reflect,Go,Reflection,Go Reflect,我想编写一些代码来检查结构的方法,并对它们做出某些断言,例如,它们返回的最后一个结果应该是错误。我尝试了以下示例脚本: import ( "context" "reflect" ) type Service struct { name string } func (svc *Service) Handle(ctx context.Context) (string, error) { return svc.name, nil } func main() {

我想编写一些代码来检查结构的方法,并对它们做出某些断言,例如,它们返回的最后一个结果应该是错误。我尝试了以下示例脚本:

import (
    "context"
    "reflect"
)

type Service struct {
    name string
}

func (svc *Service) Handle(ctx context.Context) (string, error) {
    return svc.name, nil
}

func main() {
    s := &Service{}
    t := reflect.TypeOf(s)

    for i := 0; i < t.NumMethod(); i++ {
        f := t.Method(i).Func.Type()

        f.Out(f.NumOut() - 1).Implements(reflect.TypeOf(error))
    }
}
相反,compile的内容是结尾处的以下两行:

    var err error
    f.Out(f.NumOut() - 1).Implements(reflect.TypeOf(err))
然而,这引起了恐慌:

panic: reflect: nil type passed to Type.Implements

检查最后一个参数是否实现错误接口的正确方法是什么?换句话说,如何获取错误接口的reflect.Type?

使用指向接口的指针,并获取其元素,如下所示:

f.Out(f.NumOut() - 1).Implements(reflect.TypeOf((*error)(nil)).Elem())

使用指向接口的指针,并获取其元素,如下所示:

f.Out(f.NumOut() - 1).Implements(reflect.TypeOf((*error)(nil)).Elem())
要在不使用现有错误的情况下获取错误的reflect.TypeOf,可以使用以下一行:

reflect.TypeOf((*error)(nil)).Elem()
基本上,它首先获取指向error*error的指针的类型,然后Elem将TypeOf与错误的类型区分开来

要在不使用现有错误的情况下获取错误的reflect.TypeOf,可以使用以下一行:

reflect.TypeOf((*error)(nil)).Elem()
基本上,它首先获取指向error*error的指针的类型,然后Elem将TypeOf与错误的类型区分开来

如果最后一个返回值应为且错误不使用工具,则这是不够的,x工具e与x工具e不同

只需检查类型的名称和包路径。对于预声明的类型(包括错误),包路径为空字符串

实现错误的非错误类型

名为error的本地声明类型,它未实现内置错误

实际的内置错误

如果最后一个返回值应为且错误不使用工具,则这是不够的,x工具e与x工具e不同

只需检查类型的名称和包路径。对于预声明的类型(包括错误),包路径为空字符串

实现错误的非错误类型

名为error的本地声明类型,它未实现内置错误

实际的内置错误


您可能想要确定最后一个结果是否有类型错误,而不是它实现了错误。如果是,请使用f.outp.NumOut-1==reflect.TypeOf*errornil.Elem.mably duplicate:。您可能希望确定最后一个结果是否存在类型错误,而不是它实现了错误。如果是,请使用f.outp.NumOut-1==reflect.TypeOf*errornil.Elem。可能的重复项:。
implements error? true
is error? false
type Service struct {
    name string
}

type error interface { Abc() }

func (svc *Service) Handle(ctx context.Context) (string, error) {
    return svc.name, nil
}

type builtin_error interface { Error() string }

func main() {
    s := &Service{}
    t := reflect.TypeOf(s)

    for i := 0; i < t.NumMethod(); i++ {
        f := t.Method(i).Func.Type()
        rt := f.Out(f.NumOut() - 1)
        fmt.Printf("implements error? %t\n", rt.Implements(reflect.TypeOf((*builtin_error)(nil)).Elem()))
        fmt.Printf("is error? %t\n", rt.Name() == "error" && rt.PkgPath() == "")
    }
}
implements error? false
is error? false
type Service struct {
    name string
}

func (svc *Service) Handle(ctx context.Context) (string, error) {
    return svc.name, nil
}

func main() {
    s := &Service{}
    t := reflect.TypeOf(s)

    for i := 0; i < t.NumMethod(); i++ {
        f := t.Method(i).Func.Type()
        rt := f.Out(f.NumOut() - 1)
        fmt.Printf("implements error? %t\n", rt.Implements(reflect.TypeOf((*error)(nil)).Elem()))
        fmt.Printf("is error? %t\n", rt.Name() == "error" && rt.PkgPath() == "")
    }
}
implements error? true
is error? true