Put a Go package under an `internal` directory when the application needs to import it but outside code should not. The directory name enforces an import boundary: code outside its permitted parent directory tree cannot import packages inside it. An exported name does not bypass that boundary. section 8.2.1
This service keeps its HTTP API definitions and handlers under `internal/`, while `main.go` at the module root imports the handlers to start the server. section 8.2.1
The same layout works for a command-line tool: keep `main.go` at the root and place its implementation in `internal/solver`. The root program can call the solver’s exported `New`, `Solve`, and `SaveSolution` functions and methods without making the package available to outside importers. section 9.2.3 section 9.2.1
Use the boundary for implementation code, not as a substitute for deciding what each package should expose. Service domain types commonly belong under `internal/`; HTTP response types serve the endpoint handlers, while the rest of the service uses domain types. Unlike `internal/`, `testdata/` is skipped by Go build and test commands. section 8.7
