Introduction: A Moment of Truth for Go Developers
\n\nIf you've ever written code in Go (Golang) and used interfaces, you've likely encountered this compiler message:
\n\ncannot use x (variable of type *MyStruct) as type MyInterface value in assignment:\n*MyStruct does not implement MyInterface (method GetName has a pointer receiver)\n\nOn Stack Overflow, this question gathers thousands of views. Beginners get stuck, and experienced developers shrug. But behind this error lies an elegant and important concept: the difference between a value receiver and a pointer receiver in the Go language.
\n\nIn this article, we'll look under the hood of the Go compiler, analyze real code examples, and understand how to avoid this pitfall. You'll learn not only why the error occurs but also how it relates to the type and interface system.
\n\n1. Interfaces in Go: A Quick Primer
\n\nBefore diving into the error, let's recall how Go interfaces work. Unlike Java or C++, an interface in Go is a set of methods. If a type implements all the methods of an interface, it automatically satisfies that interface (duck typing).
\n\nExample of a simple interface:
\n\ntype Speaker interface {\n Speak() string\n}\n\nNow let's define a struct and one method:
\n\ntype Dog struct {\n Name string\n}\n\n// Value receiver — the method works with a copy of the struct\nfunc (d Dog) Speak() string {\n return "Woof! I am " + d.Name\n}\n\nHere, Dog implements Speaker. It works with both Dog and *Dog:
var s Speaker\ns = Dog{Name: "Buddy"} // ✅ OK\ns = &Dog{Name: "Rex"} // ✅ OK (Go automatically dereferences)\n\nSo far, so simple. Now let's change the method to a pointer receiver:
\n\nfunc (d *Dog) Speak() string {\n return "Woof! I am " + d.Name\n}\n\nAnd here's where the magic begins.
\n\n2. Pointer Receiver vs Value Receiver: What's the Difference?
\n\nIn Go, methods can have two types of receivers:
\n\n- \n
- Value receiver
(t Type)— the method receives a copy of the value. \n - Pointer receiver
(t *Type)— the method receives a pointer to the original value. \n
Why is this important? Because the method set of a type depends on which receiver is used.
\n\nTruth table:
\n\n- \n
- Type
Thas all methods with a value receiver (forT). \n - Type
*Thas all methods with a value receiver + pointer receiver. \n
In other words: the pointer gets a "bonus" set of methods, while the value only gets those declared with a value receiver.
\n\nThis is not a bug but a feature of Go's design. The compiler cannot automatically take the address of a value if it is not addressable (e.g., a function result or a literal).
\n\n3. Breaking Down the Error: «method has a pointer receiver»
\n\nLet's go back to our example. If Speak() is declared with *Dog, then:
var s Speaker\ns = Dog{Name: "Buddy"} // ❌ ERROR\n// cannot use Dog{...} as Speaker...\n// method has a pointer receiver\n\nWhy? Because Dog (not a pointer) does not have the Speak() method in its set. The method belongs only to *Dog.
But this works:
\n\ns = &Dog{Name: "Buddy"} // ✅ OK\n\nNow let's look at a more practical example from real code, often seen on Stack Overflow.
\n\nExample: Interface and Struct with Data
\n\npackage main\n\nimport "fmt"\n\ntype User interface {\n GetID() int\n SetName(name string)\n}\n\ntype Admin struct {\n ID int\