liveBook · Manning

Composition

As explained in Go by Example

Composition is a design approach that builds larger abstractions by combining smaller components rather than inheriting implementation from a base type.

Function composition builds behavior by joining small, focused pieces instead of placing behavior in a type hierarchy. In Go, the broader design preference is composition over inheritance: types are flat, and reusable parts can be combined without creating parent–child relationships. This favors lower coupling, reuse, and code that can be adapted by adding layers rather than changing existing implementations. section 1.10 section 1.5 section 9.11

Composition takes several practical forms. Struct embedding promotes an embedded type’s fields and methods, making forwarding convenient, but it does not make the embedding type substitutable for the embedded type. Interfaces provide runtime polymorphism instead. Functions can also compose behavior: a wrapper accepts an existing handler or interface value, adds work before or after it, and returns the enhanced behavior. section 1.5.1 section 9.11 section 9.9

Wrap an HTTP handler

HTTP middleware demonstrates functional composition. A middleware receives a next handler, records response data while that handler runs, then logs the request path, method, and duration. Recording, response handling, and logging remain separate building blocks; the integration combines them into one request path. Additional middleware can be inserted without editing the health handler or the existing middleware. section 9.2.3 section 9.11 section 9.0

Use composition deliberately:

  • Combine components that each do one focused job; integrate them at the boundary where the larger behavior is needed. section 9.2.3
  • Wrap an interface or handler to modify, extend, or intercept behavior without modifying its original implementation. section 9.11
  • Use consistent function signatures and direct dependency injection so composed parts remain explicit and testable. section 9.9
  • Treat embedding as convenience for reuse, not as inheritance; promoted methods can hide behavior or alter the embedder unexpectedly. section 1.5.1 section 9.11
  • Expose a route to underlying optional behavior when wrappers or embedded interfaces might otherwise conceal it; type assertions can detect or recover capabilities. section 9.11 section 9.9

Composition has trade-offs. Layers can make data flow and optional capabilities less obvious, especially when embedding hides methods or Context carries values across API boundaries. Keep Context informational rather than using it to control program flow, use unique keys, and prefer concrete functionality when it can expose a needed capability directly. section 9.11 section 9.9

Figure 1.6 Inheritance creates a type hierarchy; embedding does not. In inheritance, you can pass parent (square) and child (circle) types interchangeably to a function that expects only the parent type. With embedding, the function can work only with the specified type. Embedding does not form a type hierarchy; it simply makes one type’s methods and data part of another type.
A cut out paper with a black line

AI-generated content may be incorrect.

Compare inheritance’s substitutable hierarchy with embedding’s distinct types. The diagram makes clear why promoted methods do not create parent–child polymorphism. section 1.5.1

How Go by Example covers it

How deep it goes
Explains embedding, wrappers, higher-order functions, interfaces, assertions, and Context; defers detailed embedding treatment.
Examples
Uses response-recording and logging middleware around an HTTP health handler, with request logs and handler-chain flow.
What it assumes
Introduces a rough composition overview while assuming enough Go familiarity to distinguish structs, interfaces, and handlers.
What you can do after
Apply it via Go handlers and interfaces to extend behavior without modifying existing implementations.
How it connects
Connects struct embedding, interfaces, higher-order functions, dependency injection, Context, type assertions, and HTTP middleware.

Also explained in

Compare how 11 books explain composition →

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.