Lesson 1 · Foundations

The Go mental model

Why Go looks so bare — and why that's the point.

Your win: explain the handful of design bets Go makes, so every later lesson feels like a consequence rather than a surprise — and so you can answer the interview opener "what do you like (or dislike) about Go?" with substance.

Coming from another language, the shock is how little there is

No classes. No inheritance. No exceptions. One loop keyword (for). No ternary operator. Generics only arrived in 2022. If your instinct is "where's the rest of it?", that instinct is the thing to reset. Go's designers treated simplicity as a feature, not a limitation — the language is small on purpose so that large codebases stay readable.1

The proverb that sums it up "Clear is better than clever." Go optimises for the reader — the engineer six months from now debugging your code at 2am — over the writer showing off.2

The six bets

Compiled & statically typed

Types checked at build time; compiles to a single native binary. Fast, and errors caught early.

Values over magic

You can see what code does. Assignment copies; sharing is an explicit pointer. No hidden references. (Lesson 3.)

Composition, not inheritance

No class hierarchies. You build behaviour by embedding pieces. (Part 2.)

Implicit interfaces

A type satisfies an interface just by having the methods — no implements. Decoupling for free. (Part 2.)

Errors are values

No exceptions. You return an error and check it. Control flow is visible. (Part 3.)

Concurrency built in

Goroutines and channels are language features, not a library. (Part 4.)

Why this shows up in your monorepo

This codebase is 30+ services compiled into one binary. That only stays sane because Go is boring on purpose: any engineer can drop into spike, notification, or conversationmgmt and read it, because there's roughly one way to do things and no clever framework hiding the control flow.

Anchor You already rely on every bet: services are wired by implicit interface satisfaction and constructors (spike/.../email_modifier_service.go:39), behaviour is shared by embedding (commonConsumer in golibs/kafka/consumer.go), failures are returned errors, and the Kafka engine is goroutines + channels. This course just makes the reflexes you're building explicit. Full map: repo-go-map.md.

One deliberate consequence to notice now

Because Go prefers explicit over implicit, it is verbose in small ways — if err != nil { return err } everywhere, no default arguments, lots of typing out. That verbosity is the price of readability, and interviewers often probe whether you understand the trade rather than just complain about it.

Do this next

A Tour of Go — the "Basics" section

The official interactive intro; run the code in your browser. Then read the Go Proverbs once — they're the philosophy in one page.

go.dev/tour
go-proverbs.github.io

Check yourself (from memory)

Q1. Go's design philosophy prioritises…

"Clear is better than clever." The language stays small so big codebases — like this 30-service monorepo — stay readable.

Q2. How does a Go type satisfy an interface?

Implicit satisfaction — no declaration needed. It's why our repo can define small interfaces right where they're consumed. (Part 2.)
Name three of Go's design bets and why each helps a large codebase.
recall, then click to reveal
(1) Simplicity / one obvious way → any engineer can read any service. (2) Implicit small interfaces → decoupling and trivial mocking. (3) Errors as values → explicit control flow, no hidden throws. (Also: composition over inheritance, concurrency built in, values over magic.)
Want the honest downsides too (verbose error handling, no enums, interface{} before generics)? A balanced take is a strong interview answer — ask me.

1. Effective Go; A Tour of Go.

2. Go Proverbs — Rob Pike, Gopherfest 2015.