Reflect.Value.MapIndex () returns a value other than reflection. ValueOf ()

According to the documentation for reflection, reflect.Value.MapIndex() should return reflect.Value , which represents the value of the data stored on a particular map key. Therefore, I understand that the following two expressions should be the same. In the first case, we get the result from MapIndex() . In the second, we get the result from MapIndex() get its basic data, and then do reflect.ValueOf() .

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

Why do we need additional reflect.ValueOf() ?

Code example:

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

Go Play: http://play.golang.org/p/TG4SzrtTf0

+4
source share
2 answers

After thinking about this for a while, it falls into the duh category. This is due to the nature of interfaces in Go, which are link objects that point to other things. I explicitly announced that my map would be map[string]interface{} , which means that the value at the location of each key is interface{} , not a string, so I really shouldn't be surprised to get a reflect.Value that contains an interface{} .

Additional reflect.ValueOf() one level deeper to get the base value of interface{} . I created two examples, both of which, I believe, confirm this behavior.

map[string]Stringer user interface example: 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()) } 

returns

 Value: {Data:testing} Kind: interface Kind2: struct 

Example using map[string]string : http://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()) } 

returns

 Value: firstValue Kind: string Kind2: string 
+2
source
 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()) 

At this point in your program, mydata is an interface, so there are no surprises that Go reports about them as such when Kind () is called.

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

Cancel this:

 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" 

I think you might be confused by the fact that your map contains interfaces, not strings.

+1
source

All Articles