Go generate code generation

Go code generation is handled by the `//go:generate` directive, which allows you to define shell commands that run via `go generate` to create source files from templates or data.

Go code generation is handled by the //go:generate directive, which allows you to define shell commands that run via go generate to create source files from templates or data. These generated files are treated as regular Go source code, but the build system ignores them unless explicitly created, keeping your repository clean of auto-generated artifacts.

You place the directive at the top of a .go file (usually a _test.go or a dedicated generate.go file) to ensure it runs in the correct package context. The command following the directive is executed in the directory containing the file, making it ideal for generating protobufs, mock interfaces, or constant values.

Here is a practical example generating a constant file from a text file:

// main.go
package main

//go:generate sh -c "echo 'const Version = \"1.0.0\"' > version_generated.go"

func main() {
	// This will fail to compile if version_generated.go doesn't exist
	println(Version) 
}

Running go generate in the directory creates version_generated.go. If you omit the file, go build will fail because Version is undefined, enforcing that generation happens before compilation.

For more complex scenarios, like generating mocks for interfaces, you typically use external tools. Here is how you might generate a mock using mockery:

// interface.go
package service

//go:generate mockery -name=UserStore -output=./mocks -outpkg=mocks

type UserStore interface {
	GetUser(id string) (*User, error)
}

Running go generate executes mockery, creating mocks/mock_user_store.go in the mocks subdirectory. Note that go generate does not automatically run during go build or go test; you must run it manually or via a Makefile/CI step. This separation prevents accidental regeneration of code during standard builds and ensures generated code is versioned in your repository.

Always verify that generated files are committed to version control. If you rely on go generate to create code required for compilation, failing to commit the output will break builds for other developers who haven't run the generation step. To keep your workflow smooth, add a make generate target that runs go generate ./... and ensures all generated files are up to date before committing.