我写了3个类似的函数来找出Go指针反射的奇怪行为。
package main
import (
"reflect"
"fmt"
)
var i interface{} = struct {}{} // i is an interface which points to a struct
var ptr *interface{} = &i // ptr is i's pointer
func f(x interface{}) { // print x's underlying value
fmt.Println(reflect.ValueOf(x).Elem())
}
func main1() { // f is asking for interface? OK, I'll use the struct's interface
structValue := reflect.ValueOf(ptr).Elem().Elem().Interface()
f(structValue)
}
func main2() { // Error? Let me try the struct's pointer
structPtr := reflect.ValueOf(ptr).Elem().Interface()
f(structPtr)
}
func main3() { // Why this one could succeed after New() ?
typ := reflect.ValueOf(ptr).Elem().Elem().Type()
newPtr := reflect.New(typ).Elem().Addr().Interface()
f(newPtr)
}
func main() {
//main1() // panic: reflect: call of reflect.Value.Elem on struct Value
//main2() // panic: reflect: call of reflect.Value.Elem on struct Value
main3() // OK. WHY???
}
只有main3在工作,其他2会出现故障。为什么? 3的主要区别在于它创建了一个新值。
对于main2,我认为ValueOf().Elem().Interface()
已经重建了指向struct{}{}
的接口,只是不明白为什么它会失败。
答案 0 :(得分:0)
reflect.ValueOf返回的值保存存储在参数中的具体值。如果参数为nil,则返回零体现值。
换句话说,reflect.Value和传递给reflect.Value的接口具有相同的基础值。
如果您将main1
更改为:
main2
和f
会按我认为的那样工作。
func f(x interface{}) { // print x's underlying value
fmt.Println(reflect.ValueOf(x))
}
f
中main3
的参数是*struct{}
。函数f
取消引用指针(通过调用Elem())并打印struct{}
的反射值。
可能令人困惑的一点是,reflect.ValueOf(ptr).Elem().Elem().Interface()
和reflect.ValueOf(ptr).Elem().Interface()
返回的接口具有相同的具体值。
表达式reflect.ValueOf(ptr).Elem()
是对应于i
的反射值。对该值的Interface()
调用将返回一个接口,其中包含i
中的具体值。
表达式reflect.ValueOf(ptr).Elem().Elem()
是与i
的具体值相对应的反射值。对该值的Interface()
调用将返回一个包含该具体值的接口。