如何在Go中将不同的结构体存储在一个切片或结构体中(非嵌入式)

3

我是新手Go语言,读完了 Go之旅 后,我想尝试自己的东西。

我的需求

我想把不同类型的结构体放进一个单一的切片(或结构体)中,

这样我就可以使用 for 循环将每个结构体传递给函数

例如

在PHP中,我可以将我的类存储在数组中,并像这样将它们中的每一个传递给 foobar()

$classes = [$A, $B, $C, $D];  // $A, $B, $C, $D are classes (called `struct` in Golang).

foreach ($classes as $class)
    foobar($class);

我的尝试

我尝试使用Golang实现相同的功能,希望代码如下所示:

A{B{}, C{}, D{}}

由于我在使用 slice 时失败了,所以我决定使用 struct 来保存我的 structs

type A struct {
    B
    C
    D
}

type B struct {
    Date string
}

type C struct {
    Date string
}

type D struct {
    Date string
}

func main() {   
    // Using reflect to loop the A struct: 
    // https://dev59.com/LWMk5IYBdhLWcg3w2BTJ
    v := reflect.ValueOf(A{})

    for i := 0; i < v.NumField(); i++ {
        foobar(v.Field(i).Interface()) // Passing each struct to the `foobar()` function
    }
}

但是看起来我实际上是在嵌入而不是存储它们,有什么建议吗?
1个回答

8

我认为interface{}是你想要的。例如像这样:

type A struct {
    data string
}

type B struct {
     data int
}

func printData(s interface{}) {
     switch s.(type) {
         case A:
             fmt.Printf("A: %s\n", s.(A).data)
         case B:
             fmt.Printf("B: %d\n", s.(B).data)
     }
 }

 func main() {
     classes := []interface{}{A{data: "first"}, B{data: 2}, A{data: "third"}}
     for _, c := range classes {
         printData(c)
     }
 }

这可能是在Go语言中最接近“鸭子类型”的方式。

但是,如果你的结构体非常相似,最好定义一个公共接口,然后为每个结构体实现该接口。以下是使用接口的示例:

type DataGetter interface {
    getDate() string
}

type A struct {
    data string
}

func (a A) getDate() string {
    return a.data
}

type B struct {
    data int
}

func (b B) getDate() string {
    return fmt.Sprintf("%d", b.data)
}

func printData(s DataGetter) {
    fmt.Printf("%s\n", s.getDate())
}

func main() {

    classes := []DataGetter{A{data: "first"}, B{data: 2}, A{data: "third"}}
    for _, c := range classes {
        printData(c)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接