Interfaces
Interfaces are how Go does polymorphism — writing one function that works with many different types. By the end of this lesson you'll define an interface, satisfy it implicitly, store mixed types in one slice, and pull concrete values back out with type assertions and type switches.
Learn Interfaces in our free Go course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free Go course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
Since Go 1.18 you can write any as a built-in alias for {'interface '} . They mean exactly the same thing.
1️⃣ Defining and Satisfying an Interface
An interface lists the methods a type must have. The crucial Go idea: satisfaction is implicit . You never write implements Speaker — if your type has a Speak() string method, it is a Speaker , full stop. This lets you write a function once and have it accept types that didn't even exist when you wrote it.
Your turn. Give French the one method it needs to satisfy Greeter , then run it.
2️⃣ A Slice of an Interface
Because every type that satisfies Shape can stand in for it, you can put different concrete types into a single and treat them uniformly. This is the everyday payoff of interfaces: collections of "things that can do X" without caring exactly what each one is.
3️⃣ Type Assertions & Type Switches
Sometimes you have an interface value and need the real type back. A type assertion v, ok := i.(T) gives you the value and a boolean telling you whether the assertion held — always use the two-value form so a wrong guess doesn't panic. When you have several possibilities, a type switch reads far more cleanly.
4️⃣ The Empty Interface & Stringer
The empty interface {'interface '} (or any ) is satisfied by everything, which is exactly why fmt.Println can accept any value. One interface you'll meet constantly is fmt.Stringer : give your type a String() string method and fmt will use it automatically when printing.
These lines define a Speaker interface, a type that satisfies it, and use it. Put them in the correct order:
C, F, B, D, E, A, G. Declare the interface, then the concrete type, then the method that satisfies the contract; inside main create a value and call its method. The interface and type definitions live at package level (outside main ).
Predict the output before revealing the answer.
"" false (an empty string then false). The dynamic type is int , not string , so the assertion fails. The two-value form returns the zero value and ok = false instead of panicking.
2. Does this compile, and what does it print?
It compiles and prints money . Coin has a String() string method, so it implicitly satisfies Stringer — no declaration needed.
3. What does the type switch print for describe(3.5) ?
other — 3.5 is a float64 , which matches neither the int nor the string case, so the default branch runs.
Q: Why doesn't Go have an implements keyword?
Go uses structural typing for interfaces: if the methods match, the type satisfies the interface automatically. This decouples your types from the interfaces other packages define, so a type can satisfy an interface that was written long after the type itself.
Q: What's the difference between any and {'interface '} ?
None — any is a built-in alias for {'interface '} added in Go 1.18. Use any for readability in new code.
Q: When should I use a type switch instead of separate interfaces?
Prefer interfaces and polymorphism when behaviour varies by type. Reach for a type switch only when you genuinely must branch on the concrete type — for example, when decoding unknown JSON or formatting values for display.
Yes. type ReadWriter interface {' '} combines both method sets. A type satisfies it only if it has every method from both.
No blanks this time — just a brief. Define a one-method interface, two types that satisfy it, then range over a slice holding both. This "list of things that share a behaviour" shape appears in almost every real Go codebase.
Practice quiz
What is a Go interface?
- A struct with no fields
- A set of method signatures
- A list of variables
- A package import
Answer: A set of method signatures. An interface is a named set of method signatures — a behavioural contract.
How does a type satisfy an interface in Go?
- With an implements keyword
- By inheriting it
- Implicitly, by having the methods
- By registering it
Answer: Implicitly, by having the methods. Satisfaction is implicit: a type satisfies an interface simply by defining the required methods.
What does the empty interface interface{} (or any) accept?
- Only structs
- Only pointers
- Nothing
- Any value of any type
Answer: Any value of any type. interface{} / any has no method requirements, so every type satisfies it.
Which form safely extracts a concrete type from an interface value?
- v := i.(T)
- v, ok := i.(T)
- v := T(i)
- v := i.T
Answer: v, ok := i.(T). The comma-ok type assertion v, ok := i.(T) returns ok=false instead of panicking on a mismatch.
What does a type switch let you do?
- Convert numbers
- Branch on the dynamic type of an interface value
- Sort a slice
- Allocate memory
Answer: Branch on the dynamic type of an interface value. A type switch (switch v := i.(type)) branches based on the value's concrete type.
Can a []Shape slice hold different concrete types at once?
- No, only one type
- Yes, any type that satisfies Shape
- Only if they are pointers
- Only structs
Answer: Yes, any type that satisfies Shape. An interface slice can hold any mix of concrete types that satisfy the interface.
Which standard interface customises how fmt prints a type?
- fmt.Printer
- fmt.Stringer
- fmt.Formatter only
- io.Writer
Answer: fmt.Stringer. Implementing fmt.Stringer's String() string method customises how fmt prints the value.
What is the zero value of an interface variable?
- 0
- An empty struct
- nil
- false
Answer: nil. An interface that holds no value is nil.
Why are interfaces useful for decoupling code?
- They make code run faster
- Callers depend on behaviour, not concrete types
- They reduce memory
- They add inheritance
Answer: Callers depend on behaviour, not concrete types. Functions accept interfaces, so any type with the right behaviour works — decoupling caller from implementation.
Does Go have an explicit 'implements' keyword?
- Yes
- Only for structs
- No
- Only with generics
Answer: No. Go has no implements keyword; interface satisfaction is structural and implicit.