猿问

带有接收器的函数,它遍历 go 中结构的某些字段

我是一个 Golang 新手,试图构建一个简单的 CLI。我正在将 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"`

}

}

我正在尝试编写一个通用的受体函数,它遍历一些结构数组的字段并将其字段连接到一个字符串中。我可以做一个专门迭代某些字段的函数,如下所示:


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领域编写几乎相同的功能。我的问题是,如何使这个函数更通用,接受一个字段并对其进行迭代。有什么想法吗?


神不在的星期二
浏览 139回答 1
1回答

跃然一笑

您可以使用relfect来做到这一点。有一个写得很好的教程,你可以看看。根据你给的结构,我写了一个demo。主要思想是通过名称找到结构体,然后迭代切片,在结构体中找到名称。p.stringifyPokemon("Types")您可以使用or p.stringifyPokemon("Abilities")now得到答案。func (p Pokemon) stringifyPokemon(field string) string {&nbsp; &nbsp; value := reflect.ValueOf(p)&nbsp; &nbsp; struct1 := value.FieldByName(field)&nbsp; &nbsp; if !struct1.IsValid() {&nbsp; &nbsp; &nbsp; &nbsp; return ""&nbsp; &nbsp; }&nbsp; &nbsp; if struct1.Type().Kind() != reflect.Slice {&nbsp; &nbsp; &nbsp; &nbsp; return ""&nbsp; &nbsp; }&nbsp; &nbsp; ans := make([]string, 0)&nbsp; &nbsp; for i := 0; i < struct1.Len(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; slice1 := struct1.Index(i)&nbsp; &nbsp; &nbsp; &nbsp; if slice1.Type().Kind() != reflect.Struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; for j := 0; j < slice1.NumField(); j++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; struct2 := slice1.Field(j)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if struct2.Type().Kind() != reflect.Struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name := struct2.FieldByName("Name")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if name.Kind() != reflect.String {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ans = append(ans, name.String())&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return strings.Join(ans[:], " / ")}
随时随地看视频慕课网APP

相关分类

Go
我要回答