Explain the Go 1.22 ServeMux enhancements: method matching, wildcards, and precedence rules.
Question 444MediumGo 1.22 to 1.25
Since Go 1.22, patterns have the form [METHOD ][HOST]/[PATH]:
"GET /items/{id}"— method + a single-segment wildcard, read viar.PathValue("id").GETalso matchesHEAD."/files/{path...}"— a trailing multi-segment wildcard capturing the rest."/{$}"— matches exactly/(without{$}, a trailing slash pattern matches the whole subtree).- If the path matches but the method does not, the mux replies 405 with an
Allowheader.
Precedence: the most specific pattern wins (one that matches a strict subset of requests). /items/latest beats /items/{id}. If two patterns overlap and neither is more specific (e.g. /a/{x} and /{y}/b), registration panics — conflicts are detected at startup, not at request time.
mux := http.NewServeMux()
mux.HandleFunc("GET /items/{id}", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "item %s", r.PathValue("id"))
})
mux.HandleFunc("GET /items/latest", latest) // more specific, wins
mux.HandleFunc("POST /items", create)
mux.HandleFunc("GET /static/{path...}", serveStatic)
mux.HandleFunc("GET /{$}", home) // only "/"
Gotcha: GODEBUG=httpmuxgo121=1 restores old behavior; wildcards must be whole segments (/b_{id} is invalid).
More on Standard Library, HTTP & Systems Design in Go
- Q443How does net/http's server handle concurrency internally? What are the consequences for handler code?
- Q445Write a logging middleware that records the response status code. What are the pitfalls of wrapping http.ResponseWriter?
- Q446Why is http.ListenAndServe(":8080", nil) not production-ready? Explain each server timeout.
- Q447How does http.Client connection pooling work, and what are common mistakes with http.Client?
- Q448Why must you close resp.Body, and why is closing alone sometimes not enough?
- Q449How is context used in net/http on both server and client sides? What happens when a client disconnects mid-request?