Logo
Logo
20 results for
  • Go packages are the primary unit of code organization. They determine what’s visible to whom, what gets compiled together, and — most importantly — they communicate intent to every engineer who reads the codebase. A package with high cohesion says something true and useful: “everything here is about orders” or “everything here handles HTTP middleware.” A package with low cohesion says nothing — it’s a filing cabinet where things went when nobody knew where else to put them.

    Go tutorial golang code quality Created Thu, 06 Feb 2025 00:00:00 +0000
  • I spent three hours once writing nearly identical impl blocks for sixteen different numeric types. Copy, paste, change i32 to i64, change i64 to u32, repeat. Halfway through I started making typos. By the end I had a bug in the u128 variant that took another hour to find. That’s the day I actually sat down and learned macros properly.

    The Gap Between Functions and Macros

    Functions are great. You take some inputs, do some work, return a result. But functions operate on values. They can’t generate new struct definitions. They can’t implement traits for you. They can’t vary the number or types of arguments they accept. They can’t produce different code depending on what you pass them at compile time.

    Rust tutorial rust macros metaprogramming Created Wed, 05 Feb 2025 10:22:00 +0000
  • Before Go 1.16, embedding static assets in a Go binary required either a code generation tool that converted files to byte arrays, a third-party library like packr or statik, or shipping the files alongside the binary and reading them from disk at runtime. Each approach had real costs: generated code bloated repositories, third-party tools had to be installed separately, and shipping separate files broke the “single binary” distribution story.

    The //go:embed directive in Go 1.16 solved this cleanly. Files, directories, and whole asset trees can be embedded directly into the binary with a single comment and a variable declaration. Templates, SQL migrations, web assets, default configs — everything your binary needs can travel with it.

    Go tutorial golang CLI Created Wed, 05 Feb 2025 00:00:00 +0000
  • There’s a moment in every async Rust developer’s journey where the runtime stops being a black box and starts being a machine you understand. For me, it was when I built a toy executor from scratch. Suddenly, Waker, Context, poll_ready — all of it made sense. Not as abstract concepts, but as mechanical parts.

    This lesson won’t make you build a production executor. But it will show you how the pieces fit together, and that understanding will change how you write and debug async code.

    Rust tutorial rust async tokio Created Tue, 04 Feb 2025 13:56:18 +0000
  • There’s a certain kind of error message I’ve come to dread in production logs: auth: db: sql: connection refused. Technically, it contains the full path from the handler down to the socket. Practically, it tells me nothing I couldn’t figure out from the stack trace — and it takes ten seconds to parse. That error message is the output of wrapping done wrong: every layer added its name reflexively, without thinking about what the reader actually needs.

    Go tutorial golang Created Tue, 04 Feb 2025 00:00:00 +0000
  • The fastest way to kill a production service is to accept work faster than you can process it. I learned this the hard way when a log ingestion pipeline I built consumed 50GB of RAM and crashed because I used unbounded channels everywhere. “It works fine in testing” — yeah, testing with 100 messages, not 10 million.

    Backpressure is the mechanism by which a system says “slow down, I’m full.” Without it, fast producers overwhelm slow consumers, and your only flow control is the OOM killer.

    Rust tutorial rust async tokio Created Sun, 02 Feb 2025 10:33:45 +0000
  • I once watched a service die in slow motion. An upstream dependency started responding slowly — not failing, just slow. Within minutes, all request goroutines were blocked waiting for the upstream. New requests kept arriving. Goroutines piled up. Memory climbed. Eventually the process was killed by the kernel. The upstream recovered in about thirty seconds. My service was down for twelve minutes. Every second of that outage was caused by the absence of a single line: a timeout.

    Go tutorial golang backend Created Sat, 01 Feb 2025 00:00:00 +0000
  • I avoided Tower for months. The trait bounds looked terrifying, the documentation assumed you already knew what you were doing, and I couldn’t figure out why I’d want it when I could just write functions. Then I needed to add logging, retries, timeouts, and rate limiting to every HTTP handler in a service with 40 endpoints.

    Writing those as middleware that composes? That’s Tower’s whole thing. And once it clicks, you’ll never build a service without it.

    Rust tutorial rust async tokio Created Fri, 31 Jan 2025 19:18:37 +0000
  • Almost every backend service I’ve built makes HTTP calls to something — a third-party API, another microservice, a webhook endpoint. And almost every production HTTP bug I’ve dealt with comes from one of three things: missing timeouts, not reusing connections, or ignoring response bodies.

    reqwest is the HTTP client for async Rust. It’s built on hyper and Tokio, handles connection pooling, TLS, cookies, compression, and all the stuff you don’t want to think about. But you still need to use it correctly.

    Rust tutorial rust async tokio Created Thu, 30 Jan 2025 16:42:09 +0000
  • If a binary tree problem asks anything about paths — longest, shortest, sum along a path, common ancestor between two nodes — the solution is almost certainly DFS. Not because DFS is the only way, but because path problems require you to propagate information up from leaves to ancestors, and that is exactly what post-order DFS does. You compute the answer for children before combining it for the parent.

    What I find interesting about this cluster of problems is how they reveal a single reusable DFS skeleton. Once you internalize the pattern — recurse left, recurse right, combine and return — you can adapt it to maximum depth, path sum, diameter, and LCA with only surface-level changes. The thinking cost drops dramatically once you stop treating each problem as novel and start asking “what do I return from each recursive call, and how do I combine it?”

    fundamentals interviews Created Thu, 30 Jan 2025 00:00:00 +0000