The killer feature of golang for LLM dev is the tooling.
forbidigo is what allows me to keep ambient config out of my app, and restrict file access to a small set of paths. The coverage tool has "nocover", so you can guarantee that every realistic path is exercised at least once ("100%" code coverage, which is not a marker for testing completeness, but rather for flagging code you forgot to test). Linting is really good as well.
The only thing I haven't found is something to enforce error handling. Rust is better for error paths because you're not allowed to ignore them.
> Linting is really good as well.
Maybe we are using different tools (or we've set it up wrong) but I'm consistently surprised at how slow Go's linting is (using golangci-lint). Takes nearly 5 minutes on our codebase after any change (which means I just don't run it locally or in-editor). It's remarkable how poor the experience is after using tools like Python's Ruff (instant) or Rust's Clippy. I'd have expected a fast, default setup that I could tune.
Event JS's Eslint, which runs in actual JS, takes 21 seconds for a full sweep (which I don't normally run, since the in-editor hints are so fast)
It's surprising, because so many of Go's dev tools are so well thought out!
"The only thing I haven't found is something to enforce error handling."
errcheck, generally as manifested in golangci-lint, ensures you can't forget to do something with them. It would be odd for you to know about forbidigo but not errcheck as the former is much less widely known; is there something that errcheck doesn't do for you?
It's worth pointing out that "discard this error on purpose" is a legitimate form of error handling, so "enforce error handling" can't really constitute banning that. That's not a Go statement, that's just true in general... it is sometimes valid to just ignore the error, because there's nothing useful to do with it anyhow. I would agree the ignoring should be explicit, but it is an option.