接口指针的奇怪行为

时间:2018-11-24 22:52:25

标签: 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{}) {             // 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{}{}的接口,只是不明白为什么它会失败。

1 个答案:

答案 0 :(得分:0)

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

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

如果您将main1更改为:

,则功能main2f会按我认为的那样工作。
func f(x interface{}) {             // print x's underlying value
    fmt.Println(reflect.ValueOf(x))
}

fmain3的参数是*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()调用将返回一个包含该具体值的接口。