26.8 TLS Configuration and Let's Encrypt with golang.org/x/crypto/acme

Right, so you’ve built your server, and it’s happily chatting away on port 80. That’s great, if you’re living in 1995. For the rest of us, we need to wrap this whole conversation in the secure, encrypted envelope of TLS. And because you’re not a multi-billion dollar corporation with a dedicated PKI team, you’re going to use Let’s Encrypt. It’s the only sane choice. It’s free, it’s automated, and it just works. The Go team, in their infinite wisdom, didn’t put the full ACME client (the protocol Let’s Encrypt uses) in the standard library, but they did bless an official one: golang.org/x/crypto/acme/autocert. This package is so good it feels like magic, and I’m inherently suspicious of magic. Let’s demystify it.

26.7 Graceful Shutdown with context and server.Shutdown()

Right, so you’ve got your server running. It’s handling requests, serving cat pictures, whatever. Now imagine you need to stop it. You hit Ctrl+C. What happens? If you’re not careful, it drops everything and vanishes like a thief in the night. Active connections are severed mid-download, database writes are abandoned, and you’re left with a corrupted state and a bunch of very confused users. Not cool. We do things properly here. We do graceful shutdown. This means we tell the server, “Hey, finish up what you’re doing, but no new stuff, and then we can go.” The net/http package gives us the tools for this, but you have to wire it up yourself. It’s not magic, it’s just good manners.

26.6 Server Timeouts: ReadTimeout, WriteTimeout, IdleTimeout

Right, let’s talk about timeouts. This isn’t just some box-ticking exercise for your app’s YAML config; this is your first and last line of defense against the chaotic, resource-hungry abyss of the public internet. A server without timeouts is like a hotel with no checkout time—eventually, you’re going to run out of rooms because a bunch of guests decided to live in the lobby, doing nothing. Let’s not run that hotel.

26.5 Serving Static Files with http.FileServer

Right, so you want to serve some static files—CSS, JavaScript, images, that sort of thing. Your first instinct might be to write a handler that opens a file and streams it out. Please, for the love of all that is holy, don’t do that. You’ll get the path wrong, forget to set the Content-Type header, and introduce a hilarious directory traversal vulnerability before lunch. Instead, you’re going to use http.FileServer. It’s a workhorse, it’s battle-tested, and it does almost everything right. I say almost because, well, we’ll get to its quirks.

26.4 Writing Middleware: Wrapping Handlers

Right, so you’ve got a handler. It does a thing. It’s a beautiful, pure function that takes a ResponseWriter and a *Request and just… handles. But now you want it to also log every request. And maybe check for an authentication header. And compress the response. And add security headers. Your first, most horrifying instinct might be to just go into your perfect little handler function and start adding a bunch of log.Println() statements and if blocks. Don’t. You’ll turn it into a tangled mess of orthogonal concerns, and I will personally come to your house and refactor your code while muttering angrily under my breath.

26.3 Enhanced Routing in Go 1.22: Method and Wildcard Patterns

Right, so you’ve graduated from the basic http.HandleFunc and http.Handle tutorials. You’ve built a few routes. And you’ve probably already run into the first major headache of the old ServeMux: its routing is… let’s be charitable and call it “simplistic.” It does prefix matching, which means a route registered at /api/ will happily try to handle a request for /api/things/i/do/not/have. That’s not just annoying; it’s a potential security and logic nightmare. You end up writing a bunch of boilerplate code inside your handler to parse out IDs and validate paths. It feels like you’re fighting the standard library.

26.2 http.ServeMux: Pattern Matching and Route Registration

Right, so you want to build a web server in Go. You’ve probably already found http.ServeMux. It’s the router that ships with the standard library, and it’s your first, and often your best, choice. It’s not the flashiest kid on the block, but it’s reliable, predictable, and doesn’t require a 50-page manual to understand. Think of it as the sturdy, well-worn toolbox in your garage, not the multi-function gizmo from a late-night infomercial that promises to julienne fries.

26.1 http.Handler and http.HandlerFunc

Alright, let’s get our hands dirty with the real meat and potatoes of the Go HTTP server: http.Handler and http.HandlerFunc. This isn’t some abstract, ivory-tower concept; it’s the fundamental contract, the interface that everything else is built upon. If you understand this, you understand how the entire net/http package holds together. The core of it all is the http.Handler interface. I love its simplicity. It’s so small, you might trip over it.

— joke —

...