golang递归地反映字段类型和值 [英] golang recursively reflect both type of field and value

查看:129
本文介绍了golang递归地反映字段类型和值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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递归地反映字段类型和值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