带有接收器的函数在 go 中迭代结构的某个字段
function with receiver that iterates through some field of struct in 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
字段编写几乎相同的函数。我的问题是,如何使这个函数更通用,接受一个字段并对其进行迭代。有什么想法吗?
您可以使用 relfect. There is a well written tutorial 来做到这一点,您可以看看。
根据你给的结构,我写了一个demo。主要思想是
找到按名称归档的结构,然后迭代切片,在结构中找到名称。
您现在可以使用 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[:], " / ")
}
我是一个 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
字段编写几乎相同的函数。我的问题是,如何使这个函数更通用,接受一个字段并对其进行迭代。有什么想法吗?
您可以使用 relfect. There is a well written tutorial 来做到这一点,您可以看看。
根据你给的结构,我写了一个demo。主要思想是 找到按名称归档的结构,然后迭代切片,在结构中找到名称。
您现在可以使用 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[:], " / ")
}