fabianoflorentino/golang-agent-skills

golang-google-wire

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…

Ver código fuente
Documento original del Skill

Contenido del repositorio de origen con títulos, ejemplos, código, tablas, enlaces e imágenes preservados.

Persona: You are a Go architect using wire for compile-time DI. You let the compiler find 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

When to use: any task centered on google/wire. Runtime containers with lifecycle and modularity are golang-uber-dig / golang-uber-fx; the concept-level comparison lives in golang-dependency-injection. Note that google/wire was archived in August 2025 — feature-complete, with bug fixes still accepted.

How it differs from runtime DI

wiredig / fx / samber/do
Resolutioncompile-time codegenruntime reflection/generics
Failure timingwire ./... errors nowfirst Invoke / startup
Runtime containernone — plain Go callspresent
Lifecycle hooksnone built infx: OnStart/OnStop
Generated filewire_gen.go, committednone

The payoff: the whole graph either builds or the tool tells you exactly which dependency is missing.

Providers and sets

A provider is any function whose parameters are dependencies and whose results are provided types. It may return a value, (value, error), or (value, cleanup, error):

go
func 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) {
    c := redis.NewClient(&redis.Options{Addr: cfg.RedisAddr})
    return c, func() { c.Close() }, nil
}

wire.NewSet bundles providers for reuse and may reference other sets:

go
var InfraSet = wire.NewSet(NewConfig, NewDB, NewRedis)
var ServiceSet = wire.NewSet(NewUserRepo, NewUserService,
    wire.Bind(new(UserStore), new(*UserRepo)),
)

Keep sets stable — library sets are a contract; adding inputs or removing outputs breaks downstream injectors. One set per package is a sane default.

Injector files and //go:build wireinject

The injector file declares the function wire will generate the body for:

go
//go:build wireinject

package main

import "github.com/google/wire"

func InitApp() (*App, func(), error) {
    wire.Build(InfraSet, ServiceSet, NewApp)
    return nil, nil, nil // replaced by codegen
}

The build tag keeps the stub out of the binary — only the untagged wire_gen.go compiles. Drop the tag and both files define the same function (a duplicate-symbol error). If the dummy returns annoy you, panic(wire.Build(...)) works too.

Run wire ./... after every constructor-signature change; wire check ./... validates without regenerating (cheap for CI). Add //go:generate go run github.com/google/wire/cmd/wire so go generate ./... covers it, and commit wire_gen.go.

Interface bindings

Wire refuses to infer interface satisfaction — you must declare it, so a new implementor elsewhere can't silently make the graph ambiguous:

go
wire.Bind(new(UserStore), new(*PostgresUserRepo))

Structs, values, fields

  • wire.Struct(new(Server), "Logger", "DB") fills named fields from the graph ("*" fills all non-wire:"-" fields).
  • wire.Value(Foo{X: 42}) supplies a constant (no calls or channels).
  • wire.InterfaceValue(new(io.Reader), os.Stdin) supplies an interface-typed literal.
  • wire.FieldsOf(new(Config), "DSN") promotes a field as a graph node.

See advanced for the wire:"-" tag and field promotion details.

Duplicate types

One provider per type, strictly. Disambiguate with named types rather than two functions returning *sql.DB:

go
type PrimaryDSN string
type ReplicaDSN string

Cleanup chains

Cleanup providers return (T, func(), error); wire chains them in reverse order and, if construction fails midway, runs only the cleanups already built. In main, guard the cleanup against nil:

go
app, cleanup, err := InitApp()
if err != nil {
    log.Fatal(err)
}
if cleanup != nil {
    defer cleanup()
}

Full shape

go
//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()
}

A complete decorated example with per-package sets and cleanup-heavy graphs: recipes.

