2013-01-03 40 views
4

根据反映文档reflect.Value.MapIndex()应该返回reflect.Value,它表示存储在地图特定键上的数据的值。所以我的理解是,以下两个表达应该是相同的。在第一种情况下,我们从MapIndex()得到结果。在第二个我们从MapIndex()得到它的底层数据的结果,然后在那做一个reflect.ValueOf()reflect.Value.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

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

额外的reflect.ValueOf()潜入一层以获得interface{}的基础价值。我创造了两个例子,我相信这两个例子证实了这种行为。使用map[string]Stringer定制接口

示例:使用http://play.golang.org/p/zXCn9Fce3Q

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 

例a map[string]stringhttp://play.golang.org/p/vXuPzmObgN

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()) 
} 

返回

Value: firstValue 
Kind: string 
Kind2: string 
+0

Whups和你在我打字的时候回答! :) –

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是一个接口,所以没有惊喜的是围棋报告为这种类时()被调用。

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" 

我想你可以通过地图中包含的接口,而不是字符串的事实被绊倒了。