reflect.Value.MapIndex()返回一个与reflect.ValueOf()不同的值

时间:2013-01-03 16:10:53

标签: reflection go

根据反射文档reflect.Value.MapIndex()应返回reflect.Value,表示存储在地图特定键上的数据的值。所以我的理解是以下两个表达式应该是相同的。在第一种情况下,我们从MapIndex()获得结果。在第二步中,我们从MapIndex()得到它的基础数据,然后对其进行reflect.ValueOf()得到结果。

reflect.ValueOf(map).MapIndex("Key")
reflect.ValueOf(reflect.ValueOf(map).MapIndex("Key").Interface())

为什么需要额外的reflect.ValueOf()

示例代码:

package main

import "fmt"
import "reflect"

func main() {
    test := map[string]interface{}{"First": "firstValue"}
    Pass(test)
}

func Pass(d interface{}) {
    mydata := reflect.ValueOf(d).MapIndex(reflect.ValueOf("First"))
    fmt.Printf("Value: %+v \n", mydata.Interface())
    fmt.Printf("Kind: %+v \n", mydata.Kind())
    fmt.Printf("Kind2: %+v \n", reflect.ValueOf(mydata.Interface()).Kind())
}

去玩:http://play.golang.org/p/TG4SzrtTf0

2 个答案:

答案 0 :(得分:2)

在考虑了一段时间后,这属于 duh 类别。它与Go中interfaces的性质有关,它是指向其他事物的参考对象。我已经明确地声明我的地图是map[string]interface{},这意味着每个键位置的值是interface{},而不是字符串,所以我真的不应该对收到{{1}感到惊讶其中包含reflect.Value

额外的interface{}潜深一层,以获得reflect.ValueOf()的基础价值。我创建了两个例子,我相信这两个例子证实了这种行为。

使用interface{}自定义界面的示例:http://play.golang.org/p/zXCn9Fce3Q

map[string]Stringer

返回

package main

import "fmt"
import "reflect"

type Test struct {
    Data string
}

func (t Test) GetData() string {
    return t.Data
}

type Stringer interface {
    GetData() string
}

func main() {
    test := map[string]Stringer{"First": Test{Data: "testing"}}
    Pass(test)
}

func Pass(d interface{}) {
    mydata := reflect.ValueOf(d).MapIndex(reflect.ValueOf("First"))
    fmt.Printf("Value: %+v \n", mydata.Interface())
    fmt.Printf("Kind: %+v \n", mydata.Kind())
    fmt.Printf("Kind2: %+v \n", reflect.ValueOf(mydata.Interface()).Kind())
}

使用Value: {Data:testing} Kind: interface Kind2: struct http://play.golang.org/p/vXuPzmObgN

的示例
map[string]string

返回

package main

import "fmt"
import "reflect"

func main() {
    test := map[string]string{"First": "firstValue"}
    Pass(test)
}

func Pass(d interface{}) {
    mydata := reflect.ValueOf(d).MapIndex(reflect.ValueOf("First"))
    fmt.Printf("Value: %+v \n", mydata.Interface())
    fmt.Printf("Kind: %+v \n", mydata.Kind())
    fmt.Printf("Kind2: %+v \n", reflect.ValueOf(mydata.Interface()).Kind())
}

答案 1 :(得分:1)

func Pass(d interface{}) {
    mydata := reflect.ValueOf(d).MapIndex(reflect.ValueOf("First"))
    fmt.Printf("Value: %+v \n", mydata.Interface())
    fmt.Printf("Kind: %+v \n", mydata.Kind())

在你的程序的这一点上,mydata是一个接口,所以当调用Kind()时Go不会报告它。

    fmt.Printf("Kind2: %+v \n", reflect.ValueOf(mydata.Interface()).Kind())

打破这个:

s := mydata.Interface()  // s is a string
v := reflect.ValueOf(s)  // v is a reflect.Value
k := v.Kind()            // k is a reflect.Kind "string"

我认为你的地图包含接口而不是字符串这一事实可能会让你感到沮丧。