Overview
go generate scans source files for //go:generate <command> comments and runs them —
nothing more. It is never invoked by go build; generation is an explicit developer step
whose output is committed to version control. That deliberate dumbness is the point: no
build-time magic, no hidden classpath scanning, just checked-in Go code anyone can read.
Key points
- A directive is a comment:
//go:generate stringer -type=Statusplaced near the declaration it serves;go generate ./...runs all of them in file order. The command gets$GOFILE,$GOPACKAGE,$GOLINEin its environment. - The usual suspects:
stringer(String() for enums),mockgen/moq(interface mocks),sqlc(type-safe code from SQL),protoc/buf(protobuf/gRPC stubs),oapi-codegen(OpenAPI handlers). - Generation beats reflection: where Java reaches for annotation processing or runtime
reflection (see javac annotation processing), Go generates
plain code ahead of time — greppable, debuggable, no runtime cost, no framework
classloader tricks.
encoding/jsonis the notable stdlib exception that pays the reflection tax. - Commit the output: generated files (conventionally
*_gen.goor a// Code generated … DO NOT EDIT.header) go into VCS, sogo buildandgo installwork from a bare clone with no generators installed. CI re-runs generate and fails on diff to catch drift. - Pin generator versions: since 1.24 a
tooldirective ingo.modtracks tool dependencies (go get -tool); before that, thetools.goblank-import pattern. Either way the generator's version is reproducible. - Not a build system: no dependency tracking, no caching, no ordering guarantees across packages — for anything complex, drive generators from make or the build pipeline instead.
Examples
//go:generate stringer -type=State -trimprefix=State
type State int
go generate ./... && git diff --exit-code # CI drift check
Related
- The Go toolchain — parent catalog.
- javac — the annotation-processing model this contrasts with.
- go build, go run, go install — builds consume the committed output, never the generators.
- gRPC in Go — the heaviest everyday user of generated code.