为什么接口不能用指针接收器实现
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
?
它们只是顶部带有编译器逻辑的内存块。 array
与 string
的不同之处在于编译器允许我们对这些内存块执行的操作。 (深入思考,您可能会开始意识到 strongly typed
和 dynamically typed
语言之间的真正区别。)
接下来你需要意识到指针是它们自己的类型。
*variable
是与 variable
不同的内存块(又名类型)。只是编译器始终假定 *variable
的内容始终是声明右侧类型的内存块的地址以及它强加的其他 restriction/features。
然后让我们回顾一下接口是什么。
伪科学定义:对任何第一个 class 公民具有特定类型的一组要求。
转化为软件工程 - 任何具有相同内存结构(回想 structure packing)的内存块(类型)与其相关联,如合同中所述(interface
) 可以像合同提到的 类型名称 一样传递。
现在你可能会开始意识到,当你说
func (f *Faz) Bar() string
是 f
的存储函数块,其中 f
的类型是 指向 Faz
[= 的指针58=]
所在地区
func (f Faz) Bar() string
是f
的内存块,其中f
的类型是Faz
所以当你说 *Faz
类型的变量满足契约时,你怎么能假设 Faz
类型的变量符合代码中的接口类型呢?选择谁满足你的契约,只有那个类型才能承担你代码中的接口类型。
我很困惑为什么编译失败:
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
?
它们只是顶部带有编译器逻辑的内存块。 array
与 string
的不同之处在于编译器允许我们对这些内存块执行的操作。 (深入思考,您可能会开始意识到 strongly typed
和 dynamically typed
语言之间的真正区别。)
接下来你需要意识到指针是它们自己的类型。 *variable
是与 variable
不同的内存块(又名类型)。只是编译器始终假定 *variable
的内容始终是声明右侧类型的内存块的地址以及它强加的其他 restriction/features。
然后让我们回顾一下接口是什么。
伪科学定义:对任何第一个 class 公民具有特定类型的一组要求。
转化为软件工程 - 任何具有相同内存结构(回想 structure packing)的内存块(类型)与其相关联,如合同中所述(interface
) 可以像合同提到的 类型名称 一样传递。
现在你可能会开始意识到,当你说
func (f *Faz) Bar() string
是 f
的存储函数块,其中 f
的类型是 指向 Faz
[= 的指针58=]
所在地区
func (f Faz) Bar() string
是f
的内存块,其中f
的类型是Faz
所以当你说 *Faz
类型的变量满足契约时,你怎么能假设 Faz
类型的变量符合代码中的接口类型呢?选择谁满足你的契约,只有那个类型才能承担你代码中的接口类型。