为了账号安全,请及时绑定邮箱和手机立即绑定

结构嵌入实现的接口

结构嵌入实现的接口

Go
倚天杖 2022-01-10 17:46:24
我对以下程序的实验感到困惑,这些程序分别与使用结构嵌入实现接口、命名类型和指针接收器有关:package mainimport "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{}}请参阅代码中的注释以了解我的困惑。有什么主要的方法来解释它们吗?
查看完整描述

2 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

来自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*,但反之则不然。这是因为指针接收器的方法可以期望能够改变其接收器,但非指针接收器的方法不能。


查看完整回答
反对 回复 2022-01-10
?
慕容3067478

TA贡献1773条经验 获得超3个赞

根据您的代码函数 mytest 可以在指向 Base 的接收器上调用。

Struct Derived 继承/嵌入 Base 和 Derived2 继承/嵌入 *Base 即指向基址的指针。

为了

  1. var _MyInt = &Derived2{}:这里创建了 Derived2 的指针,并且由于 Derived2 继承自 *Base,因此在 _MyInt 上调用 mytest 将起作用

  2. var _MyInt = Derived2{}:创建了 Derived2 的实例,并且由于 Derived2 继承自 *Base,因此在 _MyInt 上调用 mytest 将起作用

  3. var _MyInt = &Derived{}:这里创建了 Derived 的指针,并且由于 Derived 从 Base 继承,因此在 _MyInt 上调用 mytest 将起作用

  4. var _MyInt = Derived{}:创建了 Derived 的实例,并且由于 Derived 从 Base 继承,因此在 _MyInt 上调用 mytest 将不起作用,因此需要指向 Base 的指针。

您正确地指出,将接收器从 *Base 更改为 Base 将起作用,因为 Go 将能够从指针中识别 Object 并且能够调用 mytest.

根据 golang 规范,一个类型可能有一个与之关联的方法集。接口类型的方法集就是它的接口。任何其他类型 T 的方法集由所有以接收者类型 T 声明的方法组成。对应指针类型 *T 的方法集是所有以接收者 *T 或 T 声明的方法的集合(即它还包含该方法T 组)。

希望这可以帮助


查看完整回答
反对 回复 2022-01-10
  • 2 回答
  • 0 关注
  • 156 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信