Go 使用嵌入的结构遍历结构
我有几个正在接收数据的结构。所有结构应包括一些相同的数据,这些数据已嵌入Go 使用嵌入的结构遍历结构,go,struct,reflection,embedding,go-reflect,Go,Struct,Reflection,Embedding,Go Reflect,我有几个正在接收数据的结构。所有结构应包括一些相同的数据,这些数据已嵌入HeaderData结构。数据不是同时填充的,我需要一个函数来检查所有字段是否都收到了值(不是空字符串) 我试着用反思来解决这个问题。问题是反射会把标题数据< /代码>视为一个字段。这意味着它将始终是非空字符串,尽管它可能包含空字段。所以我认为我需要一种方法来单独检查这个结构 我试图用anyStruct.HeaderData访问它,但这不起作用,因为“{}是没有方法的接口” 是否有其他方法访问标题数据,以使其正常工作 或者我
HeaderData
结构。数据不是同时填充的,我需要一个函数来检查所有字段是否都收到了值(不是空字符串)
我试着用反思来解决这个问题。问题是反射会把<代码>标题数据< /代码>视为一个字段。这意味着它将始终是非空字符串,尽管它可能包含空字段。所以我认为我需要一种方法来单独检查这个结构
我试图用anyStruct.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
}
主程序包
进口(
“fmt”
“反映”
)
类型HeaderData结构{
参数1字符串
参数2字符串
}
类型Data1结构{
人头数据
参数3字符串
参数4字符串
}
类型Data2 struct{
人头数据
参数3字符串
参数5字符串
}
func dataReady(anyStruct接口{})bool{
v:=反射.ValueOf(anyStruct)
对于i:=0;i
也许可以尝试一个小界面来做同样的事情,我认为这会更具可读性
为什么你需要对此进行反思?具有检查
HeaderData
字段的方法/功能,以及那些DataN
结构的方法/功能;后者上的方法/函数将调用该方法/函数,该方法/函数将检查其中HeaderData字段的字段(事实上它是嵌入的,并不排除通过其类型的名称访问它)。您可能认为这是“太多的代码”,但作为交换,它更容易理解(而且速度更快)。@kostix这是一个选项,也许我应该这样做。但正如您所提到的,这将是更多的代码,我需要每个结构一个函数。此外,如果结构中有更改,我将不得不更新函数。所以我想如果我有一个更通用的方法来检查这个,那就太好了。谢谢你的建议!是的,这似乎是一条路要走。缺点是,如果将字段添加到结构中,则还必须使用新字段更新Check方法。但希望结构会非常稳定:-)为了简单起见,我这样做了,您可以在结构的每个级别循环字段,因此不必这样做。您还可以使用一个类型断言,使其更具动态性。谢谢:-)
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())
}
}