04 — Interfaces
Describing behaviour abstractly: interfaces, implicit satisfaction, the any
type, and recovering a concrete type safely with a type switch. Every example is live —
edit it and press Run.
1. Interfaces are satisfied implicitly
An interface lists methods. A type satisfies it just by having
those methods — there's no implements keyword and no declared link.
Here both Dog and Cat satisfy Speaker simply by
having a Speak() method, so you can treat them uniformly through the
interface:
package main
import "fmt"
type Speaker interface {
Speak() string
}
type Dog struct{}
type Cat struct{}
func (Dog) Speak() string { return "Woof" } // Dog now satisfies Speaker
func (Cat) Speak() string { return "Meow" } // so does Cat
func AllSounds(ss []Speaker) []string {
out := make([]string, len(ss))
for i, s := range ss {
out[i] = s.Speak() // dispatches to the concrete type
}
return out
}
func main() {
fmt.Println(AllSounds([]Speaker{Dog{}, Cat{}, Dog{}}))
}
Output:
[Woof Meow Woof]
2. any and the type switch
any (an alias for interface{}) holds a value of any type —
like C's void *, but it remembers the concrete type, so you recover it
safely. A type switch branches on what's really inside. Order matters:
a value takes the first matching case, so list concrete types before a broader interface
case.
package main
import "fmt"
type Speaker interface{ Speak() string }
type Dog struct{}
func (Dog) Speak() string { return "Woof" }
func Describe(x any) string {
switch v := x.(type) {
case int:
return fmt.Sprintf("int: %d", v)
case string:
return fmt.Sprintf("string: %s", v)
case Speaker: // checked after the concrete cases
return fmt.Sprintf("speaker: %s", v.Speak())
default:
return "unknown"
}
}
func main() {
fmt.Println(Describe(42))
fmt.Println(Describe("hi"))
fmt.Println(Describe(Dog{}))
fmt.Println(Describe(3.14))
}
Output:
int: 42
string: hi
speaker: Woof
unknown
For a single type, use the comma-ok assertion instead:
n, ok := x.(int) — ok is false on a mismatch and it never
panics.
Recap
| Concept | In Go |
|---|---|
| Interface | A set of methods; any type with them satisfies it |
| Satisfaction | Implicit, structural — no implements |
any | interface{}; holds anything, remembers its type |
| Safe recovery | Comma-ok v, ok := x.(T) |
| Branch on type | Type switch; first matching case wins |
Next: 05 — Errors.