GO接口中的多态性

I'm trying to reach this way of polymorphism in GO

type Discoverer interface {
    Discover() string
}

type A struct {
}

func (obj A) GetTest() string {
    return "im in A"
}

type B struct {
    A
}

func (obj B) GetTest() string {
    return "im in B"
}

func (obj A) Discover() string {
    return obj.GetTest()
}

func main() {
    a := A{}
    b := B{}

    fmt.Println(a.Discover())
    fmt.Println(b.Discover())
}

Now I'm getting in output

im in A
im in A

So, my question is: It is possible to see in output

im in A
im in B

Without "override" Discover of B?

func (obj B) Discover() string {
    return obj.GetTest()
}

Why? I've alot of small methods in struct (as classes) and Discover pretty the same for all structs, so I want to avoid copy&paste Discover in each struct(class)

go playground https://play.golang.org/p/nYc2hc3UbG

Thanks in advance!

No. You're embedding A in B. B has no definition for Discover, therefor the version on A is always invoked. That method has a receiver of type A and A has no awareness of B or the fact that it's embedded in B. Therefor A can only call it's own version of GetTest().

The only reason B satisfies the discover interface is because it has A embedded. It implements it indirectly. If you want the functionality on B, you have to define it on B. This isn't polymorphism at all, it's composition. B isn't an A, B has an A. If you want polymorphism, you use interfaces and implement them. B is a discoverable, but only because it has an A.

I would assume this is just for the example but you actually have no reason at all to even have this Discovery method. Your interface should just require GetTest instead. Don't confuse embedding with inheritance. There is no inheritance in Go. If you want polymorphic behavior you achieve it by implementing interfaces and you can't cut corners like this because the relationship between an embedded type and the embeddor is not one of inheritance, there is no base class or "overrides".

To add to @evanmcdonnal's point, embedding is neither inheritance nor polymorphism. Inheritance just happens to be a convenience such that you may get the implementation of an interface for free but in Go, its explicit. Embedding may seem like inheritance but is not, as @evanmcdonnal has pointed out.

Rather, you should separate the concepts polymorphism from inheritance and embedding and inheritance. The comparisons do not carry over from most object oriented languages. As an example, below would be an implementation of polymorphism. Notice that Discover takes an interface and A and B implements the interface, making the function itself polymorphic.

package main

import "fmt"

type A struct{}
type B struct{}

type Test interface{
    GetTest() string
}

func (a *A) GetTest() string {
    return "i am in A"
}

func (b *B) GetTest() string {
    return "i am in B"
}

func Discover(t Test) string {
    return t.GetTest()
}

func main() {
    a := &A{}
    b := &B{}

    fmt.Println(Discover(a))
    fmt.Println(Discover(b))
}