Lab 15: Capstone — REST API

Time: 30 minutes | Level: Practitioner | Docker: docker run -it --rm golang:1.22-alpine sh

Overview

Build a complete, production-quality REST API in Go: chi router, JSON handlers, in-memory store with sync.RWMutex, middleware stack (logging/recovery/requestID), table-driven tests, and graceful shutdown with context and OS signals.


Step 1: Project Setup

mkdir go-api && cd go-api
go mod init go-api
go get github.com/go-chi/chi/v5@latest

Directory structure:

go-api/
├── main.go
├── handler/
│   └── items.go
├── store/
│   └── store.go
├── middleware/
│   └── middleware.go
└── handler/
    └── items_test.go

Step 2: In-Memory Store with sync.RWMutex

store/store.go:

💡 Use RLock/RUnlock for reads (allows concurrent readers) and Lock/Unlock for writes. Never mix read and write locks for the same operation.


Step 3: JSON Handlers

handler/items.go:


Step 4: Middleware (Logging, Recovery, RequestID)

middleware/middleware.go:


Step 5: Router and Main

main.go:


Step 6: Table-Driven Tests

handler/items_test.go:


Step 7: Running the Server

💡 httptest.NewRecorder() and httptest.NewRequest() let you test HTTP handlers without starting a real server — fast, isolated, and no port conflicts.


Step 8 (Capstone): Full Store Demo + Table-Driven Tests

📸 Verified Output:


Summary

Component
Technology
Pattern

Router

go-chi/chi

URL params, route groups

JSON I/O

encoding/json

Decode request body, encode response

Concurrency

sync.RWMutex

Safe concurrent read/write store

Middleware

chi middleware stack

Logging, recovery, request ID

Testing

net/http/httptest

Table-driven, no real server needed

Graceful Shutdown

context.WithTimeout + os.Signal

Drain in-flight requests then exit

Last updated