英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论