How Go’s Built‑in HTTP Server Handles Connections and Requests
This article walks through building a minimal Go HTTP server, explains how ListenAndServe internally binds, listens, and accepts connections, details the server’s main loop, request handling, routing logic, and shows how to customize connection and state hooks with concrete code examples.
Creating a Minimal Go HTTP Server
Using only 15 lines of Go code you can start an HTTP server that listens on port 81 and responds with "hello world". The essential code is:
package main
import (
"io"
"net/http"
)
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":81", nil)
}
func hello(response http.ResponseWriter, request *http.Request) {
io.WriteString(response, "hello world")
}The server can be compiled into a single binary, making deployment straightforward.
How ListenAndServe Works
The call http.ListenAndServe(":81", nil) performs two tasks: it binds to the address and port, and it starts serving incoming connections. Internally it wraps the OS system calls bind, listen and accept, then enters a loop that accepts connections and launches a new goroutine for each.
The first argument, Addr, specifies the listening address; the second, Handler, is usually nil, which means the default http.DefaultServeMux will be used.
Connection‑level Hooks: ConnContext
Each new connection receives a context derived from a base context. The ConnContext field of http.Server allows you to modify this context before the request is processed. A custom server can be created as follows:
func main() {
http.HandleFunc("/hello", hello)
server := http.Server{
Addr: ":81",
ConnContext: func(ctx context.Context, c net.Conn) context.Context {
return context.WithValue(ctx, "hello", "roshi")
},
}
server.ListenAndServe()
}Similarly, the ConnState hook lets you run a callback whenever a connection changes state.
Request Processing Loop
After a connection is accepted, the server runs a serve loop that repeatedly reads requests from the same connection:
func (c *conn) serve(ctx context.Context) {
for {
w, err := c.readRequest(ctx)
// error handling omitted
serverHandler{c.server}.ServeHTTP(w, w.req)
}
}This design allows a single TCP connection to handle multiple HTTP requests (HTTP keep‑alive). After reading a request, the server may start a background read to pre‑fetch the next request, improving throughput.
Routing Mechanics
The ServeHTTP method looks up the registered handler based on the request URI and method. Special cases such as the * pattern or the OPTIONS method are handled by a global options handler.
Routing follows three simple rules:
If a route was registered with a host, the lookup uses host+path; otherwise it matches by path only.
Exact matches take precedence. If a pattern ends with /, prefix matching is also applied.
Examples:
http.HandleFunc("/hello", hello)
http.HandleFunc("127.0.0.1/hello", hello2)
// curl 'http://127.0.0.1:81/hello' → hello2
// curl 'http://localhost:81/hello' → helloWith a trailing slash:
http.HandleFunc("/hello", hello)
http.HandleFunc("127.0.0.1/hello/", hello2)
// curl 'http://127.0.0.1:81/hello/roshi' → hello2Key Takeaways
Starting a Go HTTP server is extremely simple.
The server runs a main accept loop that spawns a goroutine for each new connection.
Each connection runs its own request‑handling loop, performing request parsing, routing, and handler execution.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
