猿问

结构嵌入实现的接口

我对以下程序的实验感到困惑,这些程序分别与使用结构嵌入实现接口、命名类型和指针接收器有关:


package main


import "fmt"


type MyInt interface {

    mytest()

}


type Base struct {

}


func (b *Base) mytest() {

    fmt.Println("From base")

}


type Derived struct {

    Base

}


type Derived2 struct {

    *Base

}


func main() {

    // Only this one has problem

    // However, if we change mytest's receiver from *Base to Base, all the four assignments are OK

    var _ MyInt = Derived{}


    // OK

    var _ MyInt = &Derived{}

    var _ MyInt = Derived2{}

    var _ MyInt = &Derived2{}

}

请参阅代码中的注释以了解我的困惑。有什么主要的方法来解释它们吗?


倚天杖
浏览 157回答 2
2回答

慕码人8056858

来自Go 语言规范:给定一个结构类型 S 和一个名为 T 的类型,提升的方法包含在结构的方法集中,如下所示:如果 S 包含匿名字段 T,则 S 和 *S 的方法集都包含带有接收者 T 的提升方法。*S 的方法集还包括带有接收者 *T 的提升方法。如果 S 包含匿名字段 *T,则 S 和 *S 的方法集都包含带有接收者 T 或 *T 的提升方法。在您的代码中不起作用的情况:var _ MyInt = Derived{}这里的方法集Derived(其中包含一个匿名字段Base)包括Base规则 1mytest的方法。由于是一个方法*Base而不是Base,它被提升为一个方法*Derived(根据第二条规则),但不是Derived。为什么会这样?嗯,它类似于结构方法集的规则:方法T也是 的方法T*,但反之则不然。这是因为指针接收器的方法可以期望能够改变其接收器,但非指针接收器的方法不能。

慕容3067478

根据您的代码函数 mytest 可以在指向 Base 的接收器上调用。Struct Derived 继承/嵌入 Base 和 Derived2 继承/嵌入 *Base 即指向基址的指针。为了var _MyInt = &Derived2{}:这里创建了 Derived2 的指针,并且由于 Derived2 继承自 *Base,因此在 _MyInt 上调用 mytest 将起作用var _MyInt = Derived2{}:创建了 Derived2 的实例,并且由于 Derived2 继承自 *Base,因此在 _MyInt 上调用 mytest 将起作用var _MyInt = &Derived{}:这里创建了 Derived 的指针,并且由于 Derived 从 Base 继承,因此在 _MyInt 上调用 mytest 将起作用var _MyInt = Derived{}:创建了 Derived 的实例,并且由于 Derived 从 Base 继承,因此在 _MyInt 上调用 mytest 将不起作用,因此需要指向 Base 的指针。您正确地指出,将接收器从 *Base 更改为 Base 将起作用,因为 Go 将能够从指针中识别 Object 并且能够调用 mytest.根据 golang 规范,一个类型可能有一个与之关联的方法集。接口类型的方法集就是它的接口。任何其他类型 T 的方法集由所有以接收者类型 T 声明的方法组成。对应指针类型 *T 的方法集是所有以接收者 *T 或 T 声明的方法的集合(即它还包含该方法T 组)。希望这可以帮助
随时随地看视频慕课网APP

相关分类

Go
我要回答