What does go generate do, and what's a common use case?

4 minintermediategogo-generatecode-generationtooling

Quick Answer

go generate scans source files for specially formatted comments (//go:generate <command>) and runs each one as a shell command, letting you check in generated code alongside hand-written code without wiring generation into go build itself — go generate is a separate, explicit step you run on purpose, never automatically as part of a normal build. Common use cases: generating String() methods for enum-like iota constants (stringer), generating mock implementations of interfaces for testing (mockgen), generating code from a protobuf schema, or generating boilerplate for repetitive patterns the type system can't express directly (since Go, even with generics, still can't express everything through the type system alone).

Detailed Answer

go generate is deliberately simple: it just finds specially marked comments and runs whatever command follows them.

The basic mechanism

//go:generate stringer -type=Status

type Status int

const (
    Pending Status = iota
    Active
    Closed
)
go generate ./...

This runs stringer -type=Status for every file containing that comment, which generates a new file (typically status_string.go) implementing a String() method for Status, so fmt.Println(Active) prints "Active" instead of just 1.

Generating mocks for testing

//go:generate mockgen -source=service.go -destination=mocks/service_mock.go

type Service interface {
    GetUser(id int) (*User, error)
}
go generate ./...

This produces a mock implementation of Service you can use in tests to simulate specific return values or errors, without hand-writing a mock struct that has to stay in sync with the interface manually.

Why it's a separate, manual step

go build ./...      # never triggers go:generate comments automatically
go generate ./...   # runs them explicitly, only when you ask

This is deliberate: generated code is usually checked into version control like any other source file, and running generators automatically on every build would make builds slower, less predictable, and dependent on every generator tool being installed on every machine that builds the project. go generate is typically run once, after changing whatever the generator reads from, with the resulting generated file committed alongside the change.

The practical takeaway

go generate isn't magic. It's a thin, generic convention for "run this command to produce this file," used heavily for stringer-style enum methods, mock generation, and protobuf/gRPC code generation in real Go projects.

Related Resources