Master Go from the ground up
A complete tour of Go — from values, variables and control flow to data structures, functions, structs & interfaces, composition, concurrency, idiomatic error handling, generics, the standard library (strings, slices, maps, time, regexp), and JSON encoding (encoding/json, struct tags, streaming). Every lesson pairs careful prose with verified examples and hands-on challenges.
- Step 1
Understanding values in Go
Every Go program is a conversation between values. A value is a piece of data the program holds in memory — a number, a …
Start lesson - Step 2
Variables
A variable is a name your program gives to a value. Once the value has a name you can refer to it, change it (if it is m…
Start lesson - Step 3
Constants
A constant is a value that the compiler bakes in at build time. Use const for anything that should never change after th…
Start lesson - Step 4
Enums with iota
Go does not have a built-in enum keyword. The idiomatic substitute is a typed const block driven by iota — a compiler-ge…
Start lesson - Step 5
Project — Custom Logger
Time to put the first four lessons together. You will build a tiny configurable logger that uses variables for state, co…
Start lesson - Step 6
For-loops — the only way to loop
Go has exactly one loop keyword: for. Every loop you will ever write — counting, iterating, polling, retrying — is some …
Start lesson - Step 7
Conditional statement — if/else
if is exactly what you expect from any C-family language with two stylistic guardrails: there are no parentheses around …
Start lesson - Step 8
Conditional statement — switch
switch is Go’s pattern-matching tool for cleanly choosing between several constants. The shape is switch expr { case a: …
Start lesson - Step 9
Capstone — Sales Order Processor
Chapter 1 capstone. You will combine every concept from the previous lessons — types, variables, constants, iota, for, i…
Start lesson - Step 10
How to work with Arrays
An array in Go is a fixed-length sequence of values of a single type. The length is part of the type itself: `[3]int` an…
Start lesson - Step 11
Dynamic arrays — Slices
A slice is Go's answer to the dynamic array. It looks like an array — declared as `[]T` with no length — but it grows. A…
Start lesson - Step 12
Maps
A map associates keys with values. `map[K]V` is the type: K must be a type whose values can be compared with `==` (strin…
Start lesson - Step 13
Working with pointers
A pointer holds the memory address of a value. Where most languages hide pointers behind references, Go makes them expli…
Start lesson - Step 14
More on slices — slicing, copy, sharing
Now that slices, arrays, and pointers all make sense, the slicing operator deserves its own lesson. `s[a:b]` produces a …
Start lesson - Step 15
Capstone — Contact Management System
Chapter 2 capstone. You will build a small in-memory contact book that reads commands from stdin, mutates a map of names…
Start lesson - Step 16
Functions
A function is a reusable block of code that takes inputs and (optionally) returns outputs. Go's function syntax is compa…
Start lesson - Step 17
More on functions — closures and higher-order
Anonymous functions are functions without a name. You define one inline with `func(params) returnType { body }`, optiona…
Start lesson - Step 18
Variadic functions
A variadic function accepts an arbitrary number of arguments of the same type. Mark the last parameter with `...T` and i…
Start lesson - Step 19
Returning multiple values
Go functions can return more than one value. Wrap the return types in parentheses: `func divmod(a, b int) (int, int)`. I…
Start lesson - Step 20
Custom error handling
Go has no exceptions. Functions that can fail return an extra `error` value, and the caller is expected to check it. Thi…
Start lesson - Step 21
The defer statement
`defer` schedules a function call to run when the surrounding function returns — no matter how it returns (normal `retur…
Start lesson - Step 22
Panic and recovery
`panic` is Go's hard-stop. Calling `panic(value)` immediately stops the current function, runs every deferred call up th…
Start lesson - Step 23
Capstone — Save Math Lib
Chapter 3 capstone. Build a tiny safe-math command processor that exercises every concept from the chapter: ordinary fun…
Start lesson - Step 24
Custom types with Structs
A struct is a composite type that groups named fields. Go uses structs the way most languages use "plain objects": to ho…
Start lesson - Step 25
Methods and receivers
A method is a function that belongs to a type. You write it the same way you write any function, except an extra `(recei…
Start lesson - Step 26
Interfaces
An interface is a *contract*: a set of method signatures that any type can satisfy. In Go, satisfaction is implicit — th…
Start lesson - Step 27
The Stringer interface
`fmt.Stringer` is the most famous one-method interface in Go: `type Stringer interface { String() string }`. The `fmt` p…
Start lesson - Step 28
Generics — present and future
Generics — type-parameterised functions and types — landed in Go 1.18 (March 2022). They let you write code that works f…
Start lesson - Step 29
Capstone — Payroll Processor
Chapter 4 capstone. Build a small payroll processor that exercises structs, interfaces, methods, and the Stringer patter…
Start lesson - Step 30
Composition in Go
Go has no inheritance. There is no `extends` keyword, no `super` call, no class hierarchy tree to navigate. Where a Java…
Start lesson - Step 31
Embedding as an alternative to inheritance
Embedding is the syntactic convenience that lets composition *feel* like inheritance without taking on inheritance's dow…
Start lesson - Step 32
Capstone — Bank Account Management
Chapter 5 capstone. Build a small bank that supports two kinds of accounts (Checking and Savings) sharing a common embed…
Start lesson - Step 33
Goroutines — concurrency made cheap
Concurrency is Go's headline feature, and the entry point is the goroutine — a function that runs concurrently with ever…
Start lesson - Step 34
Channels — communicate, don't share
Go's concurrency motto is "Do not communicate by sharing memory; instead, share memory by communicating." The tool that …
Start lesson - Step 35
Buffered channels, close, and range
An unbuffered channel forces sender and receiver to meet. Sometimes you want to let a sender run ahead — to queue up a f…
Start lesson - Step 36
select — waiting on many channels
A goroutine often needs to wait on *several* channels at once: maybe a result, maybe a cancellation, maybe a timeout. Th…
Start lesson - Step 37
The sync package — when to share state
Channels are the idiomatic way to coordinate goroutines, but they are not always the right tool. When several goroutines…
Start lesson - Step 38
context — cancellation and deadlines
Real concurrent programs need a way to say "stop — we don't need this work anymore." A request gets cancelled, a deadlin…
Start lesson - Step 39
Capstone — Concurrent Worker Pool
Chapter 6 capstone. You will build the single most important concurrency pattern in Go: the worker pool, also called fan…
Start lesson - Step 40
Errors are values
Go has no exceptions for ordinary failures. Instead, errors are ordinary values: a function that can fail returns an `er…
Start lesson - Step 41
Sentinel errors
Sometimes callers need to react to a *specific* failure — "the record wasn't there" versus "the database is down." A sen…
Start lesson - Step 42
Custom error types
A sentinel carries only its identity. When an error needs to carry *data* — which field failed, which line, what limit w…
Start lesson - Step 43
Wrapping errors with %w
As an error travels up through layers of your program, each layer can add context about what it was trying to do. `fmt.E…
Start lesson - Step 44
errors.Is — matching through the chain
Once errors can be wrapped, a plain `err == ErrNotFound` check breaks: the sentinel is now buried under one or more laye…
Start lesson - Step 45
errors.As — extracting a typed error
`errors.Is` answers "is this *the* error?" `errors.As` answers "is there an error of this *type* in here, and if so give…
Start lesson - Step 46
Capstone — Config Entry Validator
Chapter 7 capstone. You will build a small `key=value` configuration validator that exercises every error tool from this…
Start lesson - Step 47
Type parameters
Before generics (Go 1.18+), writing one function that worked for `[]int` and `[]string` meant either copy-pasting it per…
Start lesson - Step 48
Constraints — restricting T
`any` lets you move values around but not operate on them. To write a generic `Sum`, the compiler must know `T` supports…
Start lesson - Step 49
Generic Map, Filter, Reduce
Generics let you finally write the higher-order trio — `Map`, `Filter`, `Reduce` — that every other language ships, full…
Start lesson - Step 50
Generic data structures
Type parameters work on types too, not just functions. `type Stack[T any] struct { items []T }` is a stack of any elemen…
Start lesson - Step 51
Inference & the comparable constraint
Most of the time you call generic code without ever writing a type argument — inference fills them in from the values yo…
Start lesson - Step 52
Constraints that require methods
Type-set constraints (`~int | ...`) describe which *types* are allowed. Constraints can also describe *behavior*: an ord…
Start lesson - Step 53
Capstone — Generic Pipeline Toolkit
Chapter 8 capstone. You will build a tiny generic toolkit — `Filter`, `Map`, and `Reduce` — and compose the three into a…
Start lesson - Step 54
Text wrangling — strings & strconv
Welcome to Chapter 9. You have the language; now you get the library. Go ships with a famously complete standard library…
Start lesson - Step 55
Ordering data — sort & the slices package
Sorting is the most common non-trivial thing a program does, and Go gives you two layers for it. The classic `sort` pack…
Start lesson - Step 56
Counting & sets — the maps package
You met maps in Chapter 2 as the built-in key→value store. This lesson is about the patterns that make maps a power tool…
Start lesson - Step 57
Clocks & calendars — the time package
Time is one of the genuinely hard problems in software — time zones, leap seconds, daylight saving, ambiguous formats — …
Start lesson - Step 58
Numbers — math & math/rand
When the work turns numeric, the `math` package has the constants and functions you expect from a scientific calculator,…
Start lesson - Step 59
Pattern matching — the regexp package
When text is too irregular for `strings` but too structured to ignore, regular expressions are the right tool. Go's `reg…
Start lesson - Step 60
Capstone — Log Level Report
Chapter 9 capstone. You will combine `bufio`, `strings`, `maps`, and `slices` into a small but realistic tool: a log sum…
Start lesson - Step 61
Marshal & Unmarshal — encoding/json
Chapter 10 is about the format that runs the internet: JSON. Go's `encoding/json` package turns Go values into JSON text…
Start lesson - Step 62
Controlling the shape — struct tags
Real APIs use `snake_case` or `camelCase` keys, omit empty fields, and hide secrets — none of which match Go's capitalis…
Start lesson - Step 63
Nested objects, slices & maps
JSON is recursive — objects contain objects, arrays, and arrays of objects — and Go mirrors that recursion naturally. A …
Start lesson - Step 64
Custom encoding — MarshalJSON & UnmarshalJSON
Sometimes the default field-by-field encoding is not what the wire wants. A status enum should travel as a word, not the…
Start lesson - Step 65
Streaming — json.Decoder & json.Encoder
`Marshal` and `Unmarshal` work on a complete `[]byte` held in memory. When the JSON comes from a stream — a file, an HTT…
Start lesson - Step 66
Unknown shapes — map[string]any & RawMessage
Not all JSON has a schema you know in advance — webhook payloads, config blobs, third-party responses. When you cannot d…
Start lesson - Step 67
Capstone — Leaderboard Transform
Chapter 10 capstone. You will build a complete JSON-in, JSON-out transform — the shape of every data-processing endpoint…
Start lesson - Step 68
The universal interfaces — io.Reader & io.Writer
Chapter 11 is about the two tiniest, most important interfaces in Go. `io.Writer` has one method, `Write([]byte) (int, e…
Start lesson - Step 69
Reading line by line — bufio.Scanner
Reading a whole stream with `io.ReadAll` is fine when it fits in memory, but most text processing wants one line — or on…
Start lesson - Step 70
Writing into memory — strings.Builder & bytes.Buffer
Often the destination you want is memory: build a string or a blob of bytes piece by piece, then use the result. Go's tw…
Start lesson - Step 71
Plumbing — io.Copy, MultiWriter, Discard
Because `Reader` and `Writer` are interfaces, the `io` package can offer generic plumbing that connects any source to an…
Start lesson - Step 72
Implementing your own Reader & Writer
The real power of one-method interfaces is that you can implement them. Give any type a `Write([]byte) (int, error)` met…
Start lesson - Step 73
Formatting deep dive — fmt verbs & Stringer
You have used `fmt` since lesson one; this lesson makes you fluent in its verbs. A verb is the `%`-directive that says h…
Start lesson - Step 74
Capstone — Build wc (word count)
Chapter 11 capstone. You will rebuild a classic Unix tool — `wc`, the word-count utility — which is the perfect exercise…
Start lesson