英文:
Iterating slice struct within struct using reflection
问题
我正在尝试实现以下内容:
使用案例:
- 我有三个结构体,我需要将其中的两个与另一个进行比较(在示例中描述为:需要将a和b与full进行比较)。
- 使用反射循环遍历每个字段,获取字段的名称。并比较a和full、b和full之间的差异,将结果存储在一个共享结构体中。
- 如果字段等于"World",我们知道它是一个切片结构体:
- 我需要获取Foo结构体中Bar切片的第一个索引。
- 即使变量是一个切片,我知道在这个案例中它的长度始终为1。
- 获取后,我需要像前一个if语句中所发生的那样循环遍历这些字段。
示例代码:
type Foo struct {
Hello string
World []Bar
}
type Bar struct {
Fish string
}
type Result struct {
Field string
Correct_A bool
Distance_A int
Correct_B bool
Distance_B int
Result []Result
}
func compare_structs() {
var full, a, b Foo
// 填充所有变量...
result := []Result{}
rfx_f := reflect.ValueOf(full)
rfx_a := reflect.ValueOf(a)
rfx_b := reflect.ValueOf(b)
type_result := rfx_f.Type()
for i := 0; i < rfx_f.NumField(); i++ {
tmp_res := Result{
Field: type_result.Field(i).Name,
}
if reflect.TypeOf(full).Field(i).Type.Kind() != reflect.Slice {
value := rfx_f.Field(i).Interface()
value_a := rfx_a.FieldByName(tmp_res.Field).Interface()
value_b := rfx_b.FieldByName(tmp_res.Field).Interface()
// 比较该字段的值的函数
tmp_res.compare(value, value_a, value_b)
tmp_res.lev(value, value_a, value_b)
result = append(result, tmp_res)
} else if tmp_res.Field == "World" {
/*
我需要获取Foo结构体中Bar切片的第一个索引。
即使变量是一个切片,我知道在这个案例中它的长度始终为1。
获取后,我需要像前一个if语句中所发生的那样循环遍历这些字段。
*/
}
}
}
英文:
I'm trying to achieve the following:
Use-case:
- I have three structures, I need to compare 2 of those against one. (in the example described as: a & b need to be compared against full)
- Reflection is used to loop over every field, retrieve the name of the field. And comparing the difference between a & full, b & full, storing the results in a shared structure.
- If the field equals World, we know it's a slice struct:
I need to retrieve the first index of the Bar slice within the Foo structure.
Even though the variable is a slice, I know it will always have a length of 1 in this use-case.
When retrieved I need to loop over those fields, like what is happening in the previous if statement.
Example code:
type Foo struct {
Hello string
World []Bar
}
type Bar struct {
Fish string
}
type Result struct {
Field string
Correct_A bool
Distance_A int
Correct_B bool
Distance_B int
Result []Result
}
func compare_structs() {
var full, a, b Foo
// filling in all variables...
result := []Result{}
rfx_f := reflect.ValueOf(full)
rfx_a := reflect.ValueOf(a)
rfx_b := reflect.ValueOf(b)
type_result := rfx_f.Type()
for i := 0; i < rfx_f.NumField(); i++ {
tmp_res := Result{
Field: type_result.Field(i).Name,
}
if reflect.TypeOf(full).Field(i).Type.Kind() != reflect.Slice {
value := rfx_f.Field(i).Interface()
value_a := rfx_a.FieldByName(tmp_res.Field).Interface()
value_b := rfx_b.FieldByName(tmp_res.Field).Interface()
// functions to compare the values of this field
tmp_res.compare(value, value_a, value_b)
tmp_res.lev(value, value_a, value_b)
result = append(result, tmp_res)
} else if tmp_res.Field == "World" {
/*
I need to retrieve the first index of the Bar slice within the Foo structure.
Even though the variable is a slice, I know it will always have a length of 1 in this use-case.
When retrieved I need to loop over those fields, like what is happening in the previous if statement.
*/
}
}
}
答案1
得分: 1
你首先需要获取字段:
wordField := rfx_f.Field(i)
你知道它是一个切片,所以你可以通过索引来获取第一个元素:
item := wordField.Index(0)
如果索引超出范围,这将引发 panic。
然后你可以迭代字段:
for fieldIx := 0; fieldIx < item.NumField(); fieldIx++ {
field := item.Field(fieldIx)
}
英文:
You first need to get the field:
wordField:=rfx_f.Field(i)
which you know to be a slice, so you index it to get the first element
item:=wordField.Index(0)
This will panic if index is out of range.
Then you can iterate the fields:
for fieldIx:=0;fieldIx<item.NumField();fieldIx++ {
field:=item.Field(fieldIx)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论