Hacker News new | ask | show | jobs
by tacitusarc 1866 days ago
This feels largely like a mischaracterization, and does not align with my experience. I'd change it to say, if you are focused on solving the problems creatively rather than using the language creatively, Go is a viable option. But if you're interested in creative usage of the language itself, Go is not right for you.
2 comments

I get what you're poking at and I think we're mostly saying the same thing. However I want to point out that at the level of the stack we're discussing, the application of the chosen language is essentially: plumbing. The user-facing "creative" bits I think you're referring to (those in the system at large, which may or may not use Golang middleware) are most likely a react or mobile app. I'm not trying to devalue the self worth of individuals who write Go code by suggesting that the problems their products are solving aren't creative and fun. Not at all. Rather, my point is that the application of their Go code to build yet another solution for processing requests and serving responses ends up as pretty mundane and verbose imperative program logic that requires non-trivial amounts of effort to properly test and verify. Creativity in the "plumbing" slice of the stack to me looks like concise, readable, expressive code that leverages a type system to model a problem domain and then incorporates expressive logic governing how the types interact, the correctness of which is mostly enforced by the compiler itself and where testing is only required to ensure properties the type system can't capture or to make sure traits of a given type are implemented correctly. Go just simply isn't a language that allows for that level of "creativity" in building what would otherwise just be pretty mundane service plumbing.
I agree with this. Go works like my brain, and I don't mind that. Sure you can do X in some fancy way in other languages, but that just leads to feature creep. I've never read Go code I didn't understand at first glance. I cannot say that about a single other language.
And this is totally fine if you're okay reading and writing noticeably _more_ code to solve the same problems. There's nothing wrong with favoring verbosity over expressiveness, it's just not my style.

I disagree that expressiveness lends to feature creep, I've personally never seen that happen, but that's another topic.

For me, the verbosity of Go would be a lot more justified if it aslo had some sort of memory safety system in place (similar to Rust) that could help prevent concurrency related errors. I understand that you're supposed to used channels for everything in Go, but last time I wrote a channel heavy concurrent server the compiler did nothing to prevent me from mutating shared state across different go-routines and I was unable to land on a pure channel based implementation (I needed a run_once to initialize some shared state and a WaitGroup to track active listeners, and this was the case in all the other impls I audited/referenced as well). I just don't feel like I'm getting a lot of value in exchange for the verbosity when writing Go.

That's a completely fair assessment. I don't fault 'you guys' at all because I don't expect your brain works like mine. Read: I don't think you're wrong and I'm right...never.

What I fear myself is feature creep. A design by committee that ruins the language for me, and is never good enough for you.

If sharing state, you're much better off using locks and test with go's race detector. There'll be subtle bugs or contention though, unless you don't share state.

If not, you might try 0mq, immutable lists or any other facility. Channels are just the in-process idiomatic way to communicate state, but not required at all.

In my somewhat brief experience with Go I realized that one better avoid channels even for supposedly idiomatic cases. For example, try to implement a priority queue with channels. Or why it is not possible to use the select statement against a file descriptor? Another problem is proliferation of unnecessary threads that are entirely avoidable when using mutexes.
I agree. One should have good use cases for channels, and they're overused just to get new people started with goroutines.

Mutexes go a long way, and underpins channels anyways.

Channels are also hardly foolproof. You need to internalize the (non-obvious) channel axioms[1], and there are many other pitfalls and annoyances like:

- Needing to determine ownership of closable objects passed across channels.

- Defining what special token (or OOB signaling mechanism) is used for marking end of data.

- Synchronizing who is closing the channel

Go channels are quite painful to use and often a simple lock would do better. This write-up[2] summarizes the issues with them quite nicely:

[1] https://dave.cheney.net/2014/03/19/channel-axioms [2] https://www.jtolio.com/2016/03/go-channels-are-bad-and-you-s...

> Go works like my brain

can't really fault you on that either. features/looks etc. it really comes down to wether it matches how you think. I can make big claims about functional languages being superior for x y and z but if I'm being really honest with myself. its more about that fact that it fits how my brain already models problems.