{} The Go Reference

Foundations · Guide · Start here

Foundations: Patterns & the Go Mindset

What design patterns are, why they exist, and why they look so different in Go than in Java or C++.

Foundations Start here ⏱ 5 min read Complete

In one line. A design pattern is a named, proven solution to a problem that keeps coming up — a shared vocabulary that lets one engineer say “let’s use a Strategy here” and another instantly know what they mean.

Patterns aren’t code you download. They’re descriptions of a design that you adapt to your language and problem. The catalog comes from the 1994 book Design Patterns by the “Gang of Four” (GoF), which cataloged 23 of them. That catalog is the backbone of this guide — but we read it through a Go lens, because Go changes the answers.

Why patterns are worth your time

🗣️

Shared vocabulary

”Wrap it in a Decorator” compresses a paragraph of explanation into two words on a code review.

🧩

Tried-and-tested

Each pattern encodes trade-offs people already learned the hard way, so you skip some of the mistakes.

🔌

Design for change

Most patterns exist to isolate the part of a system most likely to change behind a stable interface.

The three families

The 23 GoF patterns split into three groups by what kind of problem they solve.

graph TD
A["Design Patterns (GoF)"] --> C["Creational<br/>how objects are made"]
A --> S["Structural<br/>how objects are composed"]
A --> B["Behavioral<br/>how objects interact"]
C --> C1["Singleton · Factory Method<br/>Abstract Factory · Builder · Prototype"]
S --> S1["Adapter · Bridge · Composite · Decorator<br/>Facade · Flyweight · Proxy"]
B --> B1["Strategy · Observer · Command · State<br/>Iterator · Template Method · and more"]

🎯 A quick way to remember them

Creational = the birth of objects. Structural = the shape objects form together. Behavioral = the conversation between objects.

Why Go is different

Most pattern tutorials are written for Java or C++. Go deliberately omits features those languages lean on — and that changes everything.

Java / C++ relies on…Go gives you instead…Effect on patterns
Class inheritanceStruct embedding (composition)Template Method, Decorator become composition
Explicit implementsImplicit, small interfacesAdapter & Strategy get trivial
Objects everywhereFirst-class functionsStrategy/Command can be a func value
Threads + locksGoroutines + channelsObserver/Pub-Sub become channel-native
ConstructorsPlain NewX() functionsFactory Method is just a function

🐹 The Go proverbs that matter here

Accept interfaces, return structs.” · “The bigger the interface, the weaker the abstraction.” · “Don’t communicate by sharing memory; share memory by communicating.” Each one quietly rewrites a classic pattern.

So in this guide, every pattern page asks two questions: what’s the classic shape? and what does it actually look like in idiomatic Go? Sometimes the answer is “a one-line function.” That’s a feature, not a disappointment.

The four pillars behind Go’s approach

  • Interfaces are implicit. A type satisfies an interface just by having the methods — no implements keyword. This makes Adapter, Strategy and Dependency Injection nearly free.
  • Embedding, not inheritance. Put a struct inside another and its methods are promoted. You get reuse without a class hierarchy.
  • Functions are values. You can pass behavior directly, so many “make an object to hold one method” patterns collapse.
  • Concurrency is built in. Goroutines and channels turn Observer, Pipeline and Pub/Sub into language-level idioms.

The design principles behind every pattern

Patterns are applications of a smaller set of principles that run through the whole catalog. Learn these nine and most patterns become obvious — they’re just principles assembled for a specific problem:

PrincipleIn a sentence
Encapsulate what variesSeparate the changing part from the stable part
Favor composition over inheritanceHAS-A beats IS-A for flexibility
Program to interfaces, not implementationsDepend on abstractions, not concrete types
Strive for loose couplingMinimize what interacting objects know of each other
Open/ClosedOpen for extension, closed for modification
Dependency InversionHigh- and low-level code both depend on abstractions
Least Knowledge (Demeter)Talk only to your immediate friends
Hollywood Principle”Don’t call us, we’ll call you” — the framework drives
Single ResponsibilityOne class/type, one reason to change

Go’s design pushes you toward several of these by default — composition (embedding), program-to-interfaces (implicit interfaces), loose coupling (small interfaces) — which is exactly why so many patterns shrink in Go.

How to read a pattern page

Every pattern in this guide follows the same structure, so you always know where to look:

Intent & analogy

One-line purpose plus a real-world story to anchor it in memory.

Problem & structure

The pain it removes, then a UML diagram of the moving parts.

Idiomatic Go

Runnable Go code — the Go-native form, not a Java translation.

Trade-offs & quiz

When to use it, when not to, where the stdlib uses it, and a self-check.

✅ Mark pages as 'learned'

Use the Mark as learned button on every pattern page to track your journey. Your progress bars on the home page fill up as you go — it’s all saved in your browser.

Ready? The most natural place to begin is the very first creational pattern.

Check your understanding

Score: 0 / 5

1. What is a design pattern, most precisely?

A pattern is a description of a solution — a shared vocabulary — not code you import. You implement it yourself, shaped by your language.

2. Why do several classic patterns shrink or vanish in Go?

Many GoF patterns work around the absence of features Go has built in. Strategy is often just a function value; Iterator is range; Observer leans on channels.

3. Which statement reflects idiomatic Go best?

Go has no inheritance. It composes behavior with struct embedding and satisfies small, implicit interfaces — accept interfaces, return structs.

4. Which single principle underlies nearly every design pattern?

Almost every pattern isolates the volatile part of a design behind a stable boundary: Strategy isolates an algorithm, Decorator isolated added behavior, Factory isolates construction. 'Encapsulate what varies' is the seed most patterns grow from.

5. A teammate wraps everything in patterns 'to be flexible.' What does the book warn?

Patterns earn their keep against actual change and complexity. Forcing them speculatively ('pattern fever') adds layers, names, and indirection with no payoff — the simplest thing that works, especially in Go, often beats a formal pattern.

Comments

Sign in with GitHub to join the discussion.