Theory is useless without execution. We assemble everything learned across 14 episodes — structs, pointers, error handling, JSON codecs, context timeouts, and concurrency — into a production-grade HTTP REST API.
TL;DR (Quick Summary)#
- Go 1.22+ Routing: Native HTTP method routing and path wildcards (
http.NewServeMux().HandleFunc("POST /api/v1/users", ...)). - Streaming Codecs:
json.NewDecoder(r.Body).Decode(&req)processes payloads directly from memory streams. - Middleware Pipeline: Reusable handler wrappers for Logging, CORS, Authentication, and Rate Limiting.
- Graceful Shutdown: Intercepts
SIGINT/SIGTERMsignals and usesserver.Shutdown(ctx)to complete active requests before closing.
1. Production API Architecture#
graph LR
Client["HTTP Client / Frontend"] -->|POST /users| Logging["Logging Middleware"]
Logging -->|Passes Context| Auth["Auth Middleware"]
Auth -->|Valid Request| Router["ServeMux Router"]
Router -->|Invokes| Handler["CreateUser Handler"]
Handler -->|Returns JSON 201| Client
2. Step-by-Step Lab: Building the Production API#
Create main.go:
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
// User Model
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}
type CreateUserRequest struct {
Username string `json:"username"`
Email string `json:"email"`
}
// In-Memory Database
var users = map[string]User{
"1": {ID: "1", Username: "rhidayat", Email: "[email protected]", CreatedAt: time.Now()},
}
// Middleware: Request Logging
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf("--> %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
log.Printf("<-- %s %s completed in %v", r.Method, r.URL.Path, time.Since(start))
})
}
// Handler: GET /users/{id}
func GetUserHandler(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
user, exists := users[id]
if !exists {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(map[string]string{"error": "User not found"})
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(user)
}
// Handler: POST /users
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(map[string]string{"error": "Invalid JSON payload"})
return
}
newID := fmt.Sprintf("%d", len(users)+1)
newUser := User{
ID: newID,
Username: req.Username,
Email: req.Email,
CreatedAt: time.Now(),
}
users[newID] = newUser
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(newUser)
}
func main() {
mux := http.NewServeMux()
// Register Routes
mux.HandleFunc("GET /users/{id}", GetUserHandler)
mux.HandleFunc("POST /users", CreateUserHandler)
handler := LoggingMiddleware(mux)
server := &http.Server{
Addr: ":8080",
Handler: handler,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
}
// Start server in background
go func() {
log.Println("🚀 Go REST API running on http://localhost:8080")
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalf("Server crash: %v", err)
}
}()
// Graceful Shutdown
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
<-stop
log.Println("⚠️ Shutting down API server...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Graceful shutdown failed: %v", err)
}
log.Println("✅ Server stopped gracefully.")
}3. Testing API Endpoints#
Start the server:
go run main.goTest requests via curl:
# GET User
curl -s http://localhost:8080/users/1
# POST User
curl -s -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"username":"alice","email":"[email protected]"}'Summary & Conclusion#
Congratulations! You have completed the 15-Episode Go Master Series!
You have progressed from:
- Installation, syntax, and zero values
- Structs, maps, slices, and pointers
- Memory stack vs heap escape analysis
- Implicit interfaces, type assertions, and custom domain errors
- Goroutines, channels, G-M-P scheduler, and worker pools
- Unit testing, benchmarking, fuzzing, and zero-dependency REST API servers
Keep building high-performance Go applications!

