英文:
Golang count number of fields in a struct of structs
问题
给定一个由两个嵌套结构体StructA
和StructB
组成的结构体CompleteStruct
,其中StructB
中包含ImbStructC
。
type StructA struct {
AA int
AB int
AC int
}
type ImbStructC struct {
BCC int
}
type StructB struct {
BA int
BB int
ImbStructC
}
type CompleteStruct struct {
StructA
StructB
}
如何提取内部结构体中的字段总数?
reflect.TypeOf(CompleteStruct{}).NumField())
返回2,我认为是因为CompleteStruct
由2个嵌套结构体组成。
我可以使用什么代码来显示CompleteStruct
有6个字段?
英文:
Given a struct CompleteStruct
that is composed of two embedded structs StructA
and StructB
where StructB
has ImbStructC
in it.
type StructA struct {
AA int
AB int
AC int
}
type ImbStructC struct {
BCC int
}
type StructB struct {
BA int
BB int
ImbStructC
}
type CompleteStruct struct {
StructA
StructB
}
How do you extract the total number of fields in the inner struct?
reflect.TypeOf(CompleteStruct{}).NumField())
returns 2, I assume because CompleteStruct
is made up of 2 embedded structs.
What code can I use to show that CompleteStruct
has 6 fields?
答案1
得分: 1
递归是解决这个问题的方法,因为嵌套的结构字段可能本身嵌套了另一个结构。
此外,我们应该小心不要将嵌套的结构计算为字段 - 在reflect
包中,它们被列为“匿名”字段:
func countFields(v any) int {
return rvCountFields(reflect.ValueOf(v))
}
func rvCountFields(rv reflect.Value) (count int) {
if rv.Kind() != reflect.Struct {
return
}
fs := rv.NumField()
count += fs
for i := 0; i < fs; i++ {
f := rv.Field(i)
if rv.Type().Field(i).Anonymous {
count-- // 不要将嵌套的结构(列为匿名字段)计算为字段
}
// 递归每个字段,看看该字段是否也是一个嵌套的结构
count += rvCountFields(f)
}
return
}
输出:
main.CompleteStruct : count = 5
main.StructA : count = 3
main.StructB : count = 2
main.StructC : count = 6
main.StructD : count = 12
main.Empty : count = 0
int : count = 0
英文:
Recursion is needed to solve this, as an embedded struct field may itself embed another struct.
Also, one should be careful not to count embedded structs as field - these are listed as "anonymous" fields in the reflect
package:
func countFields(v any) int {
return rvCountFields(reflect.ValueOf(v))
}
func rvCountFields(rv reflect.Value) (count int) {
if rv.Kind() != reflect.Struct {
return
}
fs := rv.NumField()
count += fs
for i := 0; i < fs; i++ {
f := rv.Field(i)
if rv.Type().Field(i).Anonymous {
count-- // don't count embedded structs (listed as anonymous fields) as a field
}
// recurse each field to see if that field is also an embedded struct
count += rvCountFields(f)
}
return
}
https://go.dev/play/p/IjOllo86_xk
Output:
main.CompleteStruct : count = 5
main.StructA : count = 3
main.StructB : count = 2
main.StructC : count = 6
main.StructD : count = 12
main.Empty : count = 0
int : count = 0
答案2
得分: 1
reflect.VisibleFields
包列出了结构体中的所有字段,然后只需计算那些非匿名字段的数量。
func CountNumberOfFieldsInAStruct(obj interface{}) int {
fields := reflect.VisibleFields(reflect.TypeOf(obj))
count := 0
for _, field := range fields {
if !field.Anonymous {
count += 1
}
}
return count
}
正如@colm.anseo提到的,“这只会公开“可见”的即大写的结构体字段名。它不会包括小写(未公开)的结构体字段。所以如果你只想要公开的字段,那么这个方法可以工作”。
在这里进行了测试
https://go.dev/play/p/Ea-y8YAkcqZ
英文:
The reflect.VisibleFields
package lists all the fields in the struct, from there is "just" a matter of counting those fields that are not Anonymous.
func CountNumberOfFieldsInAStruct(obj interface{}) int {
fields := reflect.VisibleFields(reflect.TypeOf(obj))
count := 0
for _, field := range fields {
if !field.Anonymous {
count += 1
}
}
return count
}
As @colm.anseo mentions "this will only expose the "visible" exported i.e. capitalized struct field names. It will not include lowercase (unexported) struct fields. So if you only want exported fields, then this would work"
Tested here
答案3
得分: 0
基本上,你需要从父结构体中获取字段的数量,然后循环遍历子结构体并获取每个子结构体的字段数量,然后将它们相加。
innerFields := 0
numOfFields := reflect.TypeOf(CompleteStruct{}).NumField()
for i := 0; i < numOfFields; i++ {
innerFields += reflect.TypeOf(CompleteStruct{}).Field(i).Type.NumField()
}
这段代码已经经过测试并且可以正常工作。
英文:
Basically you need to get the number of fields from the parent struct and then loop through the children and get the number of fields for each child and then add them up
innerFields := 0
numOfFields := reflect.TypeOf(CompleteStruct{}).NumField()
for i := 0; i < numOfFields; i++ {
innerFields += reflect.TypeOf(CompleteStruct{}).Field(i).Type.NumField()
}
This code is tested and works
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论