Loading...
Loading...
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.
npx skill4agent add samber/cc-skills-golang golang-google-wirewire_gen.gowire ./...wire ./...google/wirego install github.com/google/wire/cmd/wire@latest
go get github.com/google/wire| Concern | wire | dig / fx / samber/do |
|---|---|---|
| Resolution | Compile time (codegen) | Runtime (reflection) |
| Error detection | | First |
| Runtime container | None — plain Go calls | Present |
| Lifecycle hooks | Not built in | fx: OnStart/OnStop |
| Generated files | | None |
samber/cc-skills-golang@golang-dependency-injectionfunc NewConfig() *Config { return &Config{Addr: ":8080"} }
func NewDB(cfg *Config) (*sql.DB, error) { return sql.Open("postgres", cfg.DSN) }
func NewRedis(cfg *Config) (*redis.Client, func(), error) { // cleanup chained in reverse order
c := redis.NewClient(&redis.Options{Addr: cfg.RedisAddr})
return c, func() { c.Close() }, nil
}wire.NewSet// infra/wire.go
var InfraSet = wire.NewSet(
NewConfig,
NewDB,
NewRedis,
)
// service/wire.go
var ServiceSet = wire.NewSet(
NewUserRepo,
NewUserService,
wire.Bind(new(UserStore), new(*UserRepo)), // interface binding
)//go:build wireinjectwire_gen.go//go:build wireinject
package main
import "github.com/google/wire"
// Wire generates the body of this function.
func InitApp() (*App, func(), error) {
wire.Build(InfraSet, ServiceSet, NewApp)
return nil, nil, nil // replaced by codegen
}//go:build wireinjectwire_gen.gogo buildfunc InitApp() (*App, func(), error) {
panic(wire.Build(InfraSet, ServiceSet, NewApp))
}var Set = wire.NewSet(
NewPostgresUserRepo,
wire.Bind(new(UserStore), new(*PostgresUserRepo)), // tell wire: *PostgresUserRepo satisfies UserStore
)wire.Structwire:"-"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 nodeswire:"-"wire.FieldsOftype PrimaryDSN string
type ReplicaDSN string// wire.go — injector, excluded from binary via build tag
//go:build wireinject
package main
func InitApp() (*App, func(), error) {
wire.Build(config.ConfigSet, infra.InfraSet, service.ServiceSet, NewApp)
return nil, nil, nil
}
// main.go
func main() {
app, cleanup, err := InitApp()
if err != nil { log.Fatal(err) }
defer cleanup()
app.Run()
}wire_gen.gowire ./... # regenerate all injectors in the module
wire check ./... # validate graph without regenerating (fast CI check)wire ./...//go:generate go run github.com/google/wire/cmd/wirego generate ./...wire_gen.gowire_gen.gowire ./...//go:build wireinjecttype DSN stringPrimaryDSNReplicaDSN(T, func(), error)wire.Build| Mistake | Fix |
|---|---|
Editing | Never edit it. Change providers or injectors and re-run |
Missing | Add the tag as the very first line of every injector file. |
Two providers returning | Wrap with named types ( |
Injecting an interface without | Add |
Forgetting to re-run | Run wire before |
Calling | Wire returns nil cleanup on construction error; guard with |
wire_gen.gosamber/cc-skills-golang@golang-dependency-injectionsamber/cc-skills-golang@golang-uber-digsamber/cc-skills-golang@golang-uber-fxsamber/cc-skills-golang@golang-samber-dosamber/cc-skills-golang@golang-structs-interfacessamber/cc-skills-golang@golang-testing