Разыменование структуры указателя и доступа к полям с отражением - PullRequest
0 голосов
/ 02 января 2019

Я пишу рекурсивную функцию, которая перебирает все примитивные поля в структуре.

Мне нужно иметь возможность поддерживать поля, которые являются структурами, указатели на структуры, поля и указатели на поля.

Я пытался сделать что-то вроде этого, где для каждого поля я сначала проверяю, является ли он указателем. Если это так, я включаю тип этого, а не только само поле.

//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
..................................

Проблема, с которой я сталкиваюсь, заключается в том, что тип любого указателя, структуры или нет, после вызова .Elem() равен reflect.Invalid.

Как я могу сначала разыменовать поле (если оно является указателем), а затем выполнить соответствующие действия, независимо от того, является ли поле структурой или примитивом?

Спасибо

1 Ответ

0 голосов
/ 03 января 2019

Как упоминалось mkopriva , разыменование нулевого указателя всегда возвращает reflect.Invalid. Решение состоит в том, чтобы сначала создать новый экземпляр.

if fieldVal.Kind() == reflect.Ptr {
    fieldVal.Set(reflect.New(fieldVal.Type().Elem()))
    fieldValDeref = fieldVal.Elem()
} else {
    fieldValDeref = fieldVal
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...