Internal packages
Use `internal/` to enforce non-public package boundaries inside a repo when code should not be imported externally.
Canonical guidance
- use
internal/when the compiler should enforce that a package is not public API - keep package boundaries meaningful;
internal/does not replace good package design - prefer a few coherent internal packages over many tiny hidden ones
Use when
- shared code for multiple commands in one repo
- unstable implementation details
- non-public adapters or wiring packages
Avoid
- putting broadly reusable libraries under
internal/ - adding
internal/just to hide unclear architecture - scattering one-off helper packages everywhere
Preferred pattern
repo/
internal/
authz/
config/
cmd/api/
cmd/worker/
Anti-pattern
- copying the same code into several public packages because a useful shared package was hidden under the wrong
internal/boundary
Explanation: This anti-pattern is tempting because hiding code feels safer, but a bad boundary creates duplication instead of clarity.
Why
internal/gives compiler-enforced API boundaries inside a repository
Related pages
Sources
- Organizing Go code - Andrew Gerrand
- go command - Go Team