为啥 Go 编译器不能推断结构实现了接口 [关闭]

Posted

技术标签:

【中文标题】为啥 Go 编译器不能推断结构实现了接口 [关闭]【英文标题】:Why can't Go compiler deduce that a struct implements an interface [closed]为什么 Go 编译器不能推断结构实现了接口 [关闭] 【发布时间】:2021-12-30 09:33:10 【问题描述】:

运行下面的代码会导致编译错误:

不能在返回参数中使用作者(类型 []Person)作为类型 []Namer

为什么不能Go编译?

type Namer interface 
    Name() string


type Person struct 
    name string


func (r Person) Name() string 
    return r.name


func Authors() []Namer 
    // One or the other is used - both are not good:
    authors := make([]Person, 10)
    var authors []Person

    ...

    return authors

authors 声明为authors := make([]Namer, 10)var authors []Namer 可以,但我不明白为什么编译器不能推断PersonNamer

【问题讨论】:

golang.org/doc/faq#convert_slice_of_interface Person 不是 Namer。它们是不同的类型。 Person 确实实现了Namer 接口,但这仅意味着Person 的值可以分配给Namer 类型的值。它对类型等价没有任何一般含义,例如您在此处显示的复合类型。这就是为什么需要深度转换(参见 Cerise 的评论) 这能回答你的问题吗? Type converting slices of interfaces 【参考方案1】:

因为[]Person 不是[]Namer。让我们把你的例子更进一步:

type Namer interface 
    Name() string


type Person struct 
    name string


func (r Person) Name() string 
    return r.name


type Thing struct 
    name string


func (t Thing) Name() string 
    return r.name


func Authors() []Namer 
    authors := make([]Person, 10)
    return authors


func main() 
    namers := Authors()
    // Great! This gives me a []Namer, according to the return type, I'll use it that way!
    thing := Thing
    namers := append(namers, thing)
    // This *should* work, because it's supposed to be a []Namer, and Thing is a Namer.
    // But you can't put a Thing in a []Person, because that's a concrete type.

如果代码期望收到[]Namer,那就是它必须得到的。不是 []ConcreteTypeThatImplementsNamer - 它们不可互换。

【讨论】:

以上是关于为啥 Go 编译器不能推断结构实现了接口 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能快速推断闭包类型

为啥 Crystal 不能在初始化程序中推断出这种类型?

为啥我不能用主包中的方法集合调用接口

为啥接口的显式实现不能公开?

go结构,结构嵌套,接口,指针的测试和结论

Go 语言中的方法,接口和嵌入类型