Go interfaces are satisfied implicitly — a type implements an
interface just by having the right methods. No implements keyword
needed. This makes Go interfaces uniquely flexible and composable.
Defining an Interface
type Writer interface {
Write(p []byte) (n int, err error)
}This says: "anything that has a Write method with this signature is
a Writer."
Implicit Satisfaction
type Logger struct {
prefix string
}
func (l Logger) Write(p []byte) (n int, err error) {
fmt.Printf("[%s] %s\n", l.prefix, string(p))
return len(p), nil
}
// Logger implements Writer WITHOUT declaring it
var w Writer = Logger{prefix: "APP"}This is the key insight: types satisfy interfaces just by having the right methods. No inheritance, no declaration, no keywords.
Interface Composition
Combine small interfaces into larger ones:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}Go's standard library uses this pattern extensively — io.ReadWriter,
io.ReadCloser, etc.
Empty Interface
interface{} (or any in Go 1.18+) accepts any type:
func printAny(v any) {
fmt.Printf("%v (%T)\n", v, v)
}
printAny(42) // 42 (int)
printAny("hello") // hello (string)
printAny(true) // true (bool)Use sparingly — it defeats the purpose of static typing.
Why Interfaces Matter
Interfaces let you write functions that accept behaviour rather than concrete types:
func process(w Writer) error {
_, err := w.Write([]byte("hello"))
return err
}This function works with Logger, File, Buffer, or anything else
that implements Write.
The io.Reader Pattern
Go's most famous interface — just one method:
type Reader interface {
Read(p []byte) (n int, err error)
}Files, HTTP responses, buffers, gzip readers — anything that produces
bytes implements io.Reader. This is how Go achieves its remarkable
composability.
Tips
- Keep interfaces small — 1-3 methods is ideal.
- Accept interfaces, return structs.
- Use
anysparingly — prefer specific types. - Go interfaces are about behaviour, not hierarchy.
Next: concurrency — goroutines and channels.