The Error Message
If you have spent more than a week writing Go, you have likely run into a frustrating compiler error. It usually happens when you try to pass a struct into a function, and the compiler stops you cold with a message like this:
cannot use val (type *MyStruct) as type MyInterface in argument to Foo: *MyStruct does not implement MyInterface (missing Method method)
Sometimes, the error is even more confusing because it tells you the method exists, but the "receiver" is wrong:
cannot use MyStruct{...} (type MyStruct) as type MyInterface in argument to Foo: MyStruct does not implement MyInterface (Method method has pointer receiver)
What is causing this?
Go's type system is famously explicit. Unlike some languages that try to guess what you mean, Go requires an exact match between your struct's methods and the interface's definition. This error typically stems from one of three specific issues:
- The Pointer Receiver Trap: You defined your method on
*MyStruct(the pointer), but you are passingMyStruct(the value). - Signature Mismatches: You might have a typo in a parameter or return type. For example, using an
intwhen the interface demands anint64. - Visibility Issues: Your method is unexported (lowercase) while the interface expects an exported (uppercase) one.
Step-by-Step Fixes
1. Solve the Pointer Receiver Mismatch
This is the culprit 90% of the time. In Go, the method set of a value type does not include methods defined with a pointer receiver. This prevents you from accidentally calling a method that modifies a copy of your data instead of the original.
type MyInterface interface {
Update(name string)
}
type MyStruct struct {
Name string
}
// This method belongs to *MyStruct, not MyStruct
func (s *MyStruct) Update(name string) {
s.Name = name
}
If you try to pass a literal MyStruct{}, the code will fail to compile. The fix is simple: use the address-of operator (&) to pass a pointer instead.
val := MyStruct{}
// Foo(&val) works! Foo(val) fails.
2. Match Signatures Exactly
Go does not support covariant return types or automatic type casting in interfaces. If an interface expects an error return, you cannot return nil directly if your method signature doesn't explicitly state it returns an error.
Incorrect:
type Closer interface {
Close() error
}
// This fails because the return type 'error' is missing
func (s *MyStruct) Close() {
fmt.Println("Closing...")
}
Correct: Make sure every single character in the signature matches the interface definition.
func (s *MyStruct) Close() error {
return nil
}
3. Check for Package Privacy
Interfaces defined in other packages can only "see" your exported methods. If you are trying to implement io.Writer, your method must be Write, not write. Lowercase methods are private to your package and are invisible to interfaces defined elsewhere.
The "Pro" Way to Verify Fixes
Don't wait for your whole project to build just to check if a struct satisfies an interface. Go developers use a "Static Interface Check" to catch these errors instantly. Place this line right below your struct definition:
var _ MyInterface = (*MyStruct)(nil)
This line does not allocate any memory. It simply tells the compiler: "Ensure that a pointer to MyStruct can be assigned to MyInterface." If you break the implementation later, this line will highlight the error immediately in your IDE.
Best Practices for Interfaces
- Be Consistent: If one method on your struct requires a pointer receiver, make all methods on that struct use pointer receivers. This keeps your method sets predictable.
- Keep Interfaces Small: Follow the Go proverb: "The bigger the interface, the weaker the abstraction." Aim for 1-3 methods per interface.
- Use Tooling: If you use VS Code or GoLand, right-click your struct and select "Implement Interface." This automatically generates the correct signatures, saving you from typos.

