Assuming we have an understanding that,
For explicit method definition for type
X
, GO compiler implicitly defines the same method for type*X
and vice versa, if I declare,func (c Cat) foo(){ //do stuff_ }
and declare,
func (c *Cat) foo(){ // do stuff_ }
then GO compiler gives error,
Compile error: method re-declared
which indicates that, pointer method is implicitly defined and vice versa
In the below code,
package main
type X interface{
foo();
bar();
}
type Cat struct{
}
func (c Cat) foo(){
// do stuff_
}
func (c *Cat) bar(){
// do stuff_
}
func main() {
var c Cat
var p *Cat
var x X
x = p // OK; *Cat has explicit method bar() and implicit method foo()
x = c //compile error: Cat has explicit method foo() and implicit method bar()
}
GO compiler gives error,
cannot use c (type Cat) as type X in assignment:
Cat does not implement X (bar method has pointer receiver)
at x = c
, because, implicit pointer methods satisfy interfaces, but implicit non-pointer methods do not.
Question:
Why implicit non-pointer methods do not satisfy interfaces?
Method set
Following the spec:
Method set definition sounds weird until you follow addressable and not addressable types concept.
Addressable and not addressable types
It is possible to call a pointer receiver method on a value if the value is of addressable type.
It is ok to call pointer receiver methods on values till you are dealing with addressable types (struct is addressable):
Variables of interface type are not addressable
But not all Go types are addressable. Also variables referenced through interfaces are not addressable.
It is impossible to call pointer receiver on values of not addressable types:
So with the following error Go runtime prevents segment fault:
How about this?
Add a little to dev.bmax's answer.
you can do
but not
It's legal to call a *T method on an argument of type T so long as the argument is a variable; the compiler implicitly takes its address. But this is mere syntactic sugar: a value of type T does not posses all methods that a *T pointer does, and as a result it might satisfy fewer interfaces.
On the other hand, you can always call foo() with Cat or *Cat.
Let's look into the language specification:
In your example, the method set of the interface type
x
is[foo(), bar()]
. The method set of the typeCat
is[foo()]
, and the method set of the type*Cat
is[foo()]
+[bar()]
=[foo(), bar()]
.This explains, why variable
p
satisfies the interfacex
, but variablec
doesn't.