Compiler error when using an interface type in a list

82 views
Skip to first unread message

John Sturdy

unread,
Jun 11, 2020, 12:50:41 PM6/11/20
to golang-nuts
I've defined an interface type, and a concrete type that I think implements that interface, but when I use it in a list, I get an error from the compiler that makes it look like it doesn't.

Here's my interface type, in anything/anything.go:

    package anything

    import (
            "fmt"
    )

    type AnyThing interface {
            Textual() string
            Numeric(name string) int
    }

    func OneCallee(thing AnyThing) {
            fmt.Printf("textual result is %s and numeric result is %d\n", thing.Textual(), thing.Numeric("default"))
    }

    func ListCallee(things []AnyThing) {
            fmt.Printf("textual result is %s and numeric result is %d\n", things[0].Textual(), things[0].Numeric("default"))
    }


and here's a concrete type that defines the methods required by the interface, in particularthing/particularthing.go:

    package particularthing

    type ParticularThing struct {
            Name string
            Number int
    }

    func (n ParticularThing) Textual() string {
            return n.Name
    }

    func (n ParticularThing) Numeric(name string) int {
            return n.Number
    }

and here's the caller:

    package main

    import (
            "example.com/user/scratch/anything"
            "example.com/user/scratch/particularthing"
    )

    func main() {
            onething := particularthing.ParticularThing{"this", 1}
            anything.OneCallee(onething)
            thinglist := make([]particularthing.ParticularThing, 1)
            anything.ListCallee(thinglist)
    }

When I compile it, I get:

    ./caller.go:12:21: cannot use thinglist (type []particularthing.ParticularThing) as type []anything.AnyThing in argument to anything.ListCallee

Could some explain what the problem with this is?

I've attached a tarball of the files to make experimental changes easier.

minimal.tar

burak serdar

unread,
Jun 11, 2020, 1:03:59 PM6/11/20
to John Sturdy, golang-nuts
An array of values implementing an interface cannot be used in place
of an array of those interfaces. Go's type system simply compares the
type required with the type provided, and []someInterface is not
[]someType. Note that the structure of the two objects passed to the
function is quite different. The function expects a []someInterface
where each element of the array is a pair containing the pointer to
the value and the type, but you are sending []someType where each
element is a value. So you have to convert:

intfList:=make([]AnyThing,0)
for _,x:=range thingList {
intfList=append(intfList,x)
}
anything.ListCallee(intfList)

You can argue that the compiler can do this conversion. Such
potentially expensive operations are explicit in Go, which creates
some clutter but overall not a bad thing.



>
> I've attached a tarball of the files to make experimental changes easier.
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3abb649b-f134-4535-8832-18c8ca0a54ebo%40googlegroups.com.

John Sturdy

unread,
Jun 12, 2020, 4:44:08 AM6/12/20
to golang-nuts
Thanks --- I understand the difference now... I had expected the compiler to handle it, on the basis of being able to use an implementation of an interface type wherever the interface type is used, but it looks like it's a mixture of static and dynamic typing and this is where they don't quite join up.  I'll try the solution you suggest.

On Thursday, June 11, 2020 at 6:03:59 PM UTC+1, burak serdar wrote:
> To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages