Live data from Hacker News

An Honest Review of Go (2025)

benraz.dev

111–120 of 184 posts

Re: An Honest Review of Go (2025)

#111

Earlier quoted context omitted.

I like Rust. I don't like that for fairly basic things one has to quickly reach for crates. I suppose it allows the best implementation to emerge and not be concerned with a breaking change to the language itself. I also don't like how difficult it is to cross-compile from Linux to macOS. zig cc exists, but quickly runs into a situation where a linker flag is unsupported. The rust-lang/libc also (apparently?) insists…

Yeah, I've never seen an all-in-one language like Go before. Not just a huge stdlib where you don't have to vet the authors on github to see if you'll be okay using their package, but also a huge amount of utility built in like benchmarking, testing, multiple platforms, profiling, formatting, and race-detection to name a few. I'm sad they still allow null, but they got a lot right when it comes to the tools. Everythi…

Oh Go with Rust's result/none setup and maybe better consts like in the article would be great.

Too ba null/nil is to stay since no Go 2.

Or maybe they would? Iirc 1.21 had technically a breaking change related to for loops. If it was just possible to have migration tooling. I guess too large of a change.

Re: An Honest Review of Go (2025)

#112
post #19

I've only written a handful of production projects in Go so my experience isn't very deep, but I find the syntax to be the ugliest of any PL. The mixed capitalizing based on function privacy, to me, is awful (among other things, i.e. personally I loathe curly brace initialization/definition). I'm sure you get used to it? It doesn't help that it just feels very hacked together, from the wonky generics, the lack of use…

> The mixed capitalizing based on function privacy, to me, is awful Awful compared to ... what? `private` and `public` keywords? Ugly hacks like pythons `_` and `__`? > it just feels very hacked together > the wonky generics What exactly about the generics is "wonky"? "Wonky" is not a term defined in any programming textbook I ever read. And languages are not designed on feelings, especially when the design goal is t…

I definitely prefer public private over case defined visibility.

You can't use an array for different types.

Matching _is_ useful, no one uses matching just because it looks "cool".

You can have explicit forced AND exhaustive error handling without exceptions. Go actually lacks this.

Re: An Honest Review of Go (2025)

#113
post #73
post #68

Earlier quoted context omitted.

> The noise this pattern introduces Here is the thing... it's NOT a 'noise'. Untill you see handling 'error path' as noise, you will be trapped in searching magic bullet language solution to hide it. We've all been there.

Handling errors doesn’t have to be noisy. Handling errors the way golang requires is . When it takes five times as long to figure out how a function actually works (not only due to error handling, to be fair), the language has a problem.

Your last sentence makes sense only if you consider “happy path” to be what you call “understanding how function works”. A lot of programmers are annoyed that Go forces them to think about “error path” as equally important. Later many say that Go forces you to be the better programmer. But it takes time. In any case, saying “language has a problem” is a wrong frame for thinking about this design choice.

Re: An Honest Review of Go (2025)

#114
post #107

Not shilling for Go here but there are a few misconceptions in this blog post. In addition to the others mentioned: > All of these examples involve assigning to a constant a value known at compile time but none of them will work Maps are not known at compile time. Hash functions are randomized based on a seed only known at execution time. The hashed value of "HELLO" is actually different each time the program runs. E…

Doesn't protection from reassignment not exist in most languages anyways? In C++ you should be able to cast away the const. Realistically you probably can achieve this in any language with reflection. Unless a const is literally a compile time constant inserted through the program, it's likely able to be changed somehow in most languages.

You can definitely protect from reassignment in those languages (e.g. `final` in Java) but they don't completely prevent you from changing the underlying data. Rust would be one that comes to mind that has true immutability. I guess the Go maintainers just didn't want to go down that road, which I get.

Re: An Honest Review of Go (2025)

#115
post #89
post #69

I always felt like go channels were more of a clever solution than a good one. Goroutines are a pleasure to work with though.

I'm curious what the alternative would be? Python's threads/sub-processing almost requires IO queues to function well, and are nearly the same semantically as channels... I'm not saying these are "good", just wondering what alternatives look like?

One alternative is STM, software transactional memory which is modular and composable. I think Haskell was first to implement it but its also in Clojure and some Scala libs.

This is what ZIO's type safe version looks like https://zio.dev/reference/stm/ Scala's for-comprehension is syntactic sugar for calls to flatMap, map, and withFilter, similar to Haskell's do-notation.

Re: An Honest Review of Go (2025)

#116
post #60

Earlier quoted context omitted.

IMO, this is because Go succeeded at its intended to goal: to create a language that people with very little Computer Science (but some C/C++ programming) experience can be productive in. It eschews basically all abstractions that take more than 30s to explain to someone, which leaves a lot of really useful ones on the cutting room floor.

That’s fair. I came into Go relatively late and from a more Functional Programming background, so the language ends up being kind of annoying to me but that is probably not the case for others.

Don't get me wrong, I don't think it was a good goal. But that goal is the original sin of Go as a language, and most of the bad decisions that have been made in Go's design are in pursuit of it.

Re: An Honest Review of Go (2025)

#117

I'd encourage the author to spend more time learning Go. They've come to incorrect conclusions -- especially regarding errors. Read more of the stdlib to see how powerful they can be, e.g. net.OpError: https://cs.opensource.google/go/go/+/refs/tags/go1.25.5:src/... > The user now has an interface value error that the only thing > they can do is access the string representation of ... The only > resort the consumer of…

I use Go as my preferred language and I think the author is mostly right. There’s no way for me to know or even check what are the possible errors this function can return? Sure, sometimes a comment in the library might be illuminating, but sometimes not. I agree that errors as values that I can handle at the call site rarely feel useful. Some of the Is, As ergonomics have improved, but damn if coding agents don’t lo…

I feel that in general, in the past 20+ odd years there has been an over emphasis on complex control flow with errors.

Lots of different fine grained error types with complex logic spread out over several call layers.

ime it’s better to aim for simpler handling, which seems to match go

Re: An Honest Review of Go (2025)

#118
post #29

Correct me if I'm wrong, but the Error interface means you can display the error as a string, but you don't have to? Like the err.Error() is idiomatic if you just want to display something , but you could also use the error itself https://pkg.go.dev/errors#As here's an example that uses a field from your blog example error type: https://go.dev/play/p/SoVrnfXfzZy Also "In Go, errors are values. They just aren’t partic…

My guess is that the author hasn’t fully frocked how go interfaces work yet. Go errors implement the error interface, but that just makes them interoperable, it doesn’t mean that’s all they are.

Correct me if I am wrong, but does it not mean that they are type-erased though? The whole point of returning an interface is to perform type-erasure.

If I have

    struct S { X int }
    func (s *S) Error() string { ... }
but I return it as an error:

    func DoStuff() error
Then all the caller gets is an error interface. Without downcasting (`.(T)`/`errors.As`), you can only compare it to other instances (if the library author provided them) or see the string representation.

Re: An Honest Review of Go (2025)

#119

Error handling in Go is actually very nice. You do not have unhandled errors, not possible unless you really want to not handle the error. Now I even use it similar in Python, amazing how many errors I did not handle at all. But what got me into using Go is that there is no libc dependency, just system calls, static binary, that is just amazing. I can compile Go compiler in like few minutes. Rust I cannot even compil…

> You do not have unhandled errors

Are you joking? It's trivially easy to drop the err or just not handle it accidentally in ways that are essentially impossible in rust. Especially when people re-use the `err` variable.

Re: An Honest Review of Go (2025)

#120
post #79

Man this post is a rollercoaster. First half of the post I was absolutely starstruck by how amazing go is(I haven't had time to play with it myself yet), and was making mental note after mental note to try it out asap! Then I got to the second half of the post, with the things he didn't like about go. No enums? Wtf? Not having sum types is a lesser evil imo, it places you in the mediocre, but mediocre is mostly ok so…

>No enums? [...] We're stuck with magic numbers?

In go you don't strictly need magic numbers because you can define constants:

    type Status int
    const (
        IoProblem Status = iota // we start at zero and go down from there
        JsonParse
        ...
    )
The problem is that there is no exhaustiveness with these constant groups. The type Number is not a closed set of just IoProblem and JsonParse like an enum in C. It is just an int.
Post reply on HN