How to Build an HTTP Server in Go

Introduction

Go’s standard library provides everything you need to build production-ready HTTP servers without external frameworks. This tutorial covers middleware, graceful shutdown, and best practices.

Step 1: Set Up the Server

package main

import (
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write([]byte(`{"status": "ok"}`))
    })

    server := &http.Server{
        Addr:    ":8080",
        Handler: mux,
    }
    server.ListenAndServe()
}

Step 2: Add Middleware

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))
    })
}

server.Handler = loggingMiddleware(mux)

Step 3: Graceful Shutdown

go func() {
    sigCh := make(chan os.Signal, 1)
    signal.Notify(sigCh, os.Interrupt)
    <-sigCh
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    server.Shutdown(ctx)
}()

server.ListenAndServe()

Conclusion

Go’s standard library provides a robust HTTP server with minimal dependencies. The middleware pattern, combined with graceful shutdown, gives you a production-ready foundation.