Live data from Hacker News

Ten years of “Go: The good, the bad, and the meh”

blog.carlmjohnson.net

271–280 of 305 posts

Re: Ten years of “Go: The good, the bad, and the meh”

#271
post #42

Go didn't try to be overly clever and abstract. That rubs quite a few people the wrong way, but it also means you are less likely to have to work with people who try to be clever. My first reaction when seeing Go is that it smelled of "old fart". It looked straightforward and unexciting. I'm an old fart. I like straightforward and unexciting. It tends to lead to code that I can still read 6 months from now. I want to…

Since when has "clever" become something negative? If someone is clever, that's a good thing! I also try to be clever when I do things, be it repairing something, planning my workout routine or programming.

Clever doesn't necessarily mean smart.

Back in the day when GCC 2.9.5 was a widely used version of GCC we had a codebase that was full of "clever" hacks to trick the compiler to generate the assembler code we wanted. A few of these hacks were used in tight inner-loops that had a huge impact on performance. I can still remember the day someone removed what seemed to be a no-op in a piece of code, compiled it and pushed it to production - only to have everything grind to a halt and fall over because CPU use per request tripled.

Sure, it was a "clever" way to get the compiler to output what you wanted it to output, and it was common knowledge among some of the programmers on the project what that no-op'ish line would do - but not all.

The smart thing to do would have been to fix the compiler and upstream the fix (from our internal branch of the GCC toolchain). The "clever" solution was to just figure out a bunch of tricks to manipulate the compiler and call it a day.

In the context of this thread, "clever" is mostly taken to mean "not as straight forward and understandable as it can be".

Young me loved cleverness.

Older me knows how frustrating it is when something isn't as straightforward as it could be. Either because I have to figure out how something someone else wrote works or because I have to explain what my code does to people who have gotten confused.

When I write code other people can't understand I see that as a failure on my part. Because it is. Code isn't merely a mechanism to convey meaning to a compiler, it is a way to communicate with other human beings. Most of which aren't that interested in indulging my cleverness.

Re: Ten years of “Go: The good, the bad, and the meh”

#272
post #109
post #42

Go didn't try to be overly clever and abstract. That rubs quite a few people the wrong way, but it also means you are less likely to have to work with people who try to be clever. My first reaction when seeing Go is that it smelled of "old fart". It looked straightforward and unexciting. I'm an old fart. I like straightforward and unexciting. It tends to lead to code that I can still read 6 months from now. I want to…

First time I used it, I called it 'C+-' after two weeks and a supervisord clone, but I really liked the language (except the module system). It was ~9 years ago, and other than that I only used it in coding interviews, as it's portable, simple, close enough to C that I'm not lost using it, yet simple enough that I don't introduce bugs carelessly every 30 loc. But it's a bit boring and I'll never use it for personal p…

Yeah, the original GOPATH stuff was atrocious.

Two questions:

1) how do you like the module system we have today? 2) can you expand on what you mean by boring, why it is important to you that a language not be boring, and give an example of a language that is not boring?

Re: Ten years of “Go: The good, the bad, and the meh”

#273
post #259

Earlier quoted context omitted.

If those people who 'actually write code' wouldn't have sprinkled their code with race conditions and buffer overflows maybe C would still be used widely for business apps, but reality is C code, while highly efficient, carries more risks than languages with training wheels. It's not contempt, it's coping with a reality where you can't afford to disqualify half of the programmer population because they're 'too junior…

It's a language for white-collar sweatshops ... more so than Java ever was. Ultimately this is a disservice to those with any talent as it leads to a work environment where they are relegated forever to the lower ranks (unless they give up coding and move into management).

I don't believe it's got anything to do with talent. The wiser programmers I know don't get emotional about 'training wheels' but try to prevent errors by systematically and automatically fixing weak spots. It's not about contempt but about making sure after you make a mistake nobody ever makes that same mistake again... Footguns are a waste of time regardless of how good you are at avoiding them.

Re: Ten years of “Go: The good, the bad, and the meh”

#274
post #131

Earlier quoted context omitted.

I am not aware of an option that "catches everything", in any langauge.

Any language with exceptions, checked or unchecked, will not allow errors to unintentionally get swallowed unless you write explicit code to do so. Rust and Zig's error handling also has the same property. This comes from experience working on large golang code bases, with error linters, and seeing errors silently and unintentionally ignored.

If you have an error being ignored accidentally and using errcheck, you need to file a bug for them with a test case for it.

If you mean that programmers caught the error and just made it "go away", convincing the checker that it was handled but in fact it was not, that's not something a language can solve. There is no amount of "forcing" a programmer to handle an error that they can't bypass.

Re: Ten years of “Go: The good, the bad, and the meh”

#275
post #194
post #158

Earlier quoted context omitted.

In ML-lineage languages (including Haskell) you almost never need any type annotations whatsoever, at least not unless you’re poking around at the fringes of those languages (GADTs, various GHC extensions). Type annotations for top-level definitions are often encouraged for readability and better error messages, but the compiler can almost always figure everything out itself.

From my experience, such type inference systems are awful in practice. Rust designers tried to do something like that initially but quickly realized understandability suffered greatly. You really do want to specify types manually, at least at boundaries, e.g. in function definitions. > Type annotations for top-level definitions are often encouraged for readability and better error messages, but the compiler can almos…

> You really do want to specify types manually, at least at boundaries, e.g. in function definitions

I think PureScript has the best compromise here, top-level type signatures are not enforced but if you don't include one you'll get a warning with the inferred signature. On the one hand, this is very helpful because sometimes I have a grasp for what expression I want to use, but am not sure about its type, so I simply comment out the desired signature and let the compiler tell me which direction I'm moving in, i.e. what's the type of what I just wrote. On the other hand, it being a warning also basically ensures nobody writes their top-level functions without the type signatures. Really the best of the two worlds. I think simply disallowing top-level functions without type signatures would hurt my workflow a lot.

Re: Ten years of “Go: The good, the bad, and the meh”

#277
Working with Python and Java over the years, I have this feeling that Go isnt battery included. Maybe I miss out 3rd party libraries I am very familiar with? For instance, Python has parse library to help parsing inputs without the need for RegEx. Java has lots of “common” collection libraries. I just feel exhausted coding the same from scratch in Go either because no such library exists or being told just copy and paste!

Re: Ten years of “Go: The good, the bad, and the meh”

#278

I am immensely thankful for Go. The simplicity of the language and the stdlib is shockingly well thought out -- things like io.Reader are so obvious and yet not part of many other languages. The language has made me a better programmer. And the cross-compilation story is chefs kiss . Working on a cross-platform project where in Go, I write code and it just builds. In Java, I fight with Gradle. In Swift, I fight the t…

For me the biggest unsung hero is the _stability_

There's something so liberating about finding code samples or documentation from 5-10 years ago and it is still the correct way to solve a problem. The lack of churn in the ecosystem means you can learn the language and then focus on actually building stuff rather than focusing on the rat race of learning the latest hotness and restructuring your app constantly to account for dependencies that break things.

Re: Ten years of “Go: The good, the bad, and the meh”

#279
post #244

Earlier quoted context omitted.

Java's designers have consistently mentioned the approach they're taking that Java has the last mover advantage. They cautiously see what features other languages applied, and take what gives them the highest value compared to the complexity introduced. Java's virtual threads are already superior to golang's approach because they're working on structured concurrency from the start. Value types are a huge proposition,…

> Java's designers have consistently mentioned the approach they're taking that Java has the last mover advantage. There's nothing one can do to wiggle away from designing something. You can only make tradeoffs. In this case, Java's sacrificing time. Is that a good call? I don't know. > They cautiously see what features other languages applied, and take what gives them the highest value compared to the complexity int…

> You can only make tradeoffs. In this case, Java's sacrificing time.

When you have billions of LOC, and take backward compatibility seriously, then that's a very valid approach. Furthermore, we've seen the Java team pick up cadence recently since switching to twice a year releases.

> They've historically shown poor taste in the features they've chosen,

Quite disagree. Which features are you talking about? They've shown very good taste in how records and pattern matching have been implemented for example. An also not jumping on the async bandwagon and opting for virtual threads instead.

> Already? Ten years later! Time matters.

Java had other approaches for dealing with heavyily asynchronous code, but it wasn't as ergonomic. And honestly speaking, the JVM already gives you access to native threads (something that neither golang (only "goroutines") nor python (GIL) for example offer), that unless you're doing heavy IO bound work, it's a non-issue to begin with.

> Go was built with its concurrency solution in mind

That is the claim, but in practice it is quite error prone. I was following golang from pre-release, and I voiced concerns about not having a way to declare immutable values (or at least something similar to C++'s const), but they didn't seem to care. Of course it came to bite them back[1]. Passing channels everywhere is tedious and verbose, and doesn't make it clear what the code is doing at first glance. Futures/Tasks are an easier abstraction to deal with, but of course golang didn't have generics until recently, and they still don't offer a future package.

> I've been hearing this for a while, has it been a decade yet?

You can follow the valhalla project to see what they're up to. It's sufficient to say that the pace picked up significantly on these large projects since switching to a twice a year cadence.

> You can't be serious. Complaining about another language's null problems from the perspective of Java?

Having worked on large golang codebases, I've seen first hand the issues that zero types cause in practice. At least a nullable in Java would throw an NPE instead of silently passing through the system and ending up with completely arbitrary behavior that is challenging to track down. Not to mention that you can use annotations to denote @NotNull in Java, something that golang doesn't have.

> It's a wash most of the time AFAIK. Unless we do the classic Java benchmark trick of ignoring memory usage.

Memory usage should improve with value types, but it also seems that people don't configure their JVMs properly (things like Xmx). In any case, they've also modified G1GC (and probably one or two more) to more aggressively release unused memory back to the OS).

[1] https://www.uber.com/blog/data-race-patterns-in-go/

Re: Ten years of “Go: The good, the bad, and the meh”

#280

Earlier quoted context omitted.

I've heard the drum against clever code for over a decade. This sums it up well: "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan

"If code is written as clevery as possible, it's surely written in a way that it's easy to debug it"... is what I would reply, but I get the gist. :-)

It's very unclear what people mean by "clever". For some people, a map or a fold is already "clever", while for others, this is just very straightforward code.
Post reply on HN