I do understand that interface don't implement method with pointer reference as per Go spec and FAQ, as T and *T have different method sets (https://golang.org/doc/faq#guarantee_satisfies_interface).
So, this doesn't work:
package main
import (
"fmt"
)
type user struct {
name string
}
type modifier interface {
modify()
}
func (u *user) modify() {
u.name = "My name"
}
func interfaceModify(m modifier) {
m.modify()
}
func main() {
u := user{"Default Name"}
interfaceModify(u)
fmt.Println(u.name)
}
and returns:
./main.go:26: cannot use u (type user) as type modifier in argument to interfaceModify: user does not implement modifier (modify method has pointer receiver)
This is explained as:
[…]there is no useful way for a method call to obtain a pointer.
Even in cases where the compiler could take the address of a value to pass to the method, if the method modifies the value the changes will be lost in the caller.
However, replacing interfaceModify(u)
with a direct call like u.modify()
does work: the compiler takes the address of u, and will modify its name property as Println() confirms.
So, we are able to do that operation in that precise case, but not in the interface one. My only explanation of that difference is that in interfaceModify(m modifier)
, we will have a direct copy of u to m, and no way for m to match corresponding address when calling modify()
.
And, so, declaring u := &user{"Default Name"}
would thus copy the pointer (so address) u to m, and that's why m.modify()
is possible.
Am I correct?