liveBook · Manning

Dependency injection

As explained in Go by Example

Dependency injection is a software design technique in which required dependencies are supplied to a component from outside rather than created internally.

Dependency injection supplies a component’s dependencies from outside instead of creating them internally. In Go, this decouples program logic from external inputs and outputs, making behavior easier to test without changing the program’s external behavior. section 5.0 section 5.2.1

A practical refactoring for a command-line tool follows these steps:

  • Extract main’s core logic into a testable run function. section 5.3
  • Group dependencies such as global inputs and outputs in an env struct. section 5.2.1
  • Pass real dependencies from main and controlled fakes, such as in-memory buffers, from tests. section 5.2.1
  • Update parsers and integrations to use the injected dependencies, then verify behavior manually and automatically. section 5.3 section 5.0

Injecting a logger into middleware

Middleware can accept a specific logger and return a handler-wrapping function instead of using a global logger. The logger is supplied when middleware is configured, which simplifies testing and preserves the func(Handler) Handler signature needed for composition. section 9.1.2 section 9.9

Figure 5.2 Moving main's code into a run function that accepts an *env struct. The env struct has fields for us to inject the global variables, such as the os.Stdout. This approach allows main to inject real globals to run, and tests can inject controlled fakes that we can observe from tests later.
A screenshot of a diagram

Description automatically generated

The diagram shows main passing real globals through an env struct to run while tests pass controlled fakes that can be observed. section 5.2.1

How Go by Example covers it

How deep it goes
Explains refactoring steps, injected structs, interfaces, fakes, and explicit logger configuration, stopping short of framework-based techniques.
Examples
Uses a CLI env struct with in-memory buffers and middleware configured with an explicitly injected logger.
What it assumes
Assumes basic knowledge of Go interfaces while teaching dependency isolation through concrete CLI refactoring.
What you can do after
Build testable CLI and middleware components by passing real or fake dependencies through explicit parameters.
How it connects
Connects dependency injection with testability, interfaces, middleware, handlers, function signatures, and composition.

Also explained in

Compare how 21 books explain dependency injection →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.