93 lines
2.4 KiB
Markdown
93 lines
2.4 KiB
Markdown
# 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.
|
|
|
|
- Docs: [github.com/google/wire](https://github.com/google/wire) | [User Guide](https://github.com/google/wire/blob/main/docs/guide.md)
|
|
|
|
Before writing Wire code, refer to the library's official documentation for up-to-date API signatures and examples.
|
|
|
|
## Provider Definitions
|
|
|
|
```go
|
|
// 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
|
|
|
|
```go
|
|
// 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`:
|
|
|
|
```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:
|
|
|
|
```go
|
|
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 ./...`.
|