How does go generate work, and what are best practices around it?
Question 425MediumGo 1.22 to 1.25
go generate scans source files for //go:generate command args lines (no space after //) and runs the commands with the package directory as the working directory. It is never run by go build or go test. It is a manual, author-side step, and the generated files are committed so that consumers can go get without the tools.
package color
//go:generate go tool stringer -type=Color -trimprefix=Color
//go:generate go run ./gen -out=table_gen.go
type Color int
const (
ColorRed Color = iota
ColorGreen
)
Available environment variables: $GOFILE, $GOPACKAGE, $GOLINE, $GOARCH, $GOOS, $DOLLAR. Commands run in the order they appear in files, and files are processed in sorted order. Useful flags are -run regexp and -n/-x.
Best practices:
- Generated files should start with
// Code generated ... DO NOT EDIT., which linters, gopls and code review tools recognize. - Pin generator versions (with the tool directive or
go run pkg@v). - In CI, run
go generate ./... && git diff --exit-codeto catch stale output. - Consider generics before code generation. Many stringer/mock/collection use cases no longer need it.
More on Modules, Packages & Tooling
- Q423Explain build constraints: the //go:build syntax, filename rules, and common gotchas.
- Q424How would you separate integration tests from unit tests using build tags? What alternatives exist?
- Q426What are the tradeoffs of using cgo? When would you avoid it?
- Q427What are the cgo pointer-passing rules, and how does runtime.Pinner help?
- Q428How do you cross-compile Go and produce a fully static binary for a scratch container?
- Q429How do you inject a version string at build time with -ldflags? What does this program print?