【问题标题】:Golang pass nil value as an interface through reflectionGolang 通过反射将 nil 值作为接口传递
【发布时间】:2017-10-11 18:33:56
【问题描述】:

我有一个带有接口参数的函数:

func f(e error) {
    if e == nil {
        fmt.Println("YEY! NIL") // how to get here?
    } else {
        fmt.Println("NOT NIL :(")
    }
}

我如何通过reflect 向它传递一个零值,以便它通过== nil 检查?

方法一:

func main() {
    rf := reflect.ValueOf(f)

    nilArg := reflect.Zero(reflect.TypeOf((error)(nil))) // panic: reflect: Zero(nil)

    rf.Call([]reflect.Value{nilArg})
}

方法二:

type MyError struct{}
func (e MyError) Error() string {
    return ""
}

func main() {
    rf := reflect.ValueOf(f)
    nilArg := reflect.Zero(reflect.TypeOf(&MyError{})) // NOT NIL :(

    rf.Call([]reflect.Value{nilArg})
}

由于https://golang.org/doc/faq#nil_error,第二种方法不起作用

游乐场:https://play.golang.org/p/V0bMSPcCKI

【问题讨论】:

  • 为什么 `rf := reflect.ValueOf(f)` 是一个要求? &MyError{} 无论如何都不是零

标签: go reflection


【解决方案1】:

使用表达式reflect.TypeOf((*error)(nil)).Elem() 获取接口error 的reflect.Type。

问题中的第一种方法不起作用,因为表达式reflect.TypeOf((error)(nil)) 返回nil。 nil 接口值的具体类型是 nil。

诀窍是将非接口值传递给reflect.TypeOf(),并使用反射方法从那里获取所需的reflect.Type。在这个答案中,我将*error 传递给reflect.TypeOf() 并在结果上调用Elem 以获得reflect.Typeerror

使用以下命令创建nilArg

nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())

playground example

【讨论】:

    【解决方案2】:

    您有两个选择,基本上函数f 的参数中的e(*MyError)(nil) 而不是nil。所以要么将接口声明回类型MyError,要么使用更多反射来检查它是否为nil。

    e.(*MyError) == nil
    

    reflect.ValueOf(e).IsNil()
    

    可运行示例https://play.golang.org/p/2KWguSx618

    有用的链接:

    【讨论】:

    • 有价值的信息,但问题是关于传递nil 参数,而不是更改函数内部的检查
    • 感谢您的澄清,很高兴您找到了答案!
    猜你喜欢
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2017-12-11
    • 2016-02-23
    • 2022-01-19
    • 1970-01-01
    • 2019-07-05
    相关资源
    最近更新 更多