Files
open-claw-team/.openclaw/workspace/skills/golang-dependency-injection/references/google-wire.md
T

2.4 KiB

google/wire — Compile-Time Code Generation

Wire uses code generation to resolve the dependency graph at compile time. Type-safe, but requires a build step.

Before writing Wire code, refer to the library's official documentation for up-to-date API signatures and examples.

Provider Definitions

// providers.go
package wire

import "github.com/google/wire"

// ProviderSet groups related providers
var InfraSet = wire.NewSet(
    NewConfig,
    NewDatabase,
    NewCache,
)

var ServiceSet = wire.NewSet(
    NewUserService,
    wire.Bind(new(UserStore), new(*PostgresUserStore)), // bind interface to impl
)

Injector Definition

// wire.go — build constraint ensures this is only used by the wire tool
//go:build wireinject

package main

import "github.com/google/wire"

func InitializeApp() (*App, error) {
    wire.Build(
        InfraSet,
        ServiceSet,
        NewApp,
    )
    return nil, nil // wire replaces this body
}

Generated Code

Run wire ./... to produce wire_gen.go:

// wire_gen.go — DO NOT EDIT (auto-generated by wire)
func InitializeApp() (*App, error) {
    config := NewConfig()
    database, err := NewDatabase(config)
    if err != nil {
        return nil, err
    }
    cache := NewCache(config)
    store := NewPostgresUserStore(database)
    userService := NewUserService(store, cache)
    app := NewApp(userService)
    return app, nil
}

Testing

Wire generates plain constructors, so testing uses manual injection — no container to clone:

func TestUserService(t *testing.T) {
    mock := &MockUserStore{...}
    svc := NewUserService(mock, NewTestCache())
    // ... test
}

Tradeoffs

  • Errors caught at compile time (codegen fails if graph is incomplete)
  • Requires running wire ./... after every dependency change
  • No lazy loading — all dependencies created eagerly
  • No built-in lifecycle management (health checks, shutdown)
  • No runtime container — wire generates plain Go constructor calls
  • Interface bindings require explicit wire.Bind declarations
  • Generated files (wire_gen.go) must be committed and kept in sync

Wire injectors MUST use //go:build wireinject build constraint. Generated wire_gen.go MUST NOT be edited manually — always regenerate with wire ./....