Go 接口指针的奇怪行为

Go 接口指针的奇怪行为,go,reflection,interface,go-reflect,Go,Reflection,Interface,Go Reflect,我编写了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{}) {

我编写了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{}{}
的接口,只是不理解它为什么会失败。

从reflect.ValueOf返回的值保存了参数中存储的具体值。如果参数为nil,则返回零reflect.Value

换句话说,reflect.Value和传递给reflect.Value的接口具有相同的基础值

如果将
f
更改为:

func f(x interface{}) {             // print x's underlying value
    fmt.Println(reflect.ValueOf(x))
}
main3
f
的参数是
*结构{}
。函数
f
取消对指针的引用(调用Elem()),并打印
结构{}
的反射值

有一点可能令人困惑,那就是
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()
将返回一个包含该具体值的接口。

我编写main1和main2的原因是我认为
Interface{}
是一种特殊的指针。或者,是不是在戈朗?因此,接口应该能够通过
ValueOf().Elem()调用。。。