Explain method sets. Why does *T satisfy an interface when T does not?
Question 81MediumGo 1.22 to 1.25
The spec defines method sets as follows:
- The method set of
Tcontains methods declared with receiverT. - The method set of
*Tcontains methods with receiverTand*T.
type Counter struct{ n int }
func (c *Counter) Inc() { c.n++ }
func (c Counter) Get() int { return c.n }
type Incrementer interface{ Inc() }
var _ Incrementer = &Counter{} // OK
// var _ Incrementer = Counter{} // compile error:
// Counter does not implement Incrementer (method Inc has pointer receiver)
Storing a value in an interface stores a copy, and that copy is not addressable. If the interface could call Inc on it, the method would change a hidden copy and the caller would never see the update. The language forbids that silent bug.
The rule is not the same as call syntax. c.Inc() compiles for an addressable variable c Counter because the compiler rewrites it to (&c).Inc(). That rewrite is available for direct calls but not for interface satisfaction.
More on Interfaces, Methods & Embedding
- Q79What does this print? (nil interface vs interface holding a nil pointer)
- Q80Why does this function return a non-nil error even when nothing failed? How do you fix it?
- Q82Why doesn't
m["k"].Inc()compile whenInchas a pointer receiver? What other values are not addressable? - Q83How do you decide between value and pointer receivers?
- Q84Compare
v := x.(T)withv, ok := x.(T). What happens whenTis an interface type? - Q85Explain type switch semantics. What does this print?