如何创建嵌入另一个结构的切片?

I have the following:

https://play.golang.org/p/q2NUMzbw6-

package main

import "fmt"

type A struct {
    Name string
    Address string
}

type B struct {
    A
}

type C struct {
    A
}

type D struct {
    A
}

//....more structs that embed A

type myinterface interface {
    SetName(string)
    SetAddress(string)
}

func run() *A {
    // iterate over a slice of structs that embed A.... how????
    for _, s := range []*A{
        &B{}, &C{}, &D{},
    } {
        s.SetName("Bob")
        s.SetAddress("Maine")
        // do some other stuff that gets very verbose w/out a slice...
        return s.A
    }
}

func main() {
    a := run()
    fmt.Println(a)
}

I need to iterate through all of the structs that embed A but am having a hard time doing so. The above doesn't work "cannot use B literal (type *B) as type *A in array or slice literal". What is the best way?

Declare methods on A that satisfy the interface:

func (a *A) SetName(s string) {
    a.Name = s
}

func (a *A) SetAddress(s string) {
    a.Address = s
}

Use a slice of that interface in the range:

for _, s := range []myinterface{&B{}, &C{}, &D{}} {
   ...
}

playground example

It's a common misconception to believe that type embedding in Go is analogous to inheritance in other languages.

In fact, type embedding is analogous to composition in other languages.

In your example, types B and A are not related in any way, other than the fact that by embedding A in B you are able to invoke A's methods directly over B.

You can read more about it here:

https://golang.org/doc/effective_go.html#embedding

In order to mimic "inheritance" you need to work with interfaces.

You should use myinterface as the array type in order to treat all of those structs in a generic way.

The compiler tells you the problem: you can't use type B as type A (and you also can't use type A as type B); the types simply aren't the same. You should be ranging over a slice of myinterface.

However, that's not the entire solution because s.A won't work since s now has the type myinterface (with underlying types *B, *C, and *D), and no method named A belongs to myinterface.

You can fix this by adding another method aSelf() *A to myinterface and implementing aSelf with a receiver type *A that simply returns the receiver. This way, B, C, etc. can all use this method. Note that you can't simply name the method A in this instance because B.A (and C.A etc.) will be ambiguous: does the .A refer to the embedded A field itself or to the A method of the embedded A field? You could name it a if the method will not be exported, else you need to use a different name such as the previously mentioned aSelf.

Below are the relevant bits to alter/add:

func (a *A) aSelf() *A {
    return a
}

type myinterface interface {
    SetName(string)
    SetAddress(string)
    aSelf() *A
}

func run() *A {
    // iterate over a slice of myinterface
    for _, s := range []myinterface{
        &B{}, &C{}, &D{},
    } {
        s.SetName("Bob")
        s.SetAddress("Maine")
        // do some other stuff that gets very verbose w/out a slice...
        return s.aSelf()
    }
    return nil
}

Playground link