Section 9 of 11
Packages, imports & layout
A package is a directory. Capitalization is the access modifier.
myapp/
go.mod module github.com/me/myapp
cmd/server/main.go -> go build ./cmd/server -> ./server
cmd/migrate/main.go -> go build ./cmd/migrate -> ./migrate
internal/store/store.go COMPILER-ENFORCED private to this module
pkg/ optional, public, often skipped- A package == a directory. Every .go file in it declares the same package name. No splitting a package across dirs.
- Any package named main with a func main() compiles to one binary — one module can produce several.
- internal/ is a hardcoded rule in the toolchain, not a convention: only code rooted at its parent may import it.
- NO circular imports. The compiler rejects them outright, which forces your dependency graph to be a DAG.
- Unused imports are compile errors. goimports (on save) manages them for you.
- import _ "net/http/pprof" is a blank import: run its init() for the side effect only.
- Inside a package everything sees everything; capitalization only gates access ACROSS packages.
- http.ListenAndServe is a package qualifier + function — Go has no statics because package-level funcs already are that.
Capitalization, structs, and the stdlib as namespace
go.dev playground
Try it: Rename Name to name and the json output loses the field — encoding/json can only see exported fields.