Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
The command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
File Explorer
5 files
Showing SKILL.md
SKILL.md
Source instructions · Read-only preview
name
golang-google-wire
description
Compile-time dependency injection in Golang using google/wire — wire.NewSet, wire.Build, wire.Bind (interface→concrete), wire.Struct, wire.Value, wire.InterfaceValue, wire.FieldsOf, cleanup functions, //go:build wireinject injector files, and generated wire_gen.go. Apply when using or adopting google/wire, when the codebase imports `github.com/google/wire`, or when wiring an application graph at compile time via `wire.Build`. For runtime DI with reflection, see `samber/cc-skills-golang@golang-uber-dig` skill.
user-invocable
true
license
MIT
compatibility
Designed for Claude Code or similar AI coding agents, and for projects using Golang.
Persona: You are a Go architect using wire for compile-time DI. You let the compiler catch missing dependencies, treat wire_gen.go as committed source, and re-run wire ./... after every graph change.
Dependencies:
wire: go install github.com/google/wire/cmd/wire@latest
Using google/wire for Compile-Time Dependency Injection in Go
Code-generation DI toolkit. Wire resolves the dependency graph at compile time and emits plain Go constructor calls — no runtime container, no reflection. Errors appear when you run wire ./..., not at first request.
Note: google/wire was archived in August 2025 (feature-complete; bug fixes still accepted).
This skill is not exhaustive. Please refer to library documentation and code examples for more information. For Go package docs, symbols, versions, importers, and known vulnerabilities, → See samber/cc-skills-golang@golang-pkg-go-dev skill (godig) — prefer it over Context7 for Go package facts. To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See samber/cc-skills-golang@golang-gopls skill (gopls). Context7 remains a fallback for docs not indexed on pkg.go.dev.
go get -tool github.com/google/wire/cmd/wire@latest
go get github.com/google/wire
wire vs. Runtime DI
Concern
wire
dig / fx / samber/do
Resolution
Compile time (codegen)
Runtime (reflection)
Error detection
wire ./... fails
First Invoke/startup
Runtime container
None — plain Go calls
Present
Lifecycle hooks
Not built in
fx: OnStart/OnStop
Generated files
wire_gen.go (committed)
None
For lifecycle, lazy loading, and a full matrix see samber/cc-skills-golang@golang-dependency-injection.
Providers
A provider is any Go function — inputs are dependencies, outputs are provided types. Three return forms:
Keep sets small: library sets expose a stable surface (adding inputs or removing outputs breaks downstream injectors). One set per package is a useful default.
Injectors and //go:build wireinject
The injector file declares the initialization function. Wire generates its body into wire_gen.go and replaces the stub.
//go:build wireinjectpackage main
import"github.com/google/wire"// Wire generates the body of this function.funcInitApp() (*App, func(), error) {
wire.Build(InfraSet, ServiceSet, NewApp)
returnnil, nil, nil// replaced by codegen
}
The //go:build wireinject tag prevents the stub from being compiled into the binary — only wire_gen.go (which has no such tag) makes it through go build. Without this tag, both files define the same function, causing a compile error.
Alternative syntax when a dummy return is inconvenient:
Wire forbids implicit interface satisfaction — you must declare bindings explicitly so the graph is unambiguous when multiple types implement the same interface.
var Set = wire.NewSet(
NewPostgresUserRepo,
wire.Bind(new(UserStore), new(*PostgresUserRepo)), // tell wire: *PostgresUserRepo satisfies UserStore
)
Explicit bindings prevent graph breakage when a new type implementing the same interface is added elsewhere.
Struct Providers and Values
wire.Struct fills struct fields from the graph without a manual constructor. Tag fields wire:"-" to exclude them.
wire.Struct(new(Server), "Logger", "DB") // inject named fields
wire.Struct(new(Server), "*") // inject all non-excluded fields
wire.Value(Foo{X: 42}) // constant expression (no fn calls / channels)
wire.InterfaceValue(new(io.Reader), os.Stdin) // interface-typed literal
wire.FieldsOf(new(Config), "DSN", "Addr") // promote struct fields as graph nodes
See advanced.md for the wire:"-" exclusion tag and wire.FieldsOf details.
Disambiguating Duplicate Types
Wire forbids two providers for the same type. Wrap the underlying type in distinct named types so each has exactly one provider:
Wire generates wire_gen.go (plain Go, committed, DO NOT EDIT). For a full example with per-package sets, cleanup-heavy graphs, and generated output, see recipes.md.
Codegen Workflow
wire ./... # regenerate all injectors in the module
wire check ./... # validate graph without regenerating (fast CI check)
Run wire ./... after every constructor signature change. Add //go:generate go run github.com/google/wire/cmd/wire to injector files so go generate ./... also works. Commit wire_gen.go — it must stay in sync for CI builds.
Best Practices
Never edit wire_gen.go — it is overwritten on every wire ./... run. Treat it as a build artifact that happens to be committed; source of truth is the provider and injector files.
Always add //go:build wireinject to injector files — omitting it causes duplicate-symbol compile errors because both the stub and the generated file define the same function.
Use named types to distinguish values of the same underlying type — wire enforces one provider per type; named types like type DSN string let you have PrimaryDSN and ReplicaDSN coexist.
Keep library provider sets minimal and backward-compatible — adding new required inputs breaks downstream injectors; removing outputs does too. Introduce only newly-created types in the same release.
Return (T, func(), error) from cleanup providers and let wire chain them — wire generates the correct reverse-order cleanup and handles partial failures (if construction fails midway, only already-built cleanups run).
Keep injector files focused — one function per file, one package import at a time. Fat injectors with dozens of wire.Build arguments are hard to reason about; delegate to per-package sets.
Common Mistakes
Mistake
Fix
Editing wire_gen.go manually
Never edit it. Change providers or injectors and re-run wire ./....
Missing //go:build wireinject
Add the tag as the very first line of every injector file.
Two providers returning *sql.DB
Wrap with a named struct type: type PrimaryDB struct { *sql.DB } — Wire does not distinguish pointer type aliases.
Injecting an interface without wire.Bind
Add wire.Bind(new(MyInterface), new(*MyImpl)) to the provider set.
Forgetting to re-run wire ./... after changes
Run wire before go build; add it to go generate or a Makefile target.
Calling cleanup() without guarding for nil
Wire returns nil cleanup on construction error; guard with if cleanup != nil { defer cleanup() }.
Testing
Wire generates plain Go constructors, so unit tests use manual injection — no container to clone or reset. For testing patterns (test injectors swapping real providers for fakes, CI stale-check for wire_gen.go), see testing.md.