Logo
Logo
10 results for
  • There is a particular brand of cleverness that feels deeply satisfying to write and deeply painful to maintain. The AbstractServiceProviderFactory. The builder that returns a builder that configures a builder. The generic interface so abstract it could model anything and therefore models nothing well. Go’s culture pushes back hard against this tendency, and for good reason: I’ve seen more bugs traced to abstraction layers than to simple structs.

    The Problem

    The most common form of over-engineering in Go is attempting to import Java-style construction patterns. Go doesn’t have constructors, so engineers invent them — and the result is code that’s harder to configure, not easier:

    Go tutorial golang Created Mon, 17 Nov 2025 00:00:00 +0000
  • You’ve added goroutines, you’ve got worker pools, you’ve written careful concurrent code — and the service is still slower than expected. Maybe goroutine count is climbing in your metrics dashboard. Maybe p99 latency has a long tail you can’t explain. Maybe a throughput test plateaus at 40% of what you thought the hardware should support.

    This is where guessing stops and profiling starts. Go ships world-class concurrency profiling tools in the standard library — mutex profiles, block profiles, goroutine dumps, and the execution tracer. Most engineers know about the CPU and memory profiler. Far fewer use the concurrency-specific profiles, which is a shame because they find the exact thing that’s wrong in minutes instead of days.

    Go tutorial golang concurrency Created Thu, 13 Nov 2025 00:00:00 +0000
  • Go has two ways to have a slice with zero elements, and they are not the same thing. Developers coming from Python, Ruby, or JavaScript expect an empty collection to just be an empty collection. In Go, the distinction between a nil slice and an empty slice is subtle enough that you can miss it for months — right up until a frontend engineer files a bug because your API is returning null instead of [].

    Go tutorial golang Created Mon, 03 Nov 2025 00:00:00 +0000
  • Here’s a tension that comes up in almost every real concurrent system: you want to process things fast, which means doing them in parallel, but the output needs to come out in the same order the input arrived. These two goals are in direct conflict. Parallel execution means things finish in unpredictable order. Ordered output means you have to wait for the slowest thing in each batch.

    The engineers who understand this tension build systems that make the trade-off explicitly. The engineers who don’t notice it build systems that either throttle themselves to single-goroutine throughput “to preserve order” or silently return results in the wrong order and wonder why tests fail non-deterministically.

    Go tutorial golang concurrency Created Fri, 31 Oct 2025 00:00:00 +0000
  • Every time someone asks “should I use GORM or raw SQL?” a flame war breaks out. I’ve been on both sides of that argument, and I’ve shipped production systems using all four approaches — raw SQL, GORM, sqlc, and Ent. My opinion now is boring: each one is the right choice in a specific context, and none of them is universally correct. The question isn’t which one is best, it’s which tradeoffs you’re signing up for.

    Go tutorial golang database Created Wed, 29 Oct 2025 00:00:00 +0000
  • After you absorb the Go concurrency philosophy — share memory by communicating — there’s a temptation to reach for channels every time two goroutines need to share data. Resist that. Channels are for coordination and ownership transfer. For shared mutable state that multiple goroutines read and write, a mutex is usually clearer, simpler, and faster. Using a channel where a mutex belongs is one of those things that looks idiomatic but isn’t.

    Go tutorial golang Created Mon, 20 Oct 2025 00:00:00 +0000
  • Every system has a throughput ceiling. The question isn’t whether your service can be overwhelmed — it can. The question is what happens when it is. Does it slow down gracefully, maintaining correctness and giving the caller a clear signal? Or does it blow up — OOM-killed, goroutines piling up, latency spiking to infinity while requests pile up in an unbounded queue?

    Backpressure is the mechanism that answers that question. It’s how a component communicates to its upstream: “I’m full — slow down.” Without it, fast producers eat slow consumers alive. In Go, backpressure is naturally expressed through blocking channel sends — and understanding when to block versus when to drop is one of the more interesting design decisions in concurrent systems.

    Go tutorial golang concurrency Created Sun, 19 Oct 2025 00:00:00 +0000
  • Most Go developers write concurrent code for years without thinking about the scheduler. That’s by design — the scheduler is supposed to be invisible. But eventually you’ll hit a situation where goroutines aren’t running when you expect them to, CPU cores are idle while goroutines pile up, or a CPU-bound workload is somehow slower with more goroutines. At that point you need a mental model of what’s actually happening under the hood.

    Go tutorial golang concurrency Created Wed, 08 Oct 2025 00:00:00 +0000
  • In most languages, a function returns one thing and communicates failure through a side channel — an exception, a null, a magic sentinel value. Go’s approach is different: functions can return multiple values, and the convention is to use that to make failure explicit in the signature itself. Once you’ve used it for a while, hiding failures in side channels starts to feel dishonest.

    The Problem

    Sentinel values are the old-school way to signal failure from a function. You pick some value that “shouldn’t” appear in normal results and treat it as an error signal:

    Go tutorial golang Created Mon, 06 Oct 2025 00:00:00 +0000
  • The repository pattern is one of those ideas that sounds great in an architecture talk and causes real pain when applied indiscriminately to a Go codebase. I’ve seen teams add a UserRepository interface with five methods, a concrete postgresUserRepository implementation, and a mockUserRepository for tests — and then wonder why everything takes three times as long to write. I’ve also seen teams skip the pattern entirely and end up with *sql.DB threaded through 40 different functions, impossible to test without a real database.

    Go tutorial golang database Created Thu, 02 Oct 2025 00:00:00 +0000