4

根据反射文档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

4

2 回答 2

2

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

额外的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

使用示例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 
于 2013-01-04T04:32:52.667 回答
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"

我认为您可能会因为您的地图包含接口而不是字符串而被绊倒。

于 2013-01-04T04:46:00.613 回答