为啥接口不能用指针接收器实现
Posted
技术标签:
【中文标题】为啥接口不能用指针接收器实现【英文标题】:Why can't the interface be implemented with pointer receivers为什么接口不能用指针接收器实现 【发布时间】:2015-08-04 21:16:22 【问题描述】:我很困惑为什么编译失败:
不可能的类型断言: Faz 没有实现 Foo(Bar 方法有指针接收器)
如果我将 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`
【问题讨论】:
See this post. 附带说明:@KerrekSB 引用的文章有助于我理解当 Go 抱怨“MyFoo 没有实现 Foo(Bar 方法有指针接收器)”时,它没有意味着您不能使用指针接收器。这意味着实现Bar
的MyFoo
方法中的none 应该有指针接收器,或者all 必须有。这与@0xor1 遇到的问题不同,但其他人可能会发现这个问题,因为他们混合了他们的接收器类型(就像我一样)并且不理解他们得到的错误。
【参考方案1】:
因为它是*Faz
而不是Faz
。
func main()
foo := New().(*Faz)
log.Println(foo)
【讨论】:
它们可以是 *Faz 或 Faz,但它们都必须匹配。如果您打算return Faz
或 *Faz 如果您打算 return &Faz
,则将它们全部定义。他们如何维护状态被认为是您基本上对用户隐藏的实现细节。【参考方案2】:
我认为这个问题的答案需要对语法进行更回顾的方法,以及如何通过软件工程来实现它。 (请原谅过于简单化)
首先快速回顾一下types
是什么?
它们只是顶部带有编译器逻辑的内存块。使array
与string
不同的是编译器允许我们对这些内存块执行的操作。 (深入思考,您可能会开始意识到strongly typed
和dynamically typed
语言之间的真正区别。)
接下来你需要意识到指针是它们自己的类型。 *variable
是与variable
不同的内存块(又名类型)。只是编译器始终假定*variable
的内容始终是声明右侧类型的内存块的地址以及它施加的其他限制/功能。
然后让我们回顾一下接口是什么。伪科学定义:任何一等公民必须具有特定类型的一组要求。
转换为软件工程 - 任何具有与合同 (interface
) 中描述的相关联的相同内存结构(回想 structure packing)的内存块(类型)都可以传递与合同中提到的类型名称一样。
现在你可能开始意识到,当你说
func (f *Faz) Bar() string
是f
保存函数的内存块,其中f
的类型是指向Faz
的指针
所在区域
func (f Faz) Bar() string
是f
的内存块,其中f
的类型是Faz
所以当你说*Faz
类型的变量满足契约时,你怎么能假设Faz
类型的变量在代码中符合接口类型的条件呢?选择谁满足你的合约,并且只有那个类型可以假设你代码中的接口类型。
【讨论】:
我不同意你的解释,下面的程序工作(类型 *foo 满足 String() 为类型 foo 定义):package main import ("fmt" ) type foo struct func (f foo) String() string return "111" func main() f := foo a := &foo var s fmt.Stringer s = as = f fmt.Println(f.String(), a .String(), s)以上是关于为啥接口不能用指针接收器实现的主要内容,如果未能解决你的问题,请参考以下文章