Skip to main content
Copper uses google/wire for dependency injection. Wire generates plain Go code at build time, so there is no runtime container and no reflection. If your dependency graph has a problem, you will find out with a compile error rather than a production surprise. You will rarely write wire code by hand. copper scaffold:pkg, scaffold:router, and scaffold:queries maintain it for you, and copper run regenerates it on every build.

Wire Modules

Each package declares what it provides in a wire.go file:
pkg/rockets/wire.go
The wire.Struct(new(NewSvcParams), "*") line tells wire to fill every field of the params struct from the dependency graph. This params struct convention is used throughout Copper:
Adding a dependency is a one-line struct change. You will not need to update constructor signatures throughout your codebase, or edit any wire code beyond the package’s own module.

Composing Modules

pkg/app/wire.go is the composition root for your packages. copper scaffold:pkg adds each new package’s module to it, alongside a few app-level providers:
pkg/app/wire.go
Copper ships several wire modules that you may pull into your binaries as needed:

Binding Interfaces

If you would like to depend on an interface rather than a concrete type, add a wire.Bind:
Any package may now ask for Telemetry and receive the satellite implementation. If you decide to swap implementations later, it is a one-line change.

Regenerating

Wire output is generated into wire_gen.go files, which are checked in. copper run and copper build regenerate them automatically. If you would like to run the generator manually:
Wire errors can look intimidating, but they almost always say one of two things: a type has no provider (a constructor or module is missing from a wire set) or has two providers (the same type is provided in two modules). Read the first error, find the type it names, and check your WireModules for it.