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

Yam*_*mel 3 arrays struct go slice

我是 Golang 的新手,在参观了A Tour of 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);
Run Code Online (Sandbox Code Playgroud)

我试过的

我尝试在 Golang 中做同样的事情,我希望它看起来像这样:

A{B{}, C{}, D{}}
Run Code Online (Sandbox Code Playgroud)

由于我使用失败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: 
    // http://stackoverflow.com/questions/18926303/iterate-through-a-struct-in-go
    v := reflect.ValueOf(A{})

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

但似乎我实际上是在做嵌入而不是存储它们,请问有什么建议吗?

Sev*_*eva 6

我认为 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)
     }
 }
Run Code Online (Sandbox Code Playgroud)

这可能与您在 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)
    }
}
Run Code Online (Sandbox Code Playgroud)