←back to thread

Go is still not good

(blog.habets.se)
644 points ustad | 6 comments | | HN request time: 0.001s | source | bottom
Show context
blixt ◴[] No.44983245[source]
I've been using Go more or less in every full-time job I've had since pre-1.0. It's simple for people on the team to pick up the basics, it generally chugs along (I'm rarely worried about updating to latest version of Go), it has most useful things built in, it compiles fast. Concurrency is tricky but if you spend some time with it, it's nice to express data flow in Go. The type system is most of the time very convenient, if sometimes a bit verbose. Just all-around a trusty tool in the belt.

But I can't help but agree with a lot of points in this article. Go was designed by some old-school folks that maybe stuck a bit too hard to their principles, losing sight of the practical conveniences. That said, it's a _feeling_ I have, and maybe Go would be much worse if it had solved all these quirks. To be fair, I see more leniency in fixing quirks in the last few years, like at some point I didn't think we'd ever see generics, or custom iterators, etc.

The points about RAM and portability seem mostly like personal grievances though. If it was better, that would be nice, of course. But the GC in Go is very unlikely to cause issues in most programs even at very large scale, and it's not that hard to debug. And Go runs on most platforms anyone could ever wish to ship their software on.

But yeah the whole error / nil situation still bothers me. I find myself wishing for Result[Ok, Err] and Optional[T] quite often.

replies(18): >>44983384 #>>44983427 #>>44983465 #>>44983479 #>>44983531 #>>44983616 #>>44983802 #>>44983872 #>>44984433 #>>44985251 #>>44985721 #>>44985839 #>>44986166 #>>44987302 #>>44987396 #>>45002271 #>>45002492 #>>45018751 #
1. tgv ◴[] No.44983802[source]
I find Result[] and Optional[] somewhat overrated, but nil does bother me. However, nil isn't going to go away (what else is going to be the default value for pointers and interfaces, and not break existing code?). I think something like a non-nilable type annotation/declaration would be all Go needs.
replies(2): >>44984123 #>>44985976 #
2. blixt ◴[] No.44984123[source]
Yeah maybe they're overrated, but they seem like the agreed-upon set of types to avoid null and to standardize error handling (with some support for nice sugars like Rust's ? operator).

I quite often see devs introducing them in other languages like TypeScript, but it just doesn't work as well when it's introduced in userland (usually you just end up with a small island of the codebase following this standard).

replies(1): >>44985960 #
3. tgv ◴[] No.44985960[source]
Typescript has another way of dealing with null/undefined: it's in the type definition, and you can't use a value that's potentially null/undefined. Using Optional<T> in Typescript is, IMO, weird. Typescript also has exceptions...

I think they only work if the language is built around it. In Rust, it works, because you just can't deref an Optional type without matching it, and the matching mechanism is much more general than that. But in other languages, it just becomes a wart.

As I said, some kind of type annotation would be most go-like, e.g.

    func f(ptr PtrToData?) int { ... }
You would only be allowed to touch *ptr inside a if ptr != nil { ... }. There's a linter from uber (nilaway) that works like that, except for the type annotation. That proposal would break existing code, so perhaps something an explicit marker for non-nil pointers is needed instead (but that's not very ergonomic, alas).
4. bccdee ◴[] No.44985976[source]
Yeah default values are one of Go's original sins, and it's far too late to roll those back. I don't think there are even many benefits—`int i;` is not meaningfully better than `int i = 0;`. If it's struct initialization they were worried about, well, just write a constructor.

Go has chosen explicit over implicit everywhere except initialization—the one place where I really needed "explicit."

replies(1): >>44992516 #
5. nothrabannosir ◴[] No.44992516[source]
It makes types very predictable though: a var int is always a valid int no matter what, where or how. How would you design the type system and semantics around initialization and declarations without defaults? Just allow uninitialized values like in C? That’s basically default values with extra steps and bonus security holes. An expansion of the type system to account for PossiblyUndefined<t>? That feels like a significant complication, but maybe someone made it work…
replies(1): >>45002737 #
6. bccdee ◴[] No.45002737{3}[source]
No, I'm saying the language should never permit uninitialized or undefined values in any context. Make `int i;` a compile error and force the user to write `int i = 0;`. Rust does this.