jeudi 5 mars 2020

Iterate through a struct with an embedded struct in Go

I have several structs that are receiving data. All share the same that is included in the HeaderData struct. The data is not filled at the same time and I need a function to check if all the fields have received a value (is not an empty string).

I tried to solve this with reflect. The problem is that reflect will consider the HeaderData to be one field. This means that it will always be a non-empty string, although it may include empty fields. So I believe that I need a way to check that struct separately.

I tried to access it with anyStruct.HeaderData, but that is not working since “{} is interface with no methods”.

Is there any other way to access the HeaderData so that this works?

Or can I in some way specify in the dataReady that the input must have the field HeaderData?

package main

import (
    "fmt"
    "reflect"
)

type HeaderData struct {
    Param1  string
    Param2  string
}

type Data1 struct {
    HeaderData 
    Param3  string
    Param4  string
}

type Data2 struct {
    HeaderData 
    Param3  string
    Param5  string
}

func dataReady(anyStruct interface{}) bool {
    v := reflect.ValueOf(anyStruct)
    for i := 0; i < v.NumField(); i++ {
        // fmt.Println(v.Field(i).Interface())
        if v.Field(i).Interface() == "" {
            return false
        }
    }


    // v1 := reflect.ValueOf(anyStruct.HeaderData)
    // Not working:
    // anyStruct.HeaderData undefined (type interface {} is interface with no methods)

    return true
}

func main() {
    d1 := Data1{HeaderData: HeaderData{Param1: "ABC", Param2: "DEF"}, Param3: "GHI", Param4: "JKL"}
    d2 := Data2{HeaderData: HeaderData{Param1: "ABC", Param2: "DEF"}}
    d3 := Data2{HeaderData: HeaderData{Param1: "ABC"}, Param3: "GHI", Param5: "JKL"}
    d4 := Data2{Param3: "GHI", Param5: "JKL"}
    fmt.Println("d1Ready: ", dataReady(d1))     //Returns true, which is correct
    fmt.Println("d2Ready: ", dataReady(d2))     //Returns false, which is correct
    fmt.Println("d3Ready: ", dataReady(d3))     //Returns true but should return false
    fmt.Println("d4Ready: ", dataReady(d4))     //Returns true but should return false
}

Playground





Aucun commentaire:

Enregistrer un commentaire