英文:
How can I use reflect.Value.Call() with a nil input?
问题
我想在Go中调用一个函数,使用reflect.Value.Call在方法值上,并将nil作为参数传递。请参考下面的代码示例。
我尝试在输入数组中使用reflect.ValueOf(nil)
和reflect.Value{}
,但第一个会引发panic,因为nil没有值;第二个在我将其传递给Call时引发panic,因为它是一个Zero reflect.Value。
请注意,正如代码所示,可以在不使用反射的情况下将nil传递给函数,包括当该参数是接收器时。问题是:是否可以使用reflect.Value.Call调用一个函数,将其中一个参数设置为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()
}
英文:
I want to invoke a function in Go, using reflect.Value.Call on a method value, and pass nil as a parameter. See the code below for an illustration.
I have tried using reflect.ValueOf(nil)
and reflect.Value{}
in the input array, but the first panics because nil has no value; the second panics when I pass it to Call, because it is a Zero reflect.Value.
Note that, as the code illustrates, it is certainly possible to pass nil to a function without reflection, including when that argument is the receiver. The question is: Is it possible to invoke a func using reflect.Value.Call, passing one of those parameters as nil?
You can build and run the code below at: 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()
}
答案1
得分: 6
一种选择是直接告诉reflect
你指的是一个指向Thing
的空指针:
func reflectCallNonNil() {
m, _ := typ.MethodByName("DoSomething")
f := m.Func
f.Call([]reflect.Value{reflect.ValueOf((*Thing)(nil))})
}
另外,你可以使用reflect.Zero
,它会给你一个类型的"零值"。所以在这个上下文中,nil就是指向Thing
的指针的零值。
因此,这样做也是可以的:
func reflectCallNil() {
m, _ := typ.MethodByName("DoSomething")
f := m.Func
f.Call([]reflect.Value{reflect.Zero(reflect.TypeOf(&Thing{}))})
}
英文:
One option is to simply tell reflect
that you mean a nil pointer to Thing
:
func reflectCallNonNil() {
m, _ := typ.MethodByName("DoSomething")
f := m.Func
f.Call([]reflect.Value{reflect.ValueOf((*Thing)(nil))})
}
Also, you can use reflect.Zero
which gives you a "zero value" for a type. So nil in this context is the zero value of pointer to Thing
.
Thus, doing this will work:
func reflectCallNil() {
m, _ := typ.MethodByName("DoSomething")
f := m.Func
f.Call([]reflect.Value{reflect.Zero(reflect.TypeOf(&Thing{}))})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论