Итерация по структуре со встроенной структурой - PullRequest
0 голосов
/ 05 марта 2020

У меня есть несколько структур, которые получают данные. Все структуры должны включать в себя одни и те же данные, которые были встроены в структуру HeaderData. Данные не заполняются одновременно, и мне нужна функция, чтобы проверить, все ли поля получили значение (не пустая строка).

Я попытался решить эту проблему с помощью отражения. Проблема в том, что отражение будет считать HeaderData одним полем. Это означает, что это всегда будет непустая строка, хотя она может содержать пустые поля. Поэтому я считаю, что мне нужен способ проверить эту структуру отдельно.

Я пытался получить к ней доступ с помощью anyStruct.HeaderData, но это не работает, поскольку «{} - это интерфейс без методов».

Есть ли другой способ доступа к HeaderData, чтобы это работало?

Или я могу каким-то образом указать в dataReady, что у входа должно быть поле 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
}

Детская площадка

1 Ответ

0 голосов
/ 05 марта 2020

Возможно, попробуйте немного интерфейса, чтобы сделать то же самое, и я думаю, что это было бы намного более читабельным.

https://play.golang.org/p/H4lh91RMd6C

package main

import (
     "fmt"
)

 type(

     FieldCheck interface {
         Check() (b bool)
     }

     HeaderData struct {
         Param1  string
         Param2  string
     }

    Data1 struct {
         HeaderData
         Param3  string
         Param4  string
     }

     Data2 struct {
         HeaderData
         Param3  string
         Param5  string
     }
  )

func(h *HeaderData) Check() (b bool) {
     if h.Param1 == "" || h.Param2 == "" {
         return false
     }
     return true
}

func(d *Data1) Check() (b bool) {
     if (d.Param3 == "" || d.Param4 == "" || ! d.HeaderData.Check()) {
         return false
     }
     return true
}

func(d *Data2) Check() (b bool) {
     if (d.Param3 == "" || d.Param5 == "" || ! d.HeaderData.Check()) {
         return false
     }
     return true
 }


func main() {

    d := []FieldCheck{
         &Data1{HeaderData: HeaderData{Param1: "ABC", Param2: "DEF"}, Param3: 
"GHI", Param4: "JKL"},
        &Data2{HeaderData: HeaderData{Param1: "ABC", Param2: "DEF"}},
        &Data2{HeaderData: HeaderData{Param1: "ABC"}, Param3: "GHI", Param5: 
"JKL"},
        &Data2{Param3: "GHI", Param5: "JKL"},
    }

    for _, num := range d {
        fmt.Println(num.Check())
    }
}
...