Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Iterating slice struct within struct using reflection

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.
            */
        }

    }
}

>Solution :

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)
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading