Generated Code
Anvil writes ordinary Go into the configured output file.
generator: output: ./internal/anvil/anvil_autogenerated.go package: anvilgenGenerated files are compiler output. The next anvil generate run overwrites
the configured output file.
What The File Contains
Section titled “What The File Contains”Depending on the protocols present in the project, generated code can include:
- Component structs used by generated wiring
- Provider registration
- Provider resolution calls
- Cycle-safe dependency graph construction
- HTTP route registration
- WebSocket route registration
- Request binding functions
- Request validation functions
- Request-level
Validate(ctx sdk.Ctx) errorcalls - Middleware chain construction
- Service registration metadata for gRPC
- GraphQL endpoint registration metadata
- Queue job registration metadata
- Optional package self-registration through
init
Generated code uses readable function names and comments around major sections so a developer can debug it without learning compiler internals.
The generated file starts with // Code generated by anvil; DO NOT EDIT. and
then exposes two important entrypoints:
func init() { anvil.RegisterWiring(Wiring())}
func Wiring() anvil.WiringFuncThe init function supports blank-import wiring. Wiring() supports explicit
wiring.
anvil.RegisterWiring returns a cleanup function for tests, but generated
packages intentionally ignore it. A generated package self-registers when it is
imported, then app.Wire() consumes the registered wiring functions. If
application code passes explicit wiring functions to app.Wire(...), only
those functions run.
app.Wire() takes a snapshot of the registered wiring functions at the time it
runs. Calling app.Wire(anvilgen.Wiring()) bypasses the package-level registry
and executes only the supplied function. Passing a nil wiring function returns
an error, and calling Wire twice returns anvil.ErrAlreadyWired.
The generated boot function follows the same shape in every generated package:
- Register generated DI providers.
- Resolve the protocol transports from
*anvil.WireContext. - Resolve generated components from DI.
- Register HTTP, WebSocket, gRPC, GraphQL, and queue metadata with drivers.
If a project has no routes for one protocol, that protocol registration section can be empty or absent. Generated code wires metadata; drivers execute requests.
Generated files name the provider registration section
registerHTTPProviders. That function registers all generated component
constructors in the package, not only HTTP controllers. In a mixed package it
can install middleware, GraphQL endpoints, gRPC services, queue jobs, bundles,
and HTTP controllers before any protocol metadata is registered.
The generated Go file does not embed the route manifest JSON. Tooling reads the
same compiler model through anvil manifest, anvil openapi, and
anvil testbed. That keeps runtime wiring focused on application startup while
tooling keeps its own deterministic output.
Application Code
Section titled “Application Code”Hand-written code registers dependencies through the public app/provider API. Generated provider keys are compiler output and can move when source changes.
Register hand-written dependencies through the public app/provider API:
app := anvil.New(driver, anvil.WithProviders( anvil.As[project.Store](project.NewPostgresStore(db)), anvil.Named[project.Store]("audit", auditStore), ),)Use named providers when two dependencies have the same Go type but different roles.
Provider key variables in generated code are for generated wiring only. The key string is based on Go package, type name, and optional provider name, but the variable names and grouping are compiler output. Treat them like any other generated implementation detail.
Explicit Wiring
Section titled “Explicit Wiring”Explicit wiring keeps generated modules visible at the call site:
import "example.com/portal/internal/anvilgen"
if err := app.Wire(anvilgen.Wiring()); err != nil { return err}This is the best default for tests and applications with multiple generated modules.
Blank Import Wiring
Section titled “Blank Import Wiring”Generated packages can self-register:
import _ "example.com/portal/internal/anvilgen"
if err := app.Wire(); err != nil { return err}Use this when the app shell intentionally wants generated modules to register through package initialization.
Debugging A Route
Section titled “Debugging A Route”When a route behaves incorrectly:
- Run
anvil generate. - Open the generated file.
- Search for the controller and endpoint name.
- Inspect the generated route registration.
- Inspect the generated request binder.
- Inspect the generated validation function.
- Inspect the middleware chain around the handler.
- Compare the route with
anvil manifest.
If the generated code is difficult to read, that is an Anvil bug. Generated code is part of the developer experience.
Determinism
Section titled “Determinism”With identical source, config, and Go toolchain inputs, generated code stays stable. Stable output keeps code review meaningful and makes generated-file diffs useful.
Deterministic output makes generated diffs reviewable when route tables, request models, middleware, providers, or config change.