функция с получателем, которая выполняет итерацию по некоторому полю структуры в go - PullRequest
0 голосов
/ 10 июля 2020

Я Golang новичок ie пытаюсь создать простой интерфейс командной строки. Я конвертирую полезную нагрузку вызова API в структуру и хочу отформатировать некоторую информацию из этой структуры в красивую строку для печати. Одна из информации, которую я хочу напечатать, - это массив структур, как в этом примере:

type Pokemon struct {
    Abilities []struct {
        Ability struct {
            Name string `json:"name"`
            URL  string `json:"url"`
        } `json:"ability"`
        IsHidden bool `json:"is_hidden"`
        Slot     int  `json:"slot"`
    } `json:"abilities"`
    Height int    `json:"height"`
    ID     int    `json:"id"`
    Name   string `json:"name"`
    Types  []struct {
        Slot int `json:"slot"`
        Type struct {
            Name string `json:"name"`
            URL  string `json:"url"`
        } `json:"type"`
    } `json:"types"`
    Weight int `json:"weight"`
}
}

Я пытаюсь написать общую c рецепторную функцию, которая выполняет итерацию по некоторым полям, которые являются структурными. массивы и объединить их поля в строку. Я могу выполнить функцию, которая выполняет итерацию по некоторому полю, например:

func (p Pokemon) stringifyPokemonAbilities() string {
    var listOfAbilities []string
    for _, ability := range p.Abilities {
        listOfAbilities = append(listOfAbilities, ability.Ability.Name)
    }
    return strings.Join(listOfAbilities[:], " / ")
}

Возвращает, например, synchronize / inner-focus

Работая таким образом, мне придется написать почти ту же функцию в Type поле. Мой вопрос в том, как сделать эту функцию более общей c, принимая поле и повторяя его. Есть мысли?

1 Ответ

0 голосов
/ 10 июля 2020

Вы можете сделать это, используя relfect . Существует хорошо написанное учебное пособие , на которое вы можете взглянуть.

Согласно структуре, которую вы даете, я написал демо. Основная идея - найти структуру, поданную по имени, затем выполнить итерацию среза, найти имя в структуре.

Вы можете получить ответ, используя p.stringifyPokemon("Types") или p.stringifyPokemon("Abilities") сейчас.

func (p Pokemon) stringifyPokemon(field string) string {
    value := reflect.ValueOf(p)
    struct1 := value.FieldByName(field)

    if !struct1.IsValid() {
        return ""
    }

    if struct1.Type().Kind() != reflect.Slice {
        return ""
    }

    ans := make([]string, 0)

    for i := 0; i < struct1.Len(); i++ {
        slice1 := struct1.Index(i)
        if slice1.Type().Kind() != reflect.Struct {
            continue
        }

        for j := 0; j < slice1.NumField(); j++ {
            struct2 := slice1.Field(j)
            if struct2.Type().Kind() != reflect.Struct {
                continue

            }
            name := struct2.FieldByName("Name")
            if name.Kind() != reflect.String {
                continue
            }
            ans = append(ans, name.String())
        }
    }

    return strings.Join(ans[:], " / ")
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...