Golang 通过反射将 nil 值作为接口传递

Gro*_*ozz 3 reflection go

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

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

我如何通过它传递一个 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})
}
Run Code Online (Sandbox Code Playgroud)

方法二:

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})
}
Run Code Online (Sandbox Code Playgroud)

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

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

Cer*_*món 6

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

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

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

使用以下内容创建nilArg

nilArg := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem())
Run Code Online (Sandbox Code Playgroud)

游乐场示例