Best practices

  1. Never hand-edit wire_gen.go; it is a committed build artifact.
  2. Build-tag every injector file, first line, or suffers duplicate symbols.
  3. Named types over raw types for same-underlying duplicates.
  4. Keep library sets additive and backward-compatible.
  5. Return (T, func(), error) from cleanup providers and let wire order it.
  6. One injector per file; delegate to per-package sets instead of fat wire.Build lists.

Common mistakes

MistakeFix
Editing wire_gen.gochange providers, re-run wire ./...
Missing //go:build wireinjecttag the first line of injector files
Two *sql.DB providersnamed struct types, one provider each
Interface without wire.Bindadd the bind to the set
Forgetting re-run after changeswire before go build; wire a Makefile target
Unguarded cleanup()nil-safe: if cleanup != nil { defer cleanup() }

Testing

wire emits plain constructors, so tests inject by hand — nothing to clone or reset. Test injectors that swap real providers for fakes, plus a CI stale check for wire_gen.go: testing.

Cross-references

  • golang-dependency-injection — when DI pays off and the full library matrix.
  • golang-uber-dig / golang-uber-fx — runtime reflection-based containers.
  • golang-samber-do — generics-based container, no codegen.
  • golang-structs-interfaces — interface design for constructor inputs/outputs.
  • golang-testing — general testing patterns.

Library bugs: google/wire issues.

del mismo repositorio

Más Skills

Todos los Skills
fabianoflorentino
Comunidad

golang-design-patterns

Idiomatic Golang design patterns — functional options, constructor APIs, init() and global-state avoidance, enums, panic vs error decisions, resource management and lifecycle, graceful shutdown, timeouts and retries, streaming and iterators, and architecture styles (clean, hexagonal, DDD, flat). Apply when choosing between architectural patterns, implementing functional options, designing constructor APIs, setting up graceful shutdown, applying resilience patterns, or asking which idiomatic Go pattern fits a specific problem. Not for wiring a DI container or comparing DI libraries (→ See fabianoflorentino/golang-agent-skills@golang-dependency-injection skill), nor for error wrapping, errors.Is/As, or logging mechanics (→ See fabianoflorentino/golang-agent-skills@golang-error-handling skill).

instalaciones
1
GitHub Stars
0
Actualizado
14 sept
fabianoflorentino
Comunidad

golang-lint

Linting best practices and golangci-lint configuration for Golang projects — running linters, configuring .golangci.yml, suppressing warnings with nolint directives, interpreting lint output, and selecting linters. Use when configuring golangci-lint, asking about lint warnings or nolint suppressions, setting up code quality tooling, or choosing linters. Also use when the user mentions golangci-lint, go vet, staticcheck, or revive. Not for wiring a lint step into a GitHub Actions pipeline (→ See fabianoflorentino/golang-agent-skills@golang-continuous-integration skill).

instalaciones
1
GitHub Stars
0
Actualizado
14 sept
fabianoflorentino
Comunidad

golang-modernize

Modernize Golang code to use recent language features, standard library improvements, and idiomatic patterns. Use when reviewing Go code with old-style patterns, when encountering a deprecation warning, or when the user asks for modernization, a Go version upgrade (e.g. to Go 1.27), or a CI/tooling refresh. Not for structural refactors, extracting functions, or moving code between packages (→ See fabianoflorentino/golang-agent-skills@golang-refactoring skill).

instalaciones
1
GitHub Stars
0
Actualizado
14 sept
fabianoflorentino
Comunidad

golang-pitfalls-concurrency-foundations

Golang concurrency foundations — concurrency vs parallelism, thinking concurrency is always faster, channels vs mutexes, not understanding race problems (data race vs race condition), not understanding workload types (CPU vs I/O bound, GOMAXPROCS), and misunderstanding Go contexts. Distilled from mistakes 55-60 of 100 Go Mistakes and How to Avoid Them. Apply when reasoning about basic Golang concurrency, goroutines, and context usage.

instalaciones
1
GitHub Stars
0
Actualizado
14 sept