Use interfaces to define behavior contracts between packages and packages to group related implementation details. Interfaces enable loose coupling by allowing different packages to implement the same contract without knowing each other's internal structure, while packages provide namespace organization and encapsulation for code that must be compiled together.
// Define contract in one package
type Reader interface {
Read(p []byte) (n int, err error)
}
// Implement contract in another package
type File struct{}
func (f *File) Read(p []byte) (int, error) { /* ... */ }