2

Let's consider the following program

type Fruit interface {
    Color() string
}

type Apple struct {
    color string
}

func (x *Apple) Color() string {
    return x.color
}

func (x *Apple) Compare(y Fruit) bool {
    _, ok := y.(*Apple)

    if ok {
        ok = y.Color() == x.Color()
    }

    return ok
}

func main() {
    a := Apple{"red"}
    b := Apple{"green"}

    a.Compare(&b)
}

Now, note the last line that says a.Compare(&b). Here I am passing a pointer to Apple. This works correctly, but note that my Compare function does NOT accept the pointer (y Fruit).

Now if I change the last line to say a.Compare(b) then it gives me the following error:

cannot use b (type Apple) as type Fruit in argument to a.Compare: Apple does not implement Fruit (Color method has pointer receiver)

What is [go]ing on here?

treecoder
  • 43,129
  • 22
  • 67
  • 91
  • 2
    Check out this related / possible duplicate question+answer: [Go, X does not implement Y (… method has a pointer receiver)](http://stackoverflow.com/questions/40823315/go-x-does-not-implement-y-method-has-a-pointer-receiver/40824044#40824044) – icza Apr 23 '17 at 10:53

1 Answers1

3

For reasons outlined in this answer, Apple does not implement Fruit, but *Apple does. If you define Color on Apple (instead of *Apple), the code compiles:

package main

import (
    "fmt"
)
type Fruit interface {
    Color() string
}

type Apple struct {
    color string
}

func (x Apple) Color() string {
    return x.color
}

func (x Apple) Compare(y Fruit) bool {
    _, ok := y.(Apple)

    if ok {
        ok = y.Color() == x.Color()
    }

    return ok
}

func main() {
    a := Apple{"red"}
    b := Apple{"green"}

    fmt.Println(a.Compare(b))
}
Community
  • 1
  • 1
fuglede
  • 17,388
  • 2
  • 54
  • 99
  • Alright, now I understand the difference between pointer and value receivers. One question then. Why does `a.Compare(&b)` work? I am defining a pointer receiver, but `a := Apple{"red"}` makes `a` a value, not a pointer. Then why does `a.Compare(&b)` compile? – treecoder Jun 26 '17 at 13:14
  • 1
    From https://golang.org/doc/effective_go.html#methods: "The rule about pointers vs. values for receivers is that value methods can be invoked on pointers and values, but pointer methods can only be invoked on pointers." followed by some words on why the language has been designed like that – fuglede Jul 20 '17 at 17:24