-5

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.

luqo33
  • 7,196
  • 13
  • 50
  • 101
  • 5
    https://golang.org/doc/faq#convert_slice_of_interface – Bayta Darell Nov 19 '21 at 16:09
  • 1
    `Person` isn't `Namer`. They are different types. It's true that `Person` implements the `Namer` interface, but that only means that a value of `Person` is assignable to a value of type `Namer`. It has doesn't have any general implications about type equivalence, for example in composite types as you're showing here. That is why deep conversion is required (see Cerise's comment) – Hymns For Disco Nov 19 '21 at 16:19
  • 1
    Does this answer your question? [Type converting slices of interfaces](https://stackoverflow.com/questions/12753805/type-converting-slices-of-interfaces) – rustyx Nov 19 '21 at 16:43

1 Answers1

1

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.

Adrian
  • 38,231
  • 5
  • 90
  • 87