go-google-wire
Compile-time dependency injection with google/wire. Covers provider sets, injectors, and code generation.
SKILL.mdskills/go/go-google-wire/SKILL.md
GitHubCore Principles
Wire is a code generator that automates the "manual" dependency injection you would otherwise write in main(). It has no runtime overhead and no reflection.
Workflow
- Write Providers (functions that return a value and its dependencies).
- Group them into Provider Sets.
- Create an Injector file with a
//go:build wireinjecttag. - Run
wireto generatewire_gen.go.
Best Practices
- Commit
wire_gen.go— Treat it as a standard source file. It must be in sync with your providers for the code to compile. - Use Build Tags — Always put
//go:build wireinjectat the top of your injector files (e.g.,wire.go) to prevent them from being included in the final binary. - Explicit Interface Binding — Use
wire.Bindto tell Wire which concrete type satisfies an interface. Wire does not perform implicit interface satisfaction. - Cleanup Functions — Providers can return a cleanup function (e.g.,
func()) which Wire will automatically chain in the correct reverse order. - Named Types for Duplicates — If you have two dependencies of the same type (e.g., two
*sql.DBconnections), wrap them in distinct named types (e.g.,type PrimaryDB *sql.DB).
Code Example: Provider and Set
// infra/db.go
func NewDB(cfg *Config) (*sql.DB, func(), error) {
db, _ := sql.Open("postgres", cfg.DSN)
cleanup := func() { db.Close() }
return db, cleanup, nil
}
var Set = wire.NewSet(NewDB, NewConfig)
Code Example: Injector (wire.go)
//go:build wireinject
package main
import "github.com/google/wire"
func InitializeApp() (*App, func(), error) {
wire.Build(infra.Set, service.Set, NewApp)
return nil, nil, nil
}
Running Wire
go install github.com/google/wire/cmd/wire@latest
wire ./...
Why Wire?
- Type Safety: The compiler catches missing or circular dependencies.
- Performance: Zero runtime overhead.
- Testability: No global state or magic containers; just plain Go functions.
- Maintainability: The generated
wire_gen.goshows exactly how your application is wired.
Anti-patterns
- ❌ Editing
wire_gen.go— Your changes will be overwritten. Edit the providers or the injector instead. - ❌ Missing Build Tag — Forgetting
//go:build wireinjectcauses "duplicate function" errors duringgo build. - ❌ Fat Injectors — Putting dozens of providers directly in
wire.Build. Usewire.NewSetto group them by package/layer. - ❌ Implicit Interfaces — Hoping Wire will guess which struct implements an interface. Use
wire.Bind. - ❌ Circular Dependencies — Wire will error out, but this usually indicates a deeper design flaw that needs refactoring.