Go 1.23 Range Over Functions: What It's For and What It Isn't

Go 1.23 stabilised range over function iterators, a feature that had been in the rangefunc experiment since 1.22. It’s the most significant addition to the range statement since channels were added. The reaction has been mixed: people who needed it find it elegant; people who didn’t need it find it confusing. Both reactions are reasonable. Here’s what it actually does and where it belongs. ...

June 18, 2025 · 5 min · MW

Go's Race Detector in CI: Catching Data Races Before They Catch You

A data race is a program that reads and writes shared memory concurrently without synchronisation. The behaviour is undefined: you might get the old value, the new value, a torn read (part old, part new), or a crash. Reproducing the bug is usually impossible because it depends on precise CPU scheduling. Go’s race detector is a compile-time instrumentation tool that detects these at runtime. It’s one of the most useful debugging tools in the Go ecosystem and one of the most underused. ...

October 4, 2023 · 6 min · MW

Go's net/http: Building Production HTTP Servers Without a Framework

Go’s net/http is frequently underrated. The ecosystem has frameworks — Chi, Gin, Echo, Fiber — and they’re fine choices, but the standard library gets you remarkably far without additional dependencies. After building several production APIs that stayed on raw net/http, here’s the honest assessment of what you can and can’t do without a framework, and the patterns that make it work. ...

July 5, 2023 · 6 min · MW

Database Access Patterns in Go: sqlx, pgx, and When to Use an ORM

The first question on every new Go service with a database: standard library database/sql? sqlx? pgx directly? An ORM like GORM? sqlc for code generation? The honest answer is that the right choice depends on the access pattern, the team’s SQL proficiency, and how much you value type safety at the cost of verbosity. Here’s what each option looks like in practice. ...

April 5, 2023 · 6 min · MW

Writing Idiomatic Go

Go has a strong house style that experienced practitioners converge on. Some of it is enforced by gofmt and golint. The rest is transmitted through code reviews, the standard library, and writing enough Go to feel the natural grain of the language. After several years of Go, here are the patterns that mark idiomatic code and why they work. ...

January 11, 2023 · 6 min · MW

Structured Logging in Go: slog, zerolog, and What Actually Matters

Unstructured logging is a debugging tool. Structured logging is an observability tool. The difference: unstructured logs tell a human what happened; structured logs tell a machine what happened, and the machine can then tell a human efficiently. Unstructured: 2022-11-23 10:58:34 ERROR failed to process order ORD-12345 for user usr_abc: connection refused Structured: {"time":"2022-11-23T10:58:34Z","level":"ERROR","msg":"failed to process order", "order_id":"ORD-12345","user_id":"usr_abc","error":"connection refused", "service":"order-service","version":"1.2.3"} The structured log can be indexed, filtered, aggregated, and alerted on. order_id:ORD-12345 returns all logs for that order across all services. The unstructured log requires grep and hope. ...

November 23, 2022 · 5 min · MW

Memory Layout in Go: Structs, Alignment, and Cache Performance

This is the JVM false-sharing problem in a different language. The rules differ slightly, the tooling differs, but the underlying hardware constraint — cache lines are 64 bytes and sharing one across goroutines is expensive — is identical. ...

August 17, 2022 · 5 min · MW

OpenTelemetry in Go: Distributed Tracing That Doesn't Get in the Way

Before OpenTelemetry, distributed tracing was a vendor-specific integration. You chose Jaeger or Zipkin or Datadog, added their SDK, and traced against their API. Switching vendors meant rewriting instrumentation. Adding a library that used a different tracing SDK meant two tracing systems running in parallel. OpenTelemetry solved this with a vendor-neutral API and a pluggable exporter model. The API stays the same; you swap exporters. Most major observability vendors now accept OTel format natively. Here’s what a solid Go integration looks like. ...

May 31, 2022 · 5 min · MW

Embedding in Go: Composition Over Inheritance Done Right

Go’s lack of inheritance is deliberate. The Go designers observed that inheritance hierarchies tend to create tight coupling and fragile base classes — problems that composition avoids. Embedding is Go’s tool for composition: you can embed one type in another and promote its methods, without inheritance’s downsides. It’s more powerful and more subtle than it appears. ...

January 5, 2022 · 5 min · MW

Building Reliable Pipelines with Go: Retry, Circuit Breaker, and Backoff

A service that calls a database, calls another service, or writes to a message queue will eventually encounter a failure. The question is not whether — it’s whether your service handles failures gracefully or cascades them into a larger outage. These patterns are well-documented in the resilience literature. What this post focuses on is the specific Go implementation and the traps that make naive implementations incorrect. ...

November 17, 2021 · 6 min · MW
Available for consulting Distributed systems · Low-latency architecture · Go · LLM integration & RAG · Technical leadership
hello@turboawesome.win