Interface — defines behavior through method signatures, enabling polymorphism. Struct — defines data through named fields, providing concrete implementations.
In Go, interfaces are satisfied implicitly — any type that has the right methods automatically satisfies the interface. This means you can add new implementations without touching the interface definition.
1type Logger interface {2 Log(message string)3}45type ConsoleLogger struct{ Prefix string }6func (l ConsoleLogger) Log(msg string) {7 fmt.Printf("[%s] %s\n", l.Prefix, msg)8}910func process(log Logger) {11 log.Log("starting...") // depends on interface, not concrete type12}
Structs are the building blocks — they hold data and have methods. You can embed structs for composition (similar to inheritance). Structs are concrete, typed, and compile-time checked.
1type Base struct{ ID int }2type User struct {3 Base // embed for ID field4 Name string5}
When to use:
Common mistakes:
any (empty interface) — loses type safety.