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?
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)
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",
}
}
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",
}