Minimal server
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello world")
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
ServeMux patterns (Go 1.22+)
ServeMux now supports method matching and wildcards. For most apps you don't need a third-party router anymore.
mux := http.NewServeMux()
mux.HandleFunc("GET /users/{id}", getUser)
mux.HandleFunc("POST /users", createUser)
mux.HandleFunc("GET /static/", serveStatic) // subtree
mux.HandleFunc("GET /{$}", home) // exact "/"
http.ListenAndServe(":8080", mux)
Path parameters
func getUser(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
...
}
Production server — explicit timeouts and graceful shutdown
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 15 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 60 * time.Second,
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
go srv.ListenAndServe()
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
srv.Shutdown(shutdownCtx)