6 ms·
Care to illustrate your point with an example? I’m wondering what kind of “unnecessary complexity” you’re talking about.
by ghughes 9y ago
Care to illustrate your point with an example? I’m wondering what kind of “unnecessary complexity” you’re talking about.
- stouset 9y agoI mean, generics are kind of go's whipping boy. Lacking generics means you end up with copy/pasted code for utility functions that should be part of the go stdlib in virtually every project. It also means copy/pasted code for any data structure you might want to use that's fancier than an array. Go's "simplicity" of error handling (read: lack of any actual error handling abstractions) means you don't get useful things like stack traces and have to manually grep through code for nested error messages. It also makes go code difficult to read at a glance, since virtually every statement winds up wrapped in repetitive error-handling code that doubles or even triples the amount of code in the happy path. The error-handling pattern of using tuples, but no syntactical ability to operate on data within a tuple means you almost never have the ability to chain function calls like `a.b().c().d()`. Instead you have to manually unwrap the value and error, return if there's an error, call the next function, manually unwrap the value and error, ad nauseam. The "idiom" of gift-wrapping error messages is absurd — you are replacing machine-based exception handlers with expensive, slow, error-prone, and less-capable meat-based exception handlers. Having a half-baked type system means you end up having to frequently write type-switches which are checked at runtime to do any sort of generic code. There's no functionality in the language to ensure that all possible options for that type switch are exhausted, so you are virtually guaranteed to get runtime bugs when a new type gets written and later is passed in. Speaking of type switches, they interact poorly with go's indefensible decision to have interfaces implemented implicitly rather than explicitly. I have seen types get matched to the wrong typeswitch in producion code because a new method implemented on one type caused it to accidentally "implement" an interface used elsewhere in a typeswitch. Good luck ever catching this before it hits you in production. Go's concurrency primitives are useful, but the lack of ability to abstract over them means that you have "advanced go concurrency patterns" dozens of lines long and involving multiple synchronization primitives for what amounts to `a | b | c` (https://gist.github.com/kachayev/21e7fe149bc5ae0bd878 https://gist.github.com/kachayev/21e7fe149bc5ae0bd878). God help you if you want to implement something like parallel map. God help you if you want to implement something like parallel map for n > 1 types. Go requires you to manually remember to release resources you've acquired with `defer`, instead of sanely having There is no capacity in the language to enforce that you've done so, and it is virtually impossible to find e.g., a missing `defer fd.Close()` in a large code base. God help you if you leak file descriptors and need to track down the source. Go's inability to perform any meaningful abstractions also means that you have to know all the details of code you import. It's difficult to make code a black box. Case in point: to do something as painfully simple as reading a file, you need to import bufio, io, io/util, and os. During the course of writing this post, I forgot more examples than I listed — I literally could not remember them all in my head as I was writing them down. This isn't simplicity, this is utter madness.
- zzzcpan 9y agoI wouldn't call it madness, just limits Go usage somewhat, especially in domains involving a lot of concurrency. I once had hopes for Go. But the team working on it decided not to fix any of its flaws that became obvious over time and even outright denied their existence. So, not much Go for me anymore, but I'm still looking forward to see what such approach can bring in Go 2.
- zellyn 9y agoIt really sounds like you might like Rust. Have you looked into it? /snark But seriously, for a long time before Rust was fully baked, I kept wishing it would be done, so that people hating on Go could go use Rust instead. Now it's fully baked, which is awesome.
- stouset 9y agoRust is an example of a phenomenally well-designed language. When I first started go, I was incredibly excited to start learning it. From everything I'd heard, it was everything I was hoping to find in a language. The more I started using it, the more and more its poor design decisions and the hollow defenses of these decisions by its community started to grate on me. Rust, on the other hand, I was loathing learning. I'd already just learned go and was extremely disappointed with it. I really didn't want to learn something else in this language space that I assumed overlapped so much, and I really entered into it hesitatingly. But I am exceedingly glad I did — unlike with go, every day I used Rust I came to appreciate its design more and more. Features of the language seem to have been designed to coordinate and work with one-another, instead of all being bolted on separately without regard to how they'd interact. On top of that, Rust has some of the most friendly, dedicated, and talented developer community I've ever seen.
- zellyn 9y agoAside from the occasional partially misquoted and much-publicized opinionated statement from Go Team members, Go also has some of the most friendly, dedicated, and talented developer community I've ever seen. I'm more than fine with people preferring Rust. I'm fine with Go's choices rubbing people the wrong way. But the frequent caricature of the Go Team being condescending or clueless simply rings false to anyone who has enjoyed being part of the Go community, where kindness and ability abound. I'm always curious about the frequent ravings about how friendly the Rust community is. I'm super glad, and I love seeing (hearing) the reports from the Increasing Rust's Reach program on the New Rustacean podcast, for example. I'm glad Rust is so welcoming and friendly. But I guess for this (increasingly) greybeard, it's funny, because the whole thing seems so cyclical: the Ruby community back in the PragProg-induced-popularity days, and the Perl community back in the pre-Perl6 days had a similarly lovely feel (minus the more recent but oh-so-welcome proactive diversity bent). Anyways, enough ramblings. I'm glad Rust fits so well for you. I keep meaning to learn it properly by porting an Apple II emulator or something, but… time :-)