英文:
Access pointer value of a struct inside a function
问题
我想将一个结构体对象传递给一个函数,并能够从该函数中访问其指针值。我无法理解为什么以下代码会导致错误。
为了使其工作,我不得不将structType
作为参数,如下所示:
func GetStructFieldPointers(u interface{}, structType reflect.Type, jsonFields []string) []interface{} {
structVal := reflect.ValueOf(u).Elem()
// structType := reflect.TypeOf(u)
numberOfFields := structVal.NumField()
numberOfJSONFields := len(jsonFields)
res := make([]interface{}, numberOfJSONFields)
fmt.Println(jsonFields)
for fieldIndex, field := range jsonFields {
for i := 0; i < numberOfFields; i++ {
if structType.Field(i).Tag.Get("json") == field {
valueField := structVal.Field(i)
res[fieldIndex] = valueField.Addr().Interface()
}
}
}
return res
}
user := User{}
res := GetStructFieldPointers(&user, reflect.TypeOf(user), []string{"id", "name"})
我想知道如何将User{}
作为参数,并在reflect.ValueOf
和reflect.TypeOf
调用中使用。
英文:
I want to pass a struct object to a function & be able to access its pointer value from that function. I am not able to understand why the following is resulting in error.
func GetStructFieldPointers(u interface{}, jsonFields []string) []interface{} {
structVal := reflect.ValueOf(&u).Elem()
structType := reflect.TypeOf(u)
numberOfFields := structVal.NumField() // getting error here reflect:
// call of reflect.Value.NumField
// on interface Value
numberOfJSONFields := len(jsonFields)
res := make([]interface{}, numberOfJSONFields)
fmt.Println(jsonFields)
for fieldIndex, field := range jsonFields {
for i := 0; i < numberOfFields; i++ {
if structType.Field(i).Tag.Get("json") == field {
valueField := structVal.Field(i)
res[fieldIndex] = valueField.Addr().Interface()
}
}
}
return res
}
type User struct {
Id int `json:"id"`
Name string `json:"name"`
Address string `json:"address"`
}
user := User{}
res := GetStructFieldPointers(user, []string{"id", "name"})
To make this work, I had to make structType
as a parameter like following:
func GetStructFieldPointers(u interface{}, structType reflect.Type, jsonFields []string) []interface{} {
structVal := reflect.ValueOf(u).Elem()
// structType := reflect.TypeOf(u)
numberOfFields := structVal.NumField()
numberOfJSONFields := len(jsonFields)
res := make([]interface{}, numberOfJSONFields)
fmt.Println(jsonFields)
for fieldIndex, field := range jsonFields {
for i := 0; i < numberOfFields; i++ {
if structType.Field(i).Tag.Get("json") == field {
valueField := structVal.Field(i)
res[fieldIndex] = valueField.Addr().Interface()
}
}
}
return res
}
user := User{}
res := GetStructFieldPointers(&user, reflect.TypeOf(user), []string{"id", "name"})
I like to know how to pass User{}
as a parameter & use in both reflect.ValueOf & reflect.TypeOf calls.
答案1
得分: 3
在这行代码 structVal := reflect.ValueOf(&u).Elem()
中,你获取的是一个接口的地址(你的函数的参数),而不是接口底层值的地址,然后你将指针传递给了 ValueOf
,所以 .Elem()
调用返回的是指针指向的 "elem value",也就是接口,而不是结构体。
如果你确定传入的值是结构体而不是指针,你只需要这样写:structVal := reflect.ValueOf(u)
。
如果你的函数传入的是指针,例如 GetStructFieldPointers(&u, ...
,那么你需要这样写:structVal := reflect.ValueOf(u).Elem()
。
但是你也可以通过检查值的类型来处理这两种情况。
rv := reflect.ValueOf(u)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() == reflect.Struct {
fmt.Println(rv.NumField())
}
更新:
我仔细看了你的代码... 如果你想要获取结构体字段的地址,你需要将结构体的指针作为参数传递,否则这些字段将无法获取地址。
链接:https://play.golang.org/p/RaA2rau3s-
英文:
On this line: structVal := reflect.ValueOf(&u).Elem()
you're taking the address of an interface (the argument of your func) and not an address to the interface's underlying value, and then you're passing the pointer to ValueOf
, so the .Elem()
call returns the "elem value" to which the pointer points to, which is the interface
, not struct.
If you know for a fact that the passed in value is a struct and not a pointer, all you need is this: structVal := reflect.ValueOf(u)
.
If a pointer was passed to your func, eg GetStructFieldPointers(&u, ...
then this is what you want: structVal := reflect.ValueOf(u).Elem()
.
But also you can handle both cases by checking the value's kind.
rv := reflect.ValueOf(u)
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
if rv.Kind() == reflect.Struct {
fmt.Println(rv.NumField())
}
https://play.golang.org/p/9F9LNnwEaH
Update:
Took a better look at your code... If you want to be able to get the addresses of your struct's fields, you need to pass a pointer to the struct as the argument, or else those fields are going to be unaddressable.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论