使用反射取消引用结构指针和访问字段

rob*_*y22 3 reflection go

我正在编写一个递归函数,它遍历结构中的每个原始字段。

我需要能够支持结构字段、结构指针、字段和字段指针。

我试过做这样的事情,对于每个字段,我首先检查它是否是一个指针。如果是,我会打开它的类型,而不仅仅是字段本身。

//Get reflect values and types
valOf := reflect.ValueOf(dest).Elem()
typeOf := valOf.Type()

//Iterate through each field
for i := 0; i < valOf.NumField(); i++ {

    var fieldValDeref reflect.Value

    //Get reflect value and type of single field
    fieldVal := valOf.Field(i)
    fieldTyp := typeOf.Field(i)

    //Check if field is a pointer. If so, dereference and switch on dereferenced type
    if fieldVal.Kind() == reflect.Ptr {
        fieldValDeref = fieldVal.Elem()
    } else {
        fieldValDeref = fieldVal
    }


    switch fieldValDeref.Kind() {
    case reflect.Array, reflect.Chan, reflect.Interface, reflect.Func, reflect.Map, reflect.UnsafePointer:
        return errors.New("invalid destination field: " + fieldTyp.Name)

    case reflect.Struct:
        //Recursive call
        break
    default:
        //Perform Action on Field
..................................
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是,调用后任何指针、结构与否的类型.Elem()都是reflect.Invalid.

我如何首先取消引用一个字段(如果它是一个指针),然后相应地执行操作,无论该字段是结构体还是基元?

谢谢

rob*_*y22 7

正如mkopriva 所提到的,取消引用 nil 指针将始终返回reflect.Invalid。解决方案是先创建一个新实例。

if fieldVal.Kind() == reflect.Ptr {
    fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
    fieldValDeref = fieldVal.Elem()
} else {
    fieldValDeref = fieldVal
}
Run Code Online (Sandbox Code Playgroud)