英文:
reflect.Value.MapIndex() returns a Value different from reflect.ValueOf()
问题
根据反射文档,reflect.Value.MapIndex()应该返回一个表示存储在特定键处的数据的reflect.Value。所以我的理解是以下两个表达式应该是相同的。在第一种情况下,我们从MapIndex()获取结果。在第二种情况下,我们从MapIndex()获取其底层数据,然后对其进行reflect.ValueOf()操作。
为什么需要额外的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())
}
Go Play: http://play.golang.org/p/TG4SzrtTf0
英文:
According to the reflect documentation reflect.Value.MapIndex() should return a reflect.Value which represents the Value of the data stored at a specific key of a map. So my understanding would be that the following two expressions should be identical. In the first case we are getting the result from MapIndex(). In the second we are getting the result from MapIndex() getting it's underlying data and then doing a reflect.ValueOf() on that.
reflect.ValueOf(map).MapIndex("Key")
reflect.ValueOf(reflect.ValueOf(map).MapIndex("Key").Interface())
Why is the additional reflect.ValueOf() required?
Example Code:
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
答案1
得分: 2
这是一个关于Go语言中接口的问题。在代码中,我明确声明了一个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
第二个例子使用了一个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())
}
返回结果:
Value: firstValue
Kind: string
Kind2: string
英文:
After thinking about this for a while this falls under the duh category. It has to do with the nature of interfaces in Go, which are reference objects which point to other things. I have explicitly declared my map to be map[string]interface{} meaning that the value at the location of each key is an interface{}, not a string, so I really shouldn't be surprised to receive a reflect.Value which holds an interface{}.
The additional reflect.ValueOf() dives one layer deeper to gain the underlying Value of the interface{}. I created two examples, both of which I believe confirm this behavior.
Example using a map[string]Stringer custom interface: 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 a 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
得分: 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())
At this point in your program, mydata is an interface, so no surprises that Go reports it as such when Kind() is called.
fmt.Printf("Kind2: %+v \n", reflect.ValueOf(mydata.Interface()).Kind())
Break this down:
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 may be being tripped up by the fact that your map contains interfaces, not strings.
英文:
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 no surprises that Go reports it as such when Kind() is called.
fmt.Printf("Kind2: %+v \n", reflect.ValueOf(mydata.Interface()).Kind())
Break this down:
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 may be being tripped up by the fact that your map contains interfaces, not strings.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论