为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
白衣染霜花 2022-05-18 16:29:01
我想编写一些代码来检查结构的方法并对它们做出某些断言,例如,它们返回的最后一个东西应该是error. 我尝试了以下示例脚本: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))    }}然而,这会产生一个./main.go:23:51: type error is not an expression编译的是最后的以下两行:    var err error    f.Out(f.NumOut() - 1).Implements(reflect.TypeOf(err))但是,这会产生恐慌:panic: reflect: nil type passed to Type.Implements检查最后一个参数是否实现error接口的正确方法是什么?换句话说,我如何获得reflect.Type一个error接口?
查看完整描述

3 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

如果最后一个返回值“应该是”并且error不使用Implements,这还不够,x实现e 与 x是e 不同。


只需检查类型的名称和包路径。对于预先声明的类型,包括error,包路径是一个空字符串。


实现的非错误类型error。


type Service struct {

    name string

}


type sometype struct {}


func (sometype) Error() string { return "" }


func (svc *Service) Handle(ctx context.Context) (string, sometype) {

    return svc.name, sometype{}

}


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? false

一个本地声明的类型,名为error不实现内置的error。


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

实际的内置error.


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


查看完整回答
反对 回复 2022-05-18
?
千巷猫影

TA贡献1829条经验 获得超7个赞

使用指向接口的指针,并获取Elem它,如下所示:

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


查看完整回答
反对 回复 2022-05-18
?
慕莱坞森

TA贡献1810条经验 获得超4个赞

要在不使用现有错误的情况下获得reflect.TypeOfof an error,您可以使用以下单行代码:

reflect.TypeOf((*error)(nil)).Elem()

基本上,它首先获取指向 error( *error) 的指针的类型,然后Elem()将 TypeOf“引用”到 的类型error


查看完整回答
反对 回复 2022-05-18
  • 3 回答
  • 0 关注
  • 105 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信