Method Has Pointer Receiver Interface Error in Go Fixed
A struct value does not implement an interface whose method has a pointer receiver. See the six messages, the two fixes and the fmt Stringer surprise.

The sentence "does not implement ... (method has pointer receiver)" looks like the compiler is being difficult. A Square has the method Area, and the interface wants Area. It is right, and the reason it is right is worth a minute, because the same rule decides whether your types work with sort, http, json and fmt. This article shows the six messages that come from one rule, explains the rule in terms of what the compiler would otherwise have to guess, gives the two fixes and the conditions for choosing between them, and ends with the fmt.Stringer case, where the rule gives no error at all and a surprising output. It builds on pointer or value receiver and interfaces in Go, and is part of the Go basics path.
Tested with Go 1.25.6, macOS on Apple Silicon (arm64)
Six messages from one rule
Here is a type whose only method has a pointer receiver, used in the places where that matters:
package main
import "fmt"
type Shape interface{ Area() float64 }
type Square struct{ side float64 }
func (s *Square) Area() float64 { return s.side * s.side }
func describe(s Shape) { fmt.Println(s.Area()) }
func make1() Shape {
return Square{1}
}
func main() {
sq := Square{2}
describe(sq)
shapes := []Shape{Square{1}, &Square{2}}
_ = shapes
var s Shape = &sq
_ = s.(Square)
m := map[string]Square{"a": {3}}
fmt.Println(m["a"].Area())
fmt.Println(Square{4}.Area())
}# example.test/lab
./main.go:14:9: cannot use Square{…} (value of struct type Square) as Shape value in return statement: Square does not implement Shape (method Area has pointer receiver)
./main.go:19:11: cannot use sq (variable of struct type Square) as Shape value in argument to describe: Square does not implement Shape (method Area has pointer receiver)
./main.go:21:20: cannot use Square{…} (value of struct type Square) as Shape value in array or slice literal: Square does not implement Shape (method Area has pointer receiver)
./main.go:25:6: impossible type assertion: s.(Square)
Square does not implement Shape (method Area has pointer receiver)
./main.go:28:21: cannot call pointer method Area on Square
./main.go:30:24: cannot call pointer method Area on SquareLook at the context word in each message, because it tells you which kind of place you used the value in. As a return value, a function argument and an element of a slice literal, the message is cannot use ... as Shape value in ...: Square does not implement Shape (method Area has pointer receiver). Assertion to the concrete type from an interface that holds a *Square gives impossible type assertion: s.(Square), with the same reason on the next line: a Square can never be in a Shape, so the assertion could never succeed. The last two are cannot call pointer method Area on Square, for a map element and a composite literal. Those do not involve an interface at all. They come from the next section.
Why a value does not qualify
A method with a pointer receiver can change the thing it is called on. Calling it requires the address of a variable. When you call sq.Area() on a variable, Go takes the address for you, (&sq).Area(), since sq is addressable. Put the value into an interface, though, and what the interface stores is a copy. A call through the interface would run the pointer method on that hidden copy, not on your variable, and any change it made would vanish. The language designers' answer was to make that impossible: only a pointer can carry a pointer method into an interface. The rule is stated as method sets, in the specification section on method sets:
| Type | Method set contains |
|---|---|
T | Methods with receiver T |
*T | Methods with receiver T and with receiver *T |
An interface is satisfied if the type's method set contains all its methods. *Square has Area, so it qualifies, and Square does not.
The other two messages follow the same logic. A map element is not addressable, because the table may move its entries, so m["a"].Area() has no address to take. A composite literal Square{4} is a temporary value with no variable behind it, and the compiler declines to invent one. Assign to a variable first, sq := Square{4}; sq.Area(), or use a map of pointers, map[string]*Square.
Two fixes
Pass a pointer. The smallest change at the call site, and the right one when the method modifies state or the struct is not trivially small:
package main
import "fmt"
type Shape interface{ Area() float64 }
type Square struct{ side float64 }
func (s *Square) Area() float64 { return s.side * s.side }
func describe(s Shape) { fmt.Println(s.Area()) }
func main() {
sq := Square{2}
describe(&sq)
shapes := []Shape{&Square{1}, &Square{3}}
total := 0.0
for _, s := range shapes {
total += s.Area()
}
fmt.Println(total)
byName := map[string]*Square{"a": {3}}
fmt.Println(byName["a"].Area())
}4
10
9This is also what the standard library expects. Types such as bytes.Buffer, strings.Builder and sync.Mutex are used by pointer for this reason, and constructors return *T.
Change the receiver to a value. If the type is small, immutable, and has no business being modified through a method, a value receiver is the better design, and it makes both Square and *Square satisfy the interface:
func (s Square) Area() float64 { return s.side * s.side }Do this when you wrote the type and the method does not mutate. Do not do it just to silence the compiler on a type that has other pointer methods, because mixing receivers on one type makes its method set differ between T and *T, which is the confusion you are trying to avoid. Pick one kind per type. The benchmark and the decision table are in pointer or value receiver.
The case with no error: fmt and String
The method set rule also governs which values fmt can call methods on, and there the compiler says nothing. A type with a String method on its pointer receiver prints differently as a value and as a pointer:
package main
import "fmt"
type Temp struct{ degrees float64 }
func (t *Temp) String() string { return fmt.Sprintf("%.1f C", t.degrees) }
func main() {
t := Temp{21.5}
fmt.Println(t)
fmt.Println(&t)
fmt.Printf("%v %s\n", t, &t)
}{21.5}
21.5 C
{21.5} 21.5 CThe first line prints {21.5}: the Temp value does not have String in its method set, so fmt falls back to printing the struct's fields. The second prints 21.5 C, because *Temp does. There is no compile error, since fmt.Println takes any, and the only symptom is output that looks wrong. If a type's log lines look raw in some places and formatted in others, check whether the code is printing a value where it should print a pointer, or define String on a value receiver so that both work. go vet checks printf calls for many problems, and this is not one it reports, so the habit has to be yours.
Finding the right fix quickly
When you see the error, ask two questions. Does the method change the receiver? If yes, it needs a pointer, and the fix is at the call site. Is the type used as a value everywhere else in the code, in slices, maps and struct fields? If so, it may be a small value type, and the better fix is to make all its methods value receivers. A third question helps when the type is large: how many places create the value? If it is one constructor, have it return *T and the error disappears at every use.
The compiler's wording is stable and precise, and one more detail in it is useful. The part in parentheses is either method M has pointer receiver or missing method M. The first means you have the method on the other receiver kind, and the second means it does not exist, usually a typo, a wrong signature or an unexported name, and in that case the compiler adds have M(int) and want M(string) lines so you can compare signatures.
When you cannot change either side
If the type comes from a package you do not control and it has pointer methods, you can only use it by pointer, and that is the contract. If the interface comes from elsewhere and your type cannot sensibly be a pointer, say a small value that must be comparable, write a thin wrapper type with the value-receiver method that delegates. And for generics, a constraint such as interface{ *T; Reset() } is the idiom for requiring the pointer form, which the standard library uses in a few places. The Go FAQ entry on this question explains the design reason in the language designers' words, and the Effective Go section on pointers versus values shows the standard shapes.


