How to Fix "cannot use type X as type Y in assignment" in Go Interfaces
Quick answer
The Go compiler refuses to let you assign a struct to an interface variable or pass it to a function expecting that interface, even though you're sure your...
The Go compiler refuses to let you assign a struct to an interface variable or pass it to a function expecting that interface, even though you're sure your type implements it. This is almost always a method set mismatch β either a missing method or a pointer-vs-value receiver conflict.
The Problem
The compile error names both types explicitly and usually lists exactly what's missing:
$ go build .
./main.go:22:14: cannot use user (variable of type User) as Notifier value in argument to SendAlert: User does not implement Notifier (method Notify has pointer receiver)
Or, when a method is missing entirely rather than mismatched:
$ go build .
./main.go:18:20: cannot use &svc (variable of type *EmailService) as type Notifier in variable declaration:
*EmailService does not implement Notifier (missing method Notify)
Why It Happens
Go interfaces are satisfied implicitly, based purely on method sets β there's no implements keyword, so mismatches only surface at compile time when you try to actually use the type as that interface. This error comes from one of two related causes:
- A method is genuinely missing. Your struct doesn't define every method the interface requires, or a method's signature (parameter types, return types, number of arguments) doesn't exactly match what the interface declares.
- Pointer vs. value receiver mismatch. If a method is defined with a pointer receiver (
func (s *Service) Notify()), only*Servicesatisfies the interface β the value typeServicedoes not, because Go can't guarantee it can call a pointer-receiver method on a value it doesn't have the address of in every context.
This second case is the most common source of confusion, since it's easy to assume a value and its pointer are interchangeable for interface satisfaction β in Go, they aren't.
The Fix
First, confirm exactly what the interface requires:
type Notifier interface {
Notify(message string) error
}
If the error says a method is missing, add it with a matching signature β parameter types and return types both have to match exactly, not just be "close enough":
func (s *EmailService) Notify(message string) error {
return sendEmail(message)
}
If the error is about a pointer receiver, the fix is usually to pass a pointer to the interface-accepting code instead of a value:
svc := EmailService{}
var n Notifier = &svc // use a pointer, not the value directly
SendAlert(n)
If you need the value type itself to satisfy the interface β for example, because you're storing it by value in a slice and want to pass elements directly β switch the method to a value receiver instead, as long as the method doesn't need to mutate the struct:
func (s EmailService) Notify(message string) error {
return sendEmail(message)
}
Be aware this changes behavior if the method was relying on mutating the receiver β a value receiver operates on a copy, so any field changes inside the method won't persist back to the original struct.
To check which methods a type actually satisfies before you hit the compiler error, you can assert it against the interface directly in a throwaway variable, which gives a clearer compile-time check while you're debugging:
var _ Notifier = (*EmailService)(nil) // compile-time check only, no runtime cost
This line does nothing at runtime, but if *EmailService doesn't fully implement Notifier, the build fails right here with a clear message instead of somewhere else in the code that's harder to trace back.
Still Not Working?
If method signatures look identical but the error persists, check for a subtle type mismatch in the parameters or return values β a common trap is one side using a named type and the other using its underlying type, which Go treats as genuinely different:
type Message string
// Interface expects:
Notify(msg Message) error
// But your method has:
func (s *EmailService) Notify(msg string) error { ... } // string != Message, mismatch
Align the exact types on both sides, including custom named types, generic type parameters, and variadic vs. slice parameters β Go's interface satisfaction check is strict and exact, with no implicit conversions applied.