为什么接口不能用指针接收器实现

Why can't the interface be implemented with pointer receivers

我很困惑为什么编译失败:

impossible type assertion: Faz does not implement Foo (Bar method has pointer receiver)

如果我将 Faz.Bar 的接收器设为 Faz 值而不是 Faz 指针,那么它可以正常编译,但我认为拥有指针接收器总是更好,这样值就不会被复制?

package main

import (
    "log"
)

func main() {
    foo := New().(Faz)
    log.Println(foo)
}

type Foo interface {
    Bar() string
}

func New() Foo {
    return &Faz{}
}

type Faz struct {
}

func (f *Faz) Bar() string {
    return `Bar`
}

因为它是 *Faz 而不是 Faz

func main() {
    foo := New().(*Faz)
    log.Println(foo)
}

我认为这个问题的答案需要对语法进行更回顾性的处理,以及如何通过软件工程来实现它。 (请原谅过度简化)


首先快速回顾什么是 types
它们只是顶部带有编译器逻辑的内存块。 arraystring 的不同之处在于编译器允许我们对这些内存块执行的操作。 (深入思考,您可能会开始意识到 strongly typeddynamically typed 语言之间的真正区别。)

接下来你需要意识到指针是它们自己的类型。
*variable 是与 variable 不同的内存块(又名类型)。只是编译器始终假定 *variable 的内容始终是声明右侧类型的内存块的地址以及它强加的其他 restriction/features。

然后让我们回顾一下接口是什么。
伪科学定义:对任何第一个 class 公民具有特定类型的一组要求。 转化为软件工程 - 任何具有相同内存结构(回想 structure packing)的内存块(类型)与其相关联,如合同中所述(interface) 可以像合同提到的 类型名称 一样传递。


现在你可能会开始意识到,当你说

func (f *Faz) Bar() stringf 的存储函数块,其中 f 的类型是 指向 Faz[= 的指针58=]

所在地区

func (f Faz) Bar() stringf的内存块,其中f的类型是Faz

所以当你说 *Faz 类型的变量满足契约时,你怎么能假设 Faz 类型的变量符合代码中的接口类型呢?选择谁满足你的契约,只有那个类型才能承担你代码中的接口类型。