HTTP Basics
net/http: batteries included
Go's standard library ships with a production-capable HTTP package โ no framework required. net/http covers both the server and client sides. For the server, three concepts cover almost everything: the Handler interface, the ServeMux router, and ResponseWriter.
The Handler interface
Every HTTP handler in Go satisfies one interface:
ResponseWriter is where you write the response; *Request carries everything the client sent (URL, method, headers, body). Any type with a ServeHTTP method can be registered as a handler.
http.HandlerFunc
Writing a full type just to satisfy the Handler interface for a simple function is verbose. http.HandlerFunc is an adapter that promotes a plain function to a Handler:
In practice you usually just pass the function directly to mux.Handle or mux.HandleFunc.
http.NewServeMux โ routing
A ServeMux matches incoming request paths to registered handlers:
Go 1.22 added method-qualified patterns like "GET /users/{id}", but exact-path + manual method checking works everywhere.
Inspecting the request
*http.Request carries all the information sent by the client:
Writing responses
http.ResponseWriter is an interface with three key operations, and order matters:
- Set headers โ before calling WriteHeader
- Call WriteHeader with the status code (optional; defaults to 200 on first Write)
- Write the body
http.Error is a convenience shortcut that sets a plain-text body and status in one call:
Middleware pattern
Middleware wraps a handler to run code before and/or after the inner handler. It returns a new Handler, so middleware chains compose cleanly:
Because the return type is http.Handler, you can stack multiple middleware layers:
Testing with net/http/httptest
You never need to start a real server to test your handlers. The net/http/httptest package provides in-process test helpers:
ResponseRecorder stores the status code, headers, and body in memory so you can assert on them after the handler returns. This makes handler tests fast, isolated, and free of network I/O.
Starting a real server
For completeness โ the one-liner to bind and serve (you cannot run this in the Playground because it blocks and requires a network):
In production code you usually call http.Server{Addr: ":8080", Handler: mux}.ListenAndServe() for more control over timeouts.
Knowledge Check
What interface must a Go HTTP handler implement?
What is http.HandlerFunc?
What does httptest.NewRecorder() return?