英文:
How to reflect struct recursive in golang
问题
我想递归地反射结构类型和值,但是失败了。我不知道如何递归地传递子结构。
它报错如下:
panic: reflect: NumField of non-struct type
goroutine 1 [running]:
reflect.(*rtype).NumField(0xc0b20, 0xc82000a360)
/usr/local/go/src/reflect/type.go:660 +0x7b
我有两个结构体Person
和Name
:
type Person struct {
Fullname NameType
Sex string
}
type Name struct {
Firstname string
Lastname string
}
我在主函数中定义了Person
,并使用递归函数显示结构体。
person := Person{
Name{"James", "Bound"},
"Male",
}
display(&person)
display
函数递归显示结构体。
func display(s interface{}) {
reflectType := reflect.TypeOf(s).Elem()
reflectValue := reflect.ValueOf(s).Elem()
for i := 0; i < reflectType.NumField(); i++ {
typeName := reflectType.Field(i).Name
valueType := reflectValue.Field(i).Type()
valueValue := reflectValue.Field(i).Interface()
switch reflectValue.Field(i).Kind() {
case reflect.String:
fmt.Printf("%s : %s(%s)\n", typeName, valueValue, valueType)
case reflect.Int32:
fmt.Printf("%s : %i(%s)\n", typeName, valueValue, valueType)
case reflect.Struct:
fmt.Printf("%s : it is %s\n", typeName, valueType)
display(&valueValue)
}
}
}
英文:
I want to reflect the struct type and value recursively, but it fails. I don't know how to pass the sub struct recursively.
It error the following.
panic: reflect: NumField of non-struct type
goroutine 1 [running]:
reflect.(*rtype).NumField(0xc0b20, 0xc82000a360)
/usr/local/go/src/reflect/type.go:660 +0x7b
I have two struct Person
and Name
type Person struct {
Fullname NameType
Sex string
}
type Name struct {
Firstname string
Lastname string
}
I define the Person
in main, and display the struct with recursive function.
person := Person{
Name{"James", "Bound"},
"Male",
}
display(&person)
The display
function recursive display the struct.
func display(s interface{}) {
reflectType := reflect.TypeOf(s).Elem()
reflectValue := reflect.ValueOf(s).Elem()
for i := 0; i < reflectType.NumField(); i++ {
typeName := reflectType.Field(i).Name
valueType := reflectValue.Field(i).Type()
valueValue := reflectValue.Field(i).Interface()
switch reflectValue.Field(i).Kind() {
case reflect.String:
fmt.Printf("%s : %s(%s)\n", typeName, valueValue, valueType)
case reflect.Int32:
fmt.Printf("%s : %i(%s)\n", typeName, valueValue, valueType)
case reflect.Struct:
fmt.Printf("%s : it is %s\n", typeName, valueType)
display(&valueValue)
}
}
}
答案1
得分: 7
在你的display
函数内部,你声明了valueValue
:
valueValue := reflectValue.Field(i).Interface()
所以valueValue
的类型是interface{}
。在for
循环内部,你对display
进行了递归调用:
display(&valueValue)
因此,它被调用时的参数类型是*interface{}
。在递归调用内部,reflectType
将表示interface{}
而不是存储在值中的实际类型。由于NumField
只能在表示结构体的reflect.Type
上调用,所以会引发错误。
如果你想用指向结构体的指针调用display
,你可以这样做:
v := valueValue := reflectValue.Field(i).Addr()
display(v.Interface())
英文:
Inside your display
function, you declare valueValue
as:
valueValue := reflectValue.Field(i).Interface()
So valueValue
is of type interface{}
. Inside the for loop, you have a recursive call to display
:
display(&valueValue)
So it is being called with an argument of type *interface{}
. Inside the recursive call, reflectType
will represent interface{}
rather than the type that happens to be stored within the value. Since NumField
can only be called on reflect.Type
's representing structs, you get a panic.
If you want to call display with a pointer to the struct instead, you could do so with something like this:
v := valueValue := reflectValue.Field(i).Addr()
display(v.Interface())
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论