Interface — abstracts behavior by listing method signatures without implementation. Struct — defines concrete data with named, typed fields.
Go interfaces are satisfied implicitly: if your type has all the methods, it satisfies the interface — no declaration needed. This enables loose coupling. For example, io.Reader is satisfied by files, network connections, HTTP response bodies, and more.
1type Reader interface {2 Read(p []byte) (n int, err error)3}45// os.File, *strings.Reader, *bytes.Buffer all satisfy Reader6func process(r Reader) error {7 buf := make([]byte, 1024)8 _, err := r.Read(buf)9 return err10}
Structs hold real data and can have methods. You compose structs from other structs (embedding) for reuse. Structs are the concrete types that implement interfaces.
1type Config struct {2 Host string3 Port int4}56func (c Config) Address() string {7 return fmt.Sprintf("%s:%d", c.Host, c.Port)8}910type Server struct {11 Config // embed struct for composition12 Name string13}
When to use:
Common mistakes:
err == nil after an interface assignment — interface nil checks are tricky if the interface holds a typed nil pointer.