You’re complicating it needlessly, the thinking can be much simpler: For a function like
func mutator(mute Mutable) error, the
Mutable interface simply needs to be satisfied by the
Mutable with a value receiver, like
func (ma MutableA) mutate (s string) error, then one can say that “type MutableA implements/satisfies interface Mutable”.
If another type
Mutable with a pointer receiver, like
func (mp *MutableP) mutate (s string) error, one can say that “type *MutableP implements/satisfies interface Mutable” or “type pointer-to-MutableP implements Mutable”, which does not imply that “type MutableP implements/satisfies Mutable” (but the reverse implication, that a value of a type implementing an interface implies that the pointer to a value of such type also implements it, is true… which may sound inconsistent, but it’s incredibly nice in practice sparing everyone of C++ style
-> ugliness that rarely brings any extra clarity).
So and interface can be satisfied either by a value (struct or primitive) or by a pointer to a value, the “interface satisified by type
T” is not the same thing as the “interface satisfied by type
*T". The thinking behind Go’s type system is actually very simple (although unique compared to all other programming languages), it’s just that people are not used to this simplicity so they make it complicated in their heads :)
And… the cool part is the consequence of all this: Go is transferring control of whether something is a pointer or value from the function requiring an interface type to the code defining an actual type satisfying that interface and this can be pretty awesome ;)