What are Go interfaces and how does implicit implementation work?
Learn what Go interfaces are and how implicit, structural implementation works — no 'implements' keyword — with dynamic dispatch and code examples.
Expected Interview Answer
A Go interface is a type that defines a set of method signatures; any type that has those methods satisfies the interface automatically. Implementation is implicit — there is no 'implements' keyword. If a type's method set includes every method the interface requires, it satisfies that interface without declaring any relationship.
This structural, duck-typed design decouples the definition of behavior from its implementation: interfaces can be declared in the consuming package, so you can write an interface for types you don't own. At runtime an interface value holds two words — a pointer to type information (including the method table) and a pointer to the concrete value — which powers dynamic dispatch and type assertions. The empty interface (interface{}, or any) is satisfied by every type, and small, focused interfaces like io.Reader are idiomatic.
- No explicit declaration — types satisfy interfaces automatically
- Interfaces can be defined by the consumer, decoupling packages
- Enables mocking and testing without touching concrete types
- Encourages small, composable interfaces like io.Reader/io.Writer
- Supports polymorphism via dynamic dispatch and type assertions
AI Mentor Explanation
An interface is like the role of 'wicketkeeper' — defined purely by the skills it demands: catch, stump, appeal. Nobody signs a form declaring they are a keeper; anyone who can perform those actions simply is one. Go works the same: a type never announces it implements an interface, it just happens to have the required methods, and the compiler recognizes it as fitting the role automatically.
Step-by-Step Explanation
Step 1
Declare the interface
Write type Reader interface { Read(p []byte) (int, error) } — a named set of method signatures.
Step 2
Implement the methods
Give a concrete type the exact method signatures; no 'implements' keyword or import of the interface is required.
Step 3
Satisfy structurally
If the type's method set includes every interface method, it satisfies the interface automatically at compile time.
Step 4
Use via the interface
Pass the concrete value where the interface is expected; calls dispatch dynamically to the concrete method.
Step 5
Assert or switch on type
Recover the concrete type with v, ok := x.(*T) or a type switch when you need the underlying value.
Step 6
Prefer small interfaces
Keep interfaces tiny (often one method) and define them in the consuming package for maximum decoupling.
What Interviewer Expects
- That interfaces are sets of method signatures
- That implementation is implicit — no 'implements' keyword
- Structural/duck typing based on the method set
- That an interface value holds a type pointer and a value pointer
- Idioms: small interfaces, the empty interface (any), type assertions
Common Mistakes
- Looking for an 'implements' keyword like Java
- Thinking a type must import or reference the interface it satisfies
- Confusing pointer vs value receivers when checking the method set
- Assuming a nil interface equals an interface holding a nil pointer
- Designing large interfaces instead of small, focused ones
Best Answer (HR Friendly)
“A Go interface lists the behaviors something must have. Any type that already provides those behaviors automatically counts as satisfying the interface — you never have to declare the connection, which keeps the code flexible and easy to test.”
Code Example
type Speaker interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string { return "Woof" }
type Robot struct{}
func (r Robot) Speak() string { return "Beep" }
// No "implements" — both satisfy Speaker automatically.
func announce(s Speaker) { fmt.Println(s.Speak()) }
func main() {
announce(Dog{}) // Woof
announce(Robot{}) // Beep
var s Speaker = Dog{}
if d, ok := s.(Dog); ok {
_ = d // recovered concrete type
}
}Follow-up Questions
- What is the empty interface (any) and when is it useful?
- How do pointer vs value receivers affect which types satisfy an interface?
- Why can a non-nil interface holding a nil pointer be surprising?
- How do type assertions and type switches differ?
- Why does Go favor many small interfaces over a few large ones?
MCQ Practice
1. How does a type satisfy a Go interface?
Go uses structural typing: any type whose method set includes every method the interface declares satisfies it automatically, with no explicit declaration.
2. What does an interface value hold at runtime?
An interface value is two words: a pointer to type information (with the method table) and a pointer to the underlying concrete value, enabling dynamic dispatch.
3. What is interface{} (any) satisfied by?
The empty interface declares no methods, so every type trivially satisfies it, which is why it can hold a value of any type.
Flash Cards
What is a Go interface? — A type that defines a set of method signatures; any type with those methods satisfies it.
How is implementation declared? — It isn't — implementation is implicit and structural; there is no 'implements' keyword.
What does an interface value contain? — Two pointers: one to type info (method table) and one to the concrete value.
What satisfies the empty interface (any)? — Every type, because it declares no methods.
What idiom does Go favor for interfaces? — Small, focused interfaces (often one method) defined in the consuming package.