---
title: "Go Was Never Bad"
date: 2025-06-21
tags: ["go"]
description: "Go is not for everything, and that was never the point. A defense of brutal minimalism for cloud systems."
---

Every time I see that GitHub repo go-is-not-good making the rounds again, I laugh. It's always shared by people who mistake language cleverness for engineering.

Let me say this clearly: Go is not for everything. It was never meant to be. But if you're building cloud-native systems, if you're working with distributed architecture, if you're running services in production that actually matter -- Go is brutal, minimal, and effective.

```mermaid
graph LR
    A["No generics"] -- "Go 1.18" --> B["Resolved"]
    C["No modules"] -- "Go 1.11" --> D["Resolved"]
    E["Error handling"] --> F["By Design"]
    G["Concurrency"] --> H["Same as every lang"]
```

## Generics

Go 1.18 brought generics. Not the "look how clever I am" kind. The real-world, clean, no-BS kind. I've built production-grade code with generics in Go, and it's boring in the best possible way.

## Error Handling

I respect Go's approach to error handling. It makes you look at your failure paths. There's no magic trapdoor. You deal with errors explicitly, predictably, and with clarity. Now with `errors.Is`, `errors.As`, and `errors.Join`, it's not even painful.

## Go does not babysit your Concurrency

Go gives you the raw tools to build concurrent systems. It assumes the person writing the code knows what they're doing. I respect that.

## Performance

I've deployed Go services that boot in under 50ms and run for months without a hiccup. It doesn't brag. It just works.

```mermaid
graph LR
    A["Go"] --> B["Ship fast, simple"]
    C["Java / Spring"] --> D["Medium complexity"]
    E["Rust / Haskell"] --> F["Complex, more guarantees"]
```

## Personal take

I've built banking systems, transaction processors, and cloud-native APIs with Go. It's not flashy. But Go keeps things simple and predictable, and that's exactly what backend engineering demands.
