为什么Go编译器无法推断一个结构体实现了一个接口?

huangapple go评论87阅读模式
英文:

Why can't Go compiler deduce that a struct implements an interface

问题

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

> 无法将 authors(类型 []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

英文:

Running the code below will result in a compilation error:

> cannot use authors (type []Person) as type []Namer in return argument

Why can't Go compile it?

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

Declaring authors as authors := make([]Namer, 10) or var authors []Namer would be fine, but I can't see why the compiler cannot infer that Person is Namer.

答案1

得分: 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()
    // 太好了!根据返回类型,这给了我一个[]Namer,我会按照这种方式使用它!
    thing := Thing{}
    namers := append(namers, thing)
    // 这应该可以工作,因为它应该是一个[]Namer,而Thing是一个Namer。
    // 但是你不能把Thing放在[]Person中,因为那是一个具体类型。
}

如果代码期望接收一个[]Namer,那就必须得到一个[]Namer。不能使用[]ConcreteTypeThatImplementsNamer,它们不能互换。

英文:

Because a []Person is not a []Namer. Let's take your example one step further:

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.
}

If code expects to receive a []Namer, that is what it must get. Not []ConcreteTypeThatImplementsNamer - they're not interchangeable.

huangapple
  • 本文由 发表于 2021年11月20日 00:07:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/70037722.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定