HTTP Server
Go's net/http server powers millions of production APIs.
Introduction
Go's net/http server powers millions of production APIs. Register handlers with http.HandleFunc or ServeMux (enhanced in Go 1.22 with method and path patterns), wrap middleware for logging and auth, and use http.Server for graceful shutdown.
Each incoming request runs in its own goroutine automatically. Understanding handler signatures, response writing, status codes, and Server.Shutdown with context is mandatory for backend interviews.
This lesson builds a production-ready server with middleware, health endpoint, and graceful shutdown on SIGINT.
The story
Kubernetes kubelet exposes an HTTP server on port 10250 for pod lifecycle operations. Go's net/http multiplexes routes via ServeMux, wraps handlers with middleware for auth and logging, and supports graceful shutdown with server.Shutdown(ctx) when SIGTERM arrives during a rolling update on GKE.
Every Go microservice you deploy behind an API gateway starts here: a ListenAndServe call, health endpoints, and structured request logging.
Understanding the topic
Key concepts
- http.Handler interface: ServeHTTP(ResponseWriter, *Request).
- HandlerFunc adapter converts func to Handler.
- ResponseWriter writes headers, status, body — order matters.
- http.Server{Addr, Handler, ReadTimeout, WriteTimeout}.
- Shutdown(ctx) graceful stop; ListenAndServe blocks.
- Go 1.22 ServeMux supports GET /users/{id} patterns.
Step-by-step explanation
- Register routes on ServeMux or DefaultServeMux.
- Middleware wraps Handler: logging, auth, recovery.
- Handler reads r.Method, r.URL, r.Header, r.Body.
- w.WriteHeader(status) before body; default 200.
- ListenAndServe starts accepting connections.
- Signal handler calls srv.Shutdown(ctx) on SIGTERM.
Practical code example
HTTP server with middleware, health check, and graceful shutdown:
package mainimport ("context""fmt""log""net/http""os""os/signal""syscall""time")func loggingMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {start := time.Now()next.ServeHTTP(w, r)log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))})}func main() {mux := http.NewServeMux()mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {w.Header().Set("Content-Type", "application/json")fmt.Fprint(w, `{"status":"ok"}`)})mux.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "Hello from TechLearningPRO Go!\n")})srv := &http.Server{Addr: ":8080",Handler: loggingMiddleware(mux),ReadTimeout: 5 * time.Second,WriteTimeout: 10 * time.Second,}go func() {log.Println("listening on :8080")if err := srv.ListenAndServe(); err != http.ErrServerClosed {log.Fatal(err)}}()quit := make(chan os.Signal, 1)signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)<-quitctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)defer cancel()if err := srv.Shutdown(ctx); err != nil {log.Fatal("shutdown:", err)}log.Println("server stopped gracefully")}
Output
GET /healthz HTTP/1.1 → 200 OK
Line-by-line code explanation
http.HandleFunc("/healthz", healthHandler)registers a handler on the default ServeMux.mux := http.NewServeMux()creates an isolated mux — preferred over global registration.mux.Handle("GET /api/v1/items", handler)(Go 1.22+) supports method-aware routing.func handler(w http.ResponseWriter, r *http.Request)is the standard handler signature.w.WriteHeader(http.StatusOK)sets the status before writing the body.json.NewEncoder(w).Encode(data)writes JSON responses directly to the ResponseWriter.server := &http.Server{Addr: ":8080", Handler: mux}configures the listening server.server.Shutdown(ctx)gracefully drains in-flight requests before exit.
Key takeaway: Go 1.22 pattern routing: method + path in HandleFunc. Shutdown waits for in-flight requests. Middleware wraps Handler chain.
Real-world use
Where you'll use this in production
- REST API backends for web and mobile clients.
- Internal admin APIs and health check endpoints.
- Webhook receivers for Stripe and GitHub events.
- Sidecar health servers in Kubernetes pods.
Best practices
- Set ReadTimeout, WriteTimeout, IdleTimeout on Server.
- Implement graceful Shutdown on SIGTERM for K8s.
- Recovery middleware catches panics — return 500 not crash.
- Use structured logging with request ID middleware.
- Separate router setup from main for testability.
- Return correct Content-Type and status codes.
Common mistakes
- No timeouts — slowloris and hung connections.
- Calling WriteHeader after Write — ignored.
- Not handling SIGTERM — K8s kills pod abruptly.
- Panic in handler crashes process without recovery middleware.
- Using DefaultServeMux in library code — route collisions.
Advanced interview questions
Q1Beginnerhttp.Handler vs HandlerFunc?
Q2BeginnerGraceful shutdown?
Q3IntermediateMiddleware pattern?
Q4IntermediateGo 1.22 ServeMux changes?
Q5AdvancedDesign production HTTP server for K8s.
Summary
net/http server handles each request in a goroutine. Wrap handlers with middleware for logging, auth, recovery. Configure timeouts and graceful Shutdown for production. Go 1.22 ServeMux supports method + path pattern routing. Next lesson: REST API development patterns.