问题描述
在golang中,我想递归地通过结构体进行反映,以获取字段的名称,类型和值.
In golang, I want to recursively reflect through a struct, getting the name of the field, it's type and the value.
此处的代码帮助我反映了 golang递归式反射
The code here helped me reflect golang recurisive reflection
问题是当我尝试提取该值时,当我在ptr值上反映该值时,我总是会感到恐慌.是否可以同时反映两种类型,并一直传递值直到我到达原始类型,然后打印字段名称,类型和值?
The problem is when I try to extract the value I keep getting panics when I reflect the value on a ptr Value.Is it possible to reflect both the type, and keep passing the value through until I get to the primitives, and at that point print both the field name, type and value?
这是我修改的代码:
func printType(prefix string, t reflect.Type, v reflect.Value visited map[reflect.Type]bool) {
// Print the name of this type with opening ( for description.
fmt.Printf("%s (", t)
// Traverse elements, adding to description as we go.
elems:
for {
switch t.Kind() {
case reflect.Ptr:
fmt.Print("ptr to ")
case reflect.Slice:
fmt.Print("slice of ")
case reflect.Array:
fmt.Printf("array with %d elements of ", t.Len())
default:
break elems
}
t = t.Elem()
}
// Print the kind of the type and the closing ) of the description.
// In the case of a struct, we print the names of the fields and recurse.
switch t.Kind() {
case reflect.Struct:
fmt.Printf("struct with %d fields)\n", t.NumField())
if visited[t] {
// Don't blow up on recursive type definition.
break
}
visited[t] = true
prefix += " "
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
// Get value for field
fieldValue := v.Field(i)
fmt.Print(prefix, f.Name, " ")
printType(prefix, f.Type, fieldValue, visited)
}
default:
fmt.Printf("%s) : %s\n", t.Kind(), v)
}
}
运行此命令时,我在调用fieldValue:= v.Field(i)时感到恐慌关于如何实现这一目标有什么想法吗?
When I run this I get a panic when calling fieldValue := v.Field(i)Any thoughts on how to achieve this?
谢谢
推荐答案
尝试一下:
func printValue(prefix string, v reflect.Value, visited map[interface{}]bool) {
fmt.Printf("%s: ", v.Type())
// Drill down through pointers and interfaces to get a value we can print.
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.Kind() == reflect.Ptr {
// Check for recursive data
if visited[v.Interface()] {
fmt.Println("visted")
return
}
visited[v.Interface()] = true
}
v = v.Elem()
}
switch v.Kind() {
case reflect.Slice, reflect.Array:
fmt.Printf("%d elements\n", v.Len())
for i := 0; i < v.Len(); i++ {
fmt.Printf("%s%d: ", prefix, i)
printValue(prefix+" ", v.Index(i), visited)
}
case reflect.Struct:
t := v.Type() // use type to get number and names of fields
fmt.Printf("%d fields\n", t.NumField())
for i := 0; i < t.NumField(); i++ {
fmt.Printf("%s%s: ", prefix, t.Field(i).Name)
printValue(prefix+" ", v.Field(i), visited)
}
case reflect.Invalid:
fmt.Printf("nil\n")
default:
fmt.Printf("%v\n", v.Interface())
}
}
因为可以从值中获取类型,所以无需将类型传递给打印函数.
Because it's possible to get the type from a value, there's no need to pass types to the print function.
这篇关于golang递归地反映字段类型和值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!