Interface — defines behavior through method signatures, enabling polymorphism. Struct — defines data through named, typed 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 Reader interface {2 Read(p []byte) (int, error)3}45type File struct{ Name string }6func (f *File) Read(p []byte) (int, error) {7 // read from file8 return 0, nil9}1011func process(r Reader) error {12 buf := make([]byte, 1024)13 _, err := r.Read(buf)14 return err15}
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 Config struct {2 Host string3 Port int4}56type Server struct {7 Config // embed struct for composition8 Name string9}
When to use:
Common mistakes:
any (empty interface) — loses type safety.