go mod, go fmt/vet/doc, workspaces, build, and ship.
Build for Production & Deploy
You've made it through the language! Time to ship.
Building a release binary
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -trimpath -ldflags="-s -w" -o myapp .
CGO_ENABLED=0— pure-Go binary, no libc dependency. Runs on tiny base images.-trimpath— strip absolute paths from the binary (smaller, reproducible).-ldflags="-s -w"— strip debug symbols and DWARF info. Smaller binary.
Embed a version number via -ldflags:
package main
var version = "dev" // overridden at build time
go build -ldflags="-X main.version=$(git describe --tags --always)" -o myapp .
A minimal Dockerfile
# 1. Build stage
FROM golang:1.23-alpine AS build
WORKDIR /src
COPY go.* ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/app .
# 2. Runtime stage — empty image, just the binary
FROM gcr.io/distroless/static-debian12
COPY --from=build /out/app /app
USER nonroot:nonroot
ENTRYPOINT ["/app"]
This gives you a ~10 MB image with no shell, no package manager — just your binary. Tight and secure.
Deploying to a serverless platform
Most platforms (Vercel, Cloud Run, Fly.io, AWS Lambda) can deploy a Go program in one of two ways:
- As a container using the Dockerfile above. Push, deploy, done.
- As source code that the platform builds for you (Vercel detects
go.modautomatically).
This course itself uses option 2 — the /api/play route is a Node function on
Vercel, but you could write it in Go just as easily.
The bigger picture
You now know enough Go to:
- Build a CLI tool with
cobraor justflag. - Build an HTTP API with
net/http(orchi,echo,ginif you want pre-built middleware). - Run scheduled jobs with
time.Ticker. - Talk to databases with
database/sqland a driver likepgx. - Write tests, benchmarks, and fuzz suites for all of it.
The standard library is huge — and at this point you have the toolkit to read its docs and pull in whatever you need.
Production checklist
Before you ship a service to production, walk this list:
- ✅ All HTTP clients have a
Timeout. - ✅ All goroutines have a clear exit path (context cancellation or closed channel).
- ✅ Errors are wrapped with
%wand logged with context (request ID, user ID). - ✅
go test -racepasses in CI on every PR. - ✅ A signal handler (
signal.NotifyContext) gracefully shuts down. - ✅ Health endpoint (
/healthz) for the orchestrator. - ✅ Structured logging (
log/slog) — JSON in prod, text in dev. - ✅ Metrics or tracing — at minimum, request count + latency histogram.
- ✅ The binary is built with
-trimpathand stripped (-ldflags="-s -w"). - ✅ The container runs as a non-root user.
🎉 Course complete. Welcome to the Go community.