Http Router Basics
Fast recall
Quick revision
Core answer
Whether you understand Http Router Basics beyond memorized syntax.
Giving a definition without explaining a practical trade-off.
Connect the concept to a small production example and state its complexity or failure mode.
Interview-ready guide
Interview answer
ServeMux's three generations of capability:
Pre-1.22: exact + prefix
mux.HandleFunc("/api/users", h) // exact
mux.HandleFunc("/static/", h) // subtree
mux.HandleFunc("/", h) // catch-allGo 1.22+: methods + path parameters
mux.HandleFunc("GET /users/{id}", getUser) // method + param
mux.HandleFunc("POST /users", createUser)
// r.PathValue("id") — the extracted parameterWhat ServeMux still doesn't have — where third-party routers win:
- 1Middleware chains (chi's r.Use(logging, auth)) — composable, per-route
- 2Route groups (chi's r.Route("/api", ...))
- 3Complex matching (regex constraints, host matching)
- 4Route introspection (for docs generation, auth maps)
The decision: ServeMux for most services (1.22+ covers the common API shape: method + path + param); chi when middleware composition is the priority; gin/echo for the full framework (their ecosystems, their conventions).
The verification pattern: whatever router you choose, the handler signature stays func(w http.ResponseWriter, r *http.Request) — the http.Handler interface is the universal contract, and middleware is func(http.Handler) http.Handler — the patterns compose across routers.
Http Router Basics
Direct Answer
ServeMux: exact paths, prefix subtrees (trailing slash), Go 1.22+ adds methods and path params ({id}). Use ServeMux until you need middleware chains, route groups, or complex matching — then chi/gin/echo.
Deep Dive & Architecture
The 1.22 ServeMux restructure, mechanically: patterns became (method, path, params) — the matcher indexes by method+path-prefix, extracts named segments ({id} from /users/{id}) into r.PathValue, and handles the conflicts at registration time (overlapping patterns are now a compile-time-style error at startup — registering both /users/{id} and /users/x panics or errors, catching ambiguity the old mux silently resolved by longest-prefix).
The middleware difference, which is the real third-party value: Go's middleware pattern is a function wrapping an http.Handler: func(next http.Handler) http.Handler — any router can do this, but chi's r.Use() composes the chain at registration (readable, per-route scoping), while net/http's approach requires manual wrapping (func myMiddleware(next http.HandlerFunc) http.HandlerFunc { ... } and wrapping each handler or the mux itself). The pattern is identical; the ergonomics differ.
The lock-in question, which interviews use to test judgment: the http.Handler interface is the standard — handlers written against it work with every router (ServeMux, chi, gin with an adapter). Write handlers as http.HandlerFunc, keep the router a thin dispatch layer, and switching costs a routing file, not a rewrite.
Common Mistakes & Pitfalls
Giving a definition without explaining a practical trade-off.
Check your understanding
Answer these without looking back at the article.
- When would you use Http Router Basics in a real project?
- How would you compare Http Router Basics with an alternative?
- What is a common mistake when using Http Router Basics?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.