4

In these two tutorial examples, why does a method with a pointer receiver satisfy an interface in one case but not the other?

In example #55 the class Vertex doesn't satisfy the Abser interface because method Abs is only defined for *Vertex and not Vertex:

type Abser interface {
    Abs() float64
}

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

The error message is:

prog.go:22: cannot use v (type Vertex) as type Abser in assignment:
    Vertex does not implement Abser (Abs method has pointer receiver)

But in example #57, the class MyError satisfies the error interface ok even though Error() is defined for *MyError and not MyError:

type error interface {
    Error() string
}

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}

From the description in this answer, it seems like both should work ok, but the tutorial demonstrates the first one failing. What's the difference?

Community
  • 1
  • 1
Eric
  • 11,392
  • 13
  • 57
  • 100

3 Answers3

6

in example57, the error is returned as such:

return &MyError{
    time.Now(),
    "it didn't work",
}

this returns a pointer to the MyError struct. And *MyError satisfies the interface.

In example55 this is also pointed out:

a = &v // a *Vertex implements Abser

// In the following line, v is a Vertex (not *Vertex)
// and does NOT implement Abser.
a = v

As it says in the answer you are referring to, the generation occurs when it's the other way around (*MyStruct type will have all the methods MyStruct has)

Dean Elbaz
  • 2,310
  • 17
  • 17
3

In #57 only *MyError satisfies the error. As you can see, the value returned from run() is *MyError, not MyError:

func run() error {
    return &MyError{ // <<< Notice the '&'.
        time.Now(),
        "it didn't work",
    }
}
Ainar-G
  • 34,563
  • 13
  • 93
  • 119
3

In #57 it is returning a pointer to my Error:

return &MyError{ //notice the "&", that means return the address / pointer to that struct.
    time.Now(),
    "it didn't work",
}
OneOfOne
  • 95,033
  • 20
  • 184
  • 185