Hacker News new | ask | show | jobs
by hyperman1 2230 days ago
A few years ago I started to play with go. First impression was great. But a month or so in I started to having more and more doubts. As a Java/C++ programmer I was missing especially the generic collections. Slice and map are a good start, but not enough.

Then one day I had to implement the swap operation for sorting. Again. And I thought that even C's qsort was better, and WTF am I wasting my time on this half-assed language. I dumped it, tried rust, and even with its slow compile times I couldn't be happier.

Now a few releases later, they fixed sort so I can only implement compare. Sorry, it's not nearly enough. Essential parts are simply missing. Exhibit A is source code generation, a clear indication go isn't enough on its own. I'm not working with an ecosystem where my human time is less important than the language philosophy. I want to express a repetitive pattern in the language, and then never think about dumb bureaucratics again.

It was a near miss, though. SOme things are clearly correct. I want to look again when they finally have generics, and some basic collections. I hope that day comes and I can give it a new chance. But until then, less was simply not enough .

4 comments

It's interesting the things that people think are essential and the things they are willing to put up with. I'm willing to put up with writing my own sort.Interface, adding in a few lines of boilerplate for error handling, loops, and the odd linked-list/btree/etc. I'm not willing to script my own build system in an imperative DSL or deal with dependency hell a la Java, Python, C/C++, etc. I'm willing but very reluctant to use a language that requires me to write a bunch of scripts to automate publishing source code and documentation packages. I'm willing but very reluctant to use a language with minutes-long build times. I'm willing but very reluctant to use a language that where most packages are poorly documented, lacking even basic type information (looking at you, Python and JS). I'm willing but very reluctant to use a language in which the ecosystem is an absolute mess due to the pervasive use of inheritance. I'm unwilling to use a language that simply can't be optimized (and "just write it in C" or "just use multiprocessing" are only applicable to a narrow range of bottlenecks--good luck processing a large Python data structure, for example).

This isn't Go fanboyism; I've worked with lots of languages in my career, and I still get really excited and try new languages all the time, but they all tend to optimize for nice-to-have things (such as a type system that can handle those 1-5% of use cases where Go would have you drop to interface{}) in exchange for essential things like sane tooling. Rust stands alone as a possible exception, but only since it shipped non-lexical lifetimes, rust-analyzer, and a long tail of other improvements that have recently brought its usability down into a range that is acceptable for general application development.

I've worked with lots of languages as well and dependency management in Go is the worst.

Not being able to package build and runtime dependencies with proper versioning is an incredible pain.

>I'm not willing to script my own build system in an imperative DSL or deal with dependency hell a la Java, Python, C/C++, etc.

Ironically, the fact go tried to make me use GitHub as a stopgap package manager (& denied one was necessary) while they built their own was what made me run away screaming.

They've since fixed that but seeing them fail at what Perl managed in 1995 and what became standard is larger languages around the turn of the millenium in a brand new language in 2010 wasn't a great omen.

People scoff about "GitHub as a package manager", but it hasn't chafed me much. Moreover, the scoffing isn't very substantial--it's often some variation of "but GitHub goes down all the time?! You will never be able to build/distribute your software!", which is trivially refuted (the GitHub UI goes down all the time, but its git service going down is much rarer; you can use a caching proxy if you're really concerned about reliability of the git service just like you would with a more typical package repo; GitHub isn't necessary to distribute Go applications unlike Pypi/NPM/etc for Python/JS apps). There are probably lots of good reasons for why the GitHub model is inadequate, but for whatever reason these aren't brought up in the aforementioned scoffing and I haven't stumbled on them (e.g., I don't have any private repo dependencies for my projects, but perhaps it would be a PITA for those who do?).
>it's often some variation of "but GitHub goes down all the time?!

It was never about github's downtime. It was about having to manage the code of your dependencies yourself.

>you can use a caching proxy if you're really concerned about reliability

yay one more piece of infrastructure that will break.

>There are probably lots of good reasons for why the GitHub model is inadequate, but for whatever reason these aren't brought up in the aforementioned scoffing

I really think they were.

Go has been by far the worst language for me to deal with dependencies. Java probably being the best, especially if you factor in build times.
The sort library has been massively upgraded since you used it. There are a lot more helpers so you don’t need to reimplement the swap and less functions for each slice type.
Even if it does get generics, it's not enough to fix all the issues with the language.

Java and C# are getting native compilation soon (GraalVM, CoreRT), and when they do, it's hard pressing to see why anyone would settle for an inferior language (golang) over mature and better designed systems.

> I'm not working with an ecosystem where my human time is less important than the language philosophy. I want to express a repetitive pattern in the language, and then never think about dumb bureaucratics again.

Writing code is not where time is spent. Repeating oneself, duplicating code, is fast and easy. Debugging someones code that felt like "expressing" themselves through it however, takes time, and a lot of it.

I really have no idea why some people so often need to use generics, and similar, beyond the built-in map and slice/array, when I seemingly do not, even though I write Go as my full-time job. Sure there a lot of difference between apps/domains, but the bulk of the code is usually not that different.

Partially I agree,and I'm not happy to see this downvoted.

But more code written equals more code to read. Adding a field to a struct means modifying all the boilerplate too. It is all to common to forget just one place. Boilerplate plus maintenance attracts bugs.

Generics are easily overused and abused, but a well placed generic can save a ton of time.

As an example, and the pnly generic I wrote in a week, today I had to generate a ton of test data programatically in java. So I wrote roughly a 3 line method

  T select(int index, T... values)
and used it on each of the fields with different types like this:

  struct.anInt=select(i,0,1,INT_MAX);
This allowed me to quickly iterate trough all combinations of common and edge cases. If I had to specify all cases individually, there was no chance I'd exhaustively test every combinations.
I agree of course that there will always be situations where generics/expressiveness will be convenient. But my argument is about proportionality. I'd like to optimize for the 98% of the time spent, not the last 2%. It's like when people insists on buying an ultraportable laptop for work even though they'll never move it from their desk. - "But imagine how nice it will be that time I'll be on the train!".
Have you ever worked with sequences/iterators/generators or their abstractions? They make incredibly composable, portable, sound, and readable code. And most useful programs are built on patterns that can be optimally represented using them.

They're also impossible to implement and extend without generics.

If your mental model of writing a program is giving instructions to an abstract machine, generics may seem pointless. However if you're interested in representing a problem and its solution, and allowing the language tooling to translate that into an optimal list of instructions for an abstract machine - generics are pretty critical.

Kinda sad that this is getting downvoted, regardless of whether you agree it is certainly a cogent argument.
Whatever argument it's trying to make would have been better received without the blatant insults.