Stage 1 · Code
Building Web Services
HTTP Fundamentals in Go
See what actually happens when a browser or API client knocks on your program's door: how `net/http` turns bytes on the wire into a `Request`, hands it to a handler, and lets you build the response back up deliberately.
The Front-Desk Model
Imagine a small office reception desk. A visitor walks in, gives their name, explains why they are here, and maybe hands over a document. The receptionist reads that information, decides which desk should handle it, and sends back an answer: 'please wait in room three,' 'you need a badge first,' or 'here is the document you requested.' That is the shape of HTTP.
A client sends a request. Your Go program reads it. One handler decides what to do. Then your program writes a response. Before you think about routers, JSON, or frameworks, lock in that four-step story. Web programming feels much less mysterious once you see it as a structured exchange instead of a blur of browser magic.
The client speaks first with a request. Your server gets one chance to answer with a response. Everything in net/http is built around making those two turns explicit.
The Core `net/http` Pieces
Go's standard library keeps the model intentionally small. A handler is just something that knows how to answer one HTTP request. A mux chooses which handler should receive which path. A server listens on a network address and keeps repeating that handoff for each new connection.
| Piece | What it is | Why it matters |
|---|---|---|
http.Handler | An interface with one method: ServeHTTP(http.ResponseWriter, *http.Request) | This is the contract for 'can answer an HTTP request' |
http.HandlerFunc | A function adapter that lets an ordinary function satisfy http.Handler | Most small handlers start life as plain functions |
http.ServeMux | A request multiplexer that matches paths and routes requests to handlers | It keeps one giant if statement from swallowing your server |
http.ListenAndServe | A helper that opens a TCP listener and starts serving HTTP | This is the moment your program becomes a live web server |
*http.Request | The incoming request data: method, path, headers, body, and more | Handlers read from this value to understand what the client wants |
http.ResponseWriter | The output side of the exchange | Handlers set headers, choose a status code, and write the response body here |
http.HandlerFunc is Go doing you a favor. Instead of forcing you to define a new struct type every time, it lets a normal function act like a handler. That keeps the common case simple without changing the underlying model.
Building a Small Server
Now let's put the pieces together in one small server. This example deliberately touches the important knobs: it starts a server, uses a ServeMux, reads method, path, headers, and body from the request, and writes a response with explicit headers, status code, and body.
http.ListenAndServe(":8080", mux)opens port 8080 and starts waiting for incoming requests.- When a request arrives,
ServeMuxlooks at the path and chooses a handler. - Inside the handler,
r.Method,r.URL.Path,r.Header, andr.Bodytell you what the client sent. - You shape the response by setting headers on
w, choosing a status code, and writing body bytes. - Once the handler returns, Go sends that response back across the network to the client.
The first body write can cause Go to send the headers immediately. That is why status code and header decisions usually happen before fmt.Fprint, w.Write, or json.NewEncoder(w).Encode(...).
Tracing a Real Request
Let's slow one request all the way down. Pretend a terminal client sends the following request to our running server. The values are concrete on purpose so you can picture the exact data moving through the program.
POST /inspect HTTP/1.1
Host: localhost:8080
Content-Type: text/plain
X-Client-Name: terminal-demo
Content-Length: 14
deploy previewThe important shift is this: the server is not working with mysterious browser objects. It is reading ordinary data from *http.Request and writing ordinary data to http.ResponseWriter, one deliberate step at a time.
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
X-Server-Name: request-lab
method=POST
path=/inspect
client=terminal-demo
body=deploy previewStatus line first, then headers, then the body. That is the full round trip: request in, handler work, response out.
Quiz and Practice
What job does `http.Handler` represent in Go's HTTP model?
Hands-On Project
Time to prove you can control both sides of the exchange: method checking, headers, status code, and body.
Write `Ping` so that `GET /ping` responds with status `200`, header `Content-Type: text/plain; charset=utf-8`, and body `pong`. Any other method must return status `405` with body `method not allowed`.
Summary and Key Takeaways
http.Handleris the basic promise: given a request, produce a response.http.HandlerFunclets an ordinary function satisfy that promise without extra ceremony.http.ServeMuxdecides which handler receives a request based on the path and route pattern.- Handlers read request data from
*http.Requestand write response data throughhttp.ResponseWriter. - A full HTTP exchange is concrete: method, path, headers, body in; status, headers, body out.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.