Why doesn't this compile, and why does Go refuse it?
type Shape interface{ Area() float64 }
type Square struct{ side float64 }
func (s *Square) Area() float64 { return s.side * s.side }
func main() {
var s Shape = Square{2} // compile error
fmt.Println(s.Area())
}
Error: Square does not implement Shape (method Area has pointer receiver).
Method sets: the method set of T contains only value-receiver methods. The method set of *T contains both value- and pointer-receiver methods. Area has a pointer receiver, so only *Square satisfies Shape. Use var s Shape = &Square{2}.
Why: a value stored in an interface is not addressable. If Go allowed this, calling a pointer method would have to take the address of a hidden copy, and any change would silently be lost. Calling sq.Area() directly on an addressable variable sq works, because the compiler rewrites it to (&sq).Area(). The same limit explains why Square{2}.Area() on a composite literal, or on a map element, does not compile. Put var _ Shape = (*Square)(nil) near the type to get a compile-time check that it implements the interface.
More on Tricky Output & Code-Review Puzzles
- Q487Why doesn't this loop update the users?
- Q488Why is err != nil true here even though the function returned a nil pointer?
- Q490When is the receiver bound for a method value? What prints?
- Q491Code review: why does Counter always report 0, and what else is wrong?
- Q492What happens if you add or delete map entries while ranging over the map?
- Q493Why won't m["a"].count++ compile, and what happens with a nil map?