Interface 嵌入式结构的覆盖行为

Interface 嵌入式结构的覆盖行为,interface,go,embedding,Interface,Go,Embedding,我有一个XY类型,它有各种字段和方法(几十个) 现在我想定义第二种类型,它嵌入XY,保留所有字段和方法。但我确实想修改一些函数 type AB struct { XY } func (ab *AB) Do2() { ... } 到目前为止还不错。现在我想把AB传递给一个取XY的函数 func SomeFunc(xy *XY) { ... } 这是我绊倒的地方,没有多态性 我可以将*AB.XY传递给函数,但这将不再使用AB的Do2函数。我可以为它创建一个接口,这可能是预期的方式,但是

我有一个XY类型,它有各种字段和方法(几十个)

现在我想定义第二种类型,它嵌入XY,保留所有字段和方法。但我确实想修改一些函数

type AB struct {
    XY
}

func (ab *AB) Do2() { ... }
到目前为止还不错。现在我想把AB传递给一个取XY的函数

func SomeFunc(xy *XY) { ... }
这是我绊倒的地方,没有多态性

我可以将
*AB.XY
传递给函数,但这将不再使用AB的Do2函数。我可以为它创建一个接口,这可能是预期的方式,但是如果SomeFunc需要接近XY的所有函数,比如几乎所有字段的getter,我基本上需要创建XY的一个副本,作为一个接口(可能的用例:我在服务器上,必须以特定的方式向客户端发送值)。我不想只把它变成一个接口,因为我必须重新定义使用该接口的所有类型中的所有字段和函数


我可以想到这个问题的解决方案,例如,使Do2成为一个闭包,它是根据“主机”类型设置的,或者XY中的枚举字段,并根据该“类型”变量更改Do2的行为,或者在SomeFunc中使用反射和
接口{}
,但我想知道Go中的“正确”方式是什么。即使您有很多功能,如何以最有效的方式实现这一点?

在Go中实现这一点的正确方法是使用接口。创建
Do1
Do2
等的接口,并使SomeFunc与接口类型一起工作。

如@Ainar-G所说,使用接口是此类行为的正确方式,例如:

type Doer interface {
    Do1()
    Do2()
}

func (*S1) Do1() {
    println("S1.Do1")
}
func (*S1) Do2() {
    println("S1.Do2")
}

type S2 struct{ S1 }

func (*S2) Do1() {
    println("S2.Do1")
}

func DoIt(d Doer) {
    d.Do1()
    d.Do2()
    // you can use a type switch for specific corner cases, or implement a MarshalJson (or similar) interface for you types)
    switch v := d.(type) {
        case *S1:
            println("Special case for S1", v)
        case *S2:
            println("Special case for S2", v)

    }
}

type Doer interface {
    Do1()
    Do2()
}

func (*S1) Do1() {
    println("S1.Do1")
}
func (*S1) Do2() {
    println("S1.Do2")
}

type S2 struct{ S1 }

func (*S2) Do1() {
    println("S2.Do1")
}

func DoIt(d Doer) {
    d.Do1()
    d.Do2()
    // you can use a type switch for specific corner cases, or implement a MarshalJson (or similar) interface for you types)
    switch v := d.(type) {
        case *S1:
            println("Special case for S1", v)
        case *S2:
            println("Special case for S2", v)

    }
}