Sheet ⁨10⁩ · ⁨Roadmaps⁩Surveyed ⁨2026⁩

Go Developer Beginner to Expert

A roadmap for Go from syntax and the type system through goroutines and channels, building HTTP services, databases, testing, and running Go binaries in production.

Published:
Updated:
8 Stages
All Levels

Go is small enough that you can read the whole specification in an afternoon, and that is precisely why people plateau. The syntax stops being the obstacle within a week, and the remaining difficulty is idiom: what to do with errors, when a channel is the wrong tool, and how to keep concurrency bounded.

Work through the stages in order. Two of them are worth resisting the urge to skip. Interfaces, because implicit satisfaction is the thing that makes Go code testable without a mocking framework, and it is genuinely different from every language with an implements keyword. And concurrency, because goroutines are so cheap that the mistake is not using too few, it is spawning them without a ceiling.

The two common deployment shapes for Go, and which roadmap topic each makes concrete: static binaries and scratch images on the container path, cold starts and context deadlines on the Lambda path, with connection pooling and structured logging underpinning both.

That diagram is the argument for the last two stages. The static binary is an abstract fact until you see a 12 MB image with no shell in it. context.Context is boilerplate until a Lambda deadline arrives as a cancelled context and the code that ignores it keeps billing you. And SetMaxOpenConns is a line in the docs until an autoscaling group opens 900 connections against a database configured for 200.

01
1

Language Foundations

6 topics·5 required·1 recommended
Go is deliberately small. Read all of it, then stop looking for the features it does not have.

Syntax, types, and zero values

Required

Variables, constants, control flow, and the fact that every type has a usable zero value: 0, "", nil, and a struct with all fields zeroed. Designing around zero values rather than constructors is idiomatic and removes a lot of nil checking.

Slices, maps, and arrays

Required

Understand that a slice is a view over a backing array with length and capacity. append may or may not allocate, and two slices can share memory, which is the source of most surprising mutation bugs.

Structs, methods, and pointer vs value receivers

Required

Methods on types, and when a receiver should be a pointer: when you mutate, or when the struct is large. Mixing both on one type is a lint warning worth heeding.

Interfaces, satisfied implicitly

Required

No implements keyword: a type satisfies an interface by having the methods. Keep interfaces small, define them where they are consumed rather than where the type lives, and accept interfaces while returning structs.

Errors are values

Required

Return errors, do not throw them. Wrap with fmt.Errorf("...: %w", err) to preserve the chain, then inspect with errors.Is and errors.As. Learn this before adopting an error library.

Generics

Recommended

Type parameters and constraints, added in 1.18. Useful for containers and a handful of helpers. Most Go code does not need them, and reaching for them early usually produces something an interface did better.

02
2

Standard Library Fluency

5 topics·5 required
Go's standard library covers more than most ecosystems need a framework for.

net/http, both directions

Required

Write a server with http.ServeMux and handlers, and a client with a configured http.Client. Note the default client has NO timeout, which is a production incident waiting to happen.

The io interfaces

Required

io.Reader and io.Writer are the most important abstractions in the language. Composing them means streaming through a pipeline instead of buffering a whole file in memory.

encoding/json

Required

Struct tags, omitempty, and the difference between a missing field and a zero value. Use a pointer or json.RawMessage when that distinction matters.

time, and why monotonic matters

Required

time.Duration arithmetic, tickers, and using time.Since for elapsed time rather than subtracting wall clocks, which can jump.

log/slog for structured logging

Required

Structured logging in the standard library since 1.21. A JSON handler to stdout is all a container needs, and it removes a dependency most projects used to carry.

03
3

Concurrency

7 topics·6 required·1 recommended
The reason many people pick Go, and the part most often misused.

Goroutines and the scheduler

Required

A goroutine costs a couple of kilobytes, so a goroutine per request is normal. The runtime multiplexes them across OS threads itself. There is no GIL and no single event loop to block.

Channels, and when not to use one

Required

Channels transfer ownership of data. Buffered versus unbuffered, closing, and select. The idiom worth internalising early: if you are only protecting shared state, a sync.Mutex is simpler and clearer than a channel.

context.Context everywhere

Required

Cancellation, deadlines and request-scoped values. Any function doing I/O takes a context as its first parameter. Without this, a cancelled request keeps working and you cannot shed load.

sync primitives

Required

WaitGroup to wait for a set of goroutines, Mutex and RWMutex for shared state, sync.Once for one-time init, and errgroup for a group where the first error cancels the rest.

The race detector

Required

Run go test -race in CI, always. It finds data races that no code review reliably catches, and a race that has never fired is not a race that is absent.

Bounded worker pools

Required

An unbounded go f() per item is a goroutine leak and a way to exhaust a downstream dependency. Use a fixed pool reading from a channel, or a semaphore, so concurrency has a ceiling you chose.

Goroutine leak detection

Recommended

A goroutine blocked forever on a channel is a leak the garbage collector cannot help with. go.uber.org/goleak in tests, and the /debug/pprof/goroutine endpoint in production.

04
4

Testing

5 topics·3 required·1 recommended·1 optional
Go's testing story is built in and unusually pleasant.

Table-driven tests

Required

The dominant Go idiom: a slice of cases, one loop, t.Run for subtests so failures name themselves. This replaces most of what other ecosystems use a framework for.

Interfaces as seams for fakes

Required

Because interfaces are implicit and defined at the consumer, a hand-written fake is usually less work than a mocking library. Depend on a small interface, pass a fake in a test.

httptest for handlers and clients

Required

httptest.NewRecorder to exercise a handler without a socket, and httptest.NewServer to give a client a real endpoint to talk to.

Benchmarks and fuzzing

Recommended

go test -bench with b.N, and built-in fuzzing since 1.18. Fuzzing pays off immediately on anything that parses untrusted input.

Golden files

Optional

Compare output against a checked-in file, regenerated behind a -update flag. Well suited to templates, generated code and serialisation.

05
5

Building Services

6 topics·4 required·1 recommended·1 optional
Where Go earns its place, and where the standard library is often enough.

An HTTP service without a framework

Required

Since 1.22 http.ServeMux handles method and path patterns, so a routing library is genuinely optional. Start with the standard library and add chi or echo only when you can name the missing feature.

Middleware as handler wrapping

Required

Middleware is a function taking an http.Handler and returning one. Logging, recovery, auth and timeouts all compose this way, with no framework involved.

Graceful shutdown

Required

signal.NotifyContext plus server.Shutdown(ctx) so in-flight requests finish before the process exits. Without it, every deploy drops connections and the errors look like someone else's fault.

database/sql and connection pooling

Required

database/sql with pgx, and SetMaxOpenConns set deliberately. The default is unlimited, which will exhaust your database before your service notices.

sqlc or hand-written SQL over an ORM

Recommended

The Go community leans away from heavy ORMs. sqlc generates typed code from real SQL, keeping the query readable and the result typed.

gRPC and protobuf

Optional

Worth learning for service-to-service work: a schema, generated clients, and streaming. Overkill for a public API that a browser will call.

06
6

Modules and Tooling

5 topics·3 required·2 recommended
A small toolset, and worth knowing exactly.

Modules, go.mod and go.sum

Required

go mod tidy, semantic import versioning, and why go.sum belongs in version control. Minimal version selection means Go picks the lowest version satisfying all requirements, which is different from most package managers.

Project layout, without cargo-culting

Required

cmd/ for binaries, internal/ for packages that must not be imported externally (the compiler enforces it). Resist the elaborate layouts circulating online until the project needs them.

go vet, staticcheck, golangci-lint

Required

go vet catches real mistakes and ships with the toolchain. Add staticcheck via golangci-lint in CI and fix what it reports rather than suppressing it.

go generate and code generation

Recommended

Stringer for enums, mockgen, sqlc, protoc. Committing generated code is the Go norm, so builds do not depend on generator availability.

Cross compilation

Recommended

GOOS=linux GOARCH=arm64 go build produces a binary for another platform with no toolchain gymnastics. This is how one laptop builds for Graviton.

07
7

Shipping the Binary

4 topics·2 required·2 recommended
The stage where Go's design pays off most visibly.

Static binaries and scratch images

Required

CGO_ENABLED=0 go build -ldflags="-s -w" gives a static binary with no libc dependency, which a FROM scratch image can run alone. Images under 15 MB with almost no attack surface are routine.

Multi-stage Dockerfiles

Required

Build in the golang image, copy only the binary into the final stage. Copy go.mod/go.sum and run go mod download before the source, so the dependency layer caches.

Embedding assets with go:embed

Recommended

//go:embed puts templates, migrations and static files inside the binary, so deployment stays a single file.

Build info and versioning

Recommended

Stamp a version with -ldflags="-X main.version=...", or read runtime/debug.ReadBuildInfo(). Being able to ask a running binary what it is saves real time in an incident.

08
8

Running Go in Production

6 topics·5 required·1 recommended
The part that separates working from reliable.

Structured logging and correlation

Required

A slog JSON handler to stdout, with a request ID carried in the context so every line for one request can be found together.

pprof, in production

Required

Import net/http/pprof behind an internal port and you can capture a CPU or heap profile from a live process. Combined with go tool pprof, this is the best profiling story of any mainstream runtime.

Timeouts on everything

Required

http.Server needs ReadHeaderTimeout and WriteTimeout; http.Client needs a Timeout. The zero value means wait forever, and a hung upstream then exhausts your goroutines.

The memory model in practice

Required

Go is garbage collected with a low-latency collector. GOMEMLIMIT (1.19+) is what keeps a container from being OOM-killed, and it matters more than GOGC tuning for most services.

OpenTelemetry tracing

Recommended

otel-go with context propagation, exporting to X-Ray, Tempo or Jaeger. Because context already threads through your code, adding spans is mostly mechanical.

Health checks that mean something

Required

Separate liveness (is the process wedged) from readiness (can it serve, are its dependencies reachable). A readiness check that always returns 200 is decoration.

Comments

Was this useful?

You might also enjoy

More posts on similar topics

Python Developer Beginner to Expert

Python Developer Beginner to Expert

Python is easy to start and deceptively deep, which produces a common shape of developer: fluent in syntax, productive in a framework, and unsure what happens when the code meets real traffic. This ro

Node.js Developer Beginner to Expert

Node.js Developer Beginner to Expert

Node.js Developer Beginner to Expert This roadmap takes you from JavaScript foundations and the event loop through building APIs, working with databases, streams, testing, and security, and on to r

Full-Stack Developer Beginner to Expert

Full-Stack Developer Beginner to Expert

Full-Stack Developer Beginner to Expert This roadmap walks you from your first web page to shipping and operating a complete production application. Work the stages in order. Build the frontend fun

Backend Developer Beginner to Expert

Backend Developer Beginner to Expert

Backend Developer Beginner to Expert This roadmap walks you from your first server-side program to designing scalable, secure systems. Work through the stages in order. Nail a language, the command

React Developer Beginner to Expert

React Developer Beginner to Expert

React Developer Beginner to Expert This roadmap takes you from JavaScript prerequisites through JSX, hooks, and state management, and on to data fetching, meta-frameworks, performance, and testing.

Frontend Developer Beginner to Expert

Frontend Developer Beginner to Expert

Frontend Developer Beginner to Expert This roadmap walks you from absolute beginner to a strong, hireable frontend engineer. Work through the stages in order. The early ones build the mental model

6 related posts