-1

If I have an interface type like:

type Message interface {
  New() *Message
  Get() string
}

and a structure like this:

type Entity struct {}
func (e *Entity) New() *Entity {
  return e
}
func (e Entiy) Get() string {
  return "hi"
}

Entity will not be a Message type unless I remove the New() *Message. Can someone explain to me why that is not working and/or where my issue is?

Challenger5
  • 959
  • 6
  • 26
zio
  • 193
  • 1
  • 1
  • 10
  • 2
    https://play.golang.org/p/tE8ao7eyS0e – dm03514 Apr 18 '18 at 12:00
  • @dm03514 thanks! I guess it has to work this way. I maybe misunderstood the way how interfaces are working – zio Apr 18 '18 at 12:07
  • 2
    The whole pointer to an interface is really confusing, i'm trying to think how to explain it but am not even familiar with what technically is going on under the hood. https://stackoverflow.com/questions/44370277/type-is-pointer-to-interface-not-interface-confusion has a good explanation, and a couple of really good links – dm03514 Apr 18 '18 at 12:09

1 Answers1

4

For Entity to fulfill your interface it must comply strictly with the interface definition:

Trying to print an entity using

func msg(m Message) {
  fmt.Println(m.Get())
}

shows:

func main() {
    fmt.Println("Hello, playground")
    e := &Entity{}
    e2 := e.New()
    msg(e2)
}
prog.go:28:5: cannot use e2 (type *Entity) as type Message in argument to msg:
    *Entity does not implement Message (wrong type for New method)
        have New() *Entity
        want New() *Message

Updating Entity.New() to return a pointer to a Message interface now shows:

type Message interface {
  New() *Message
  Get() string
}

type Entity struct {}
func (e *Entity) New() *Message {
  return e

prog.go:14:3: cannot use e (type *Entity) as type *Message in return argument:
    *Message is pointer to interface, not interface
prog.go:28:5: cannot use e2 (type *Message) as type Message in argument to msg:
    *Message is pointer to interface, not interface

More about this can be read:

"<type> is pointer to interface, not interface" confusion

Now updating your methods to return an interface instead of a pointer to an interface yields:

type Message interface {
  New() Message
  Get() string
}

type Entity struct {}
func (e *Entity) New() Message {
  return e
}
func (e Entity) Get() string {
  return "hi"
}

func msg(m Message) {
  fmt.Println(m.Get())
}

func main() {
    fmt.Println("Hello, playground")
    e := &Entity{}
    e2 := e.New()
    msg(e2)
}

Hello, playground
hi
dm03514
  • 54,664
  • 18
  • 108
  • 145