如何使用带有nil输入的reflect.Value.Call()?

Sam*_*ury 3 reflection go

我想在Go中调用一个函数,在方法值上使用reflect.Value.Call,并将nil作为参数传递.请参阅下面的代码以获取说明.

我已经尝试在输入数组中使用reflect.ValueOf(nil)reflect.Value{},但是第一次恐慌是因为nil没有值; 当我把它传递给Call时,第二次恐慌,因为它是一个Zero reflect.Value.

请注意,正如代码所示,当然可以将nil传递给没有反射的函数,包括当该参数是接收器时.问题是:是否可以使用reflect.Value.Call调用func,将其中一个参数传递为nil?

您可以在http://play.golang.org/p/x9NXMDHWdM上构建并运行以下代码

package main

import "reflect"

type Thing struct{}

var (
    thingPointer = &Thing{}
    typ          = reflect.TypeOf(thingPointer)
)

func (t *Thing) DoSomething() {
    if t == nil {
        println("t was nil")
    } else {
        println("t was not nil")
    }
}

func normalInvokation() {
    thingPointer.DoSomething()
    // prints "t was not nil"
    t := thingPointer
    t = nil
    t.DoSomething()
    // prints "t was nil"
}

func reflectCallNonNil() {
    m, _ := typ.MethodByName("DoSomething")
    f := m.Func
    f.Call([]reflect.Value{reflect.ValueOf(&Thing{})})
    // prints "t was not nil"
}

func reflectCallNil() {
    // m, _ := typ.MethodByName("DoSomething")
    // f := m.Func
    // f.Call(???)
    // how can I use f.Call to print "t was nil" ?
}

func main() {
    normalInvokation()
    reflectCallNonNil()
    reflectCallNil()
}
Run Code Online (Sandbox Code Playgroud)

Not*_*fer 6

一种选择是简单地告诉reflect你,你指的是一个零指针Thing:

func reflectCallNonNil() {
    m, _ := typ.MethodByName("DoSomething")
    f := m.Func
    f.Call([]reflect.Value{reflect.ValueOf((*Thing)(nil))})

}
Run Code Online (Sandbox Code Playgroud)

此外,您可以使用reflect.Zero它为您提供类型的"零值".所以这个上下文中的零是指针的零值Thing.

因此,这样做将起作用:

func reflectCallNil() {
    m, _ := typ.MethodByName("DoSomething")
    f := m.Func
    f.Call([]reflect.Value{reflect.Zero(reflect.TypeOf(&Thing{}))})
}
Run Code Online (Sandbox Code Playgroud)