9 comments

[ 2.9 ms ] story [ 32.3 ms ] thread
Hmm... I thought it was going to be about the game go. Not that I want to take up the game any more than I want to start using Go...
I find Go an exceptionally weird language.

Multiple return values and constant nil checking and error handling is odd - there are far better patterns for handling this but Go chose something that looks easy but doesn't scale well. I have other issues but writing good Go code that is easy to read feels very difficult.

Very short function parameters seems to be idiomatic but very odd as well. I never understood the desire to condense meaning as much as possible versus a more legible approach.

I take your point about short parameter names. Like, why is it better to have to read all the code to understand what the parameter means?
I really really like Go as well. It fits my mental model I guess. Overall, I find it keeps things simple. One tell-tale sign was when I implemented Concurrent Hash-Array Mapped tries (basically a lock-free hashmap) as a learning exercise:

The code really looked like the pseudocode algorithm (albeit a bit different because of the lack of sumtypes).

I also like the error handling although multiple return values often preclude us from chaining calls. It forces to deal with error values a bit too eagerly at times but one get used to it.

And the language, tooling, etc, keeps improving steadily without breaking old code. Very good engineering from the implementers.

I really enjoy Go. I’ve always been inclined towards keeping the actual language simpler to write and read and it’s a very pragmatic language in my opinion.
Mixed feelings about go. - I dislike the verbosity of the error checking; rust’s ? Operator did it 100x better. With go, if some function deep in the call stack might return err, every single point in the call stack above it has to check “if err != nil”. I understand the point of this; unchecked exceptions are very bad, but some syntactic sugar could go a long way here.

- I dislike in general code generation. This isn’t a Go thing, this is a “any language but rust” thing: macros are just _so good_. I don’t have to keep a code generator daemon running in the background, and I don’t have to worry about running a code generation step in CI.

- I dislike implicit interface adherence: this makes it so hard for me to navigate code bases. For instance, If I take a Foo interface, I just have to guess at where all the Foo implementers are?

Those are just a couple of my qualms. In general, though, I do reach towards Go for projects that I know aren’t going to hit massive scale (scale as in “need 10 developers supporting it”), and it hits the sweet spot for me that’s between prototyping in python and enterprise in Java / Rust.

Have to agree about the implicit interfaces - I have a large codebase to deal with and I end up doing text searches through it to find implementations of a interface. This is not ok in 2022. The error handling is poor, as well.
Most of the comments dealing with error handling and interfaces are just stuff I grew used to having done Java for so long. However, for me personally, in a modern software development sense the pain point that I have with Go is unit test mocks and dependency injection. I remember spending a good afternoon trying to figure out how to setup some mocks and do some DI for some tests I was creating. I figured it out but it felt backwards and the code looked just as backwards to me. I tried to explain why we should do DI and mocks for tests but after showing the code to other developers it was a hard sale. The style and readability just wasn't there for them. I have respect for the Go language but maybe in the future mocks and DI will become easier or more natural looking.