Live data from Hacker News

An Honest Review of Go (2025)

benraz.dev

131–140 of 184 posts

Re: An Honest Review of Go (2025)

#131

I think I know why Go ended up without good enum support. (Disclaimer, formerly worked at Google and used proto/grpc/go there and now in my own startup in github.com/accretional/collector which tries to address this problem with a type registry and fully reflective API. Not privy to the full history, just reasoning.) Proto is designed so that messages can be deserialized into older/previous proto definitions by clien…

Wha do you mean by “fixing this” or it being a design flaw?

I agree with the point about sequential allocation, but that can also be solved by something like a linter. How do you achieve compatibility with old clients without allowing something similar to reserved field numbers to deal with version skew ambiguity?

I view an enum more as an abstraction to create subtypes, especially named ones. “Enumerability” is not necessarily required and in some cases is detrimental (if you design software in the way proto wants you to). Whether an enum is “open” or “closed” is a similar decision to something like required vs optional fields enforced by the proto itself (“hard” required being something that was later deprecated).

One option would be to have enums be “closed” and call it a day - but then that means you can never add new values to a public enum without breaking all downstream software. Sometimes this may be justified, but other times it’s not something that is strictly required (basically it comes down to whether an API of static enumerability for the enum is required or not).

IMO the Go way is the most flexible and sane default. Putting aside dedicated keywords etc, the “open by default” design means you can add enum values when necessary. You can still do dynamic closed enums with extra code. Static ones are still not possible though without codegen. However if the default was closed enums, you wouldn’t be able to use it when you wanted an open one, and would have it set it up the way it does now anyway.

Re: An Honest Review of Go (2025)

#132
post #113
post #73

Earlier quoted context omitted.

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.

This is something gophers constantly repeat, but it is entirely a self-inflicted issue that other languages more modern than C don’t actually struggle with.

When in Rust, it is explicitly clear when and where errors can come up, and what types of errors I have to deal with. It is far less clear in golang, since there is no help from the type system when I’m using errors.Is and errors.As. Not being verbose doesn’t make error handling any less explicit.

Nobody is upset about having to pay attention to the unhappy path. This is entirely a straw man that gophers fall back to in order to feel like they’re somehow enlightened, shut down conversation, and to avoid having to consider what other people are saying. We are desperately hoping to help you realize that there are other, better ways that don’t come at the ridiculous readability costs inflicted by the anemic golang approach.

It really is okay to stop making excuses and accept that your preferred language has warts. I promise. Nobody will think less of you.

Re: An Honest Review of Go (2025)

#133

Earlier quoted context omitted.

> 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.

> I definitely prefer public private over case defined visibility.

And I think `public` and `private` keywords are a verbose mess that adds nothing to a language.

> You can't use an array for different types.

Yes I can. I even provided an example for exactly that: `[4]any` can hold references to any type.

> Matching _is_ useful

A lot of things are useful, doesn't mean they are used for that useful case most of the time.

> You can have explicit forced AND exhaustive error handling without exceptions

Go has wrapped and typed errors, covering exactly that.

Re: An Honest Review of Go (2025)

#134
post #26

> difficulty of writing if err != nil Literally the simplest way to deal with errors (cognitively and character wise). Since AI autocomplete entered the scene, typing this repetitive (for a reason) pattern became not a problem at all (I'm not even talking about post Claude Code era) > The only resort the consumer of this library has is to parse the string value of this error for useful information. Well, no. See for…

>> difficulty of writing if err != nil >Literally the simplest way to deal with errors (cognitively and character wise). Since AI autocomplete entered the scene, typing this repetitive (for a reason) pattern became not a problem at all (I'm not even talking about post Claude Code era) I agree with you. I don't have problems with the `if err!=nil` syntax. From my post: > It’s become something of a meme to bemoan the s…

It’s still an issue because the type system doesn’t actually help you out when you want to handle all the possible types of error.

Re: An Honest Review of Go (2025)

#135
post #113

Earlier quoted context omitted.

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.

This is something gophers constantly repeat, but it is entirely a self-inflicted issue that other languages more modern than C don’t actually struggle with. When in Rust, it is explicitly clear when and where errors can come up, and what types of errors I have to deal with. It is far less clear in golang, since there is no help from the type system when I’m using errors.Is and errors.As. Not being verbose doesn’t mak…

That's not a straw man, it's a valid reply to your first argument about "error handling code being an obstacle to understanding how function works". Why it makes you angry and makes you resort to ad hominem, I don't know, but that's clearly the end of the discussion.

Re: An Honest Review of Go (2025)

#136
post #135

Earlier quoted context omitted.

This is something gophers constantly repeat, but it is entirely a self-inflicted issue that other languages more modern than C don’t actually struggle with. When in Rust, it is explicitly clear when and where errors can come up, and what types of errors I have to deal with. It is far less clear in golang, since there is no help from the type system when I’m using errors.Is and errors.As. Not being verbose doesn’t mak…

That's not a straw man, it's a valid reply to your first argument about "error handling code being an obstacle to understanding how function works". Why it makes you angry and makes you resort to ad hominem, I don't know, but that's clearly the end of the discussion.

No, it is a knee-jerk response that invariably assumes that a belief that golang’s specific approach is bad is equivalent to believing that errors are of secondary importance, and assumes that anyone who disagrees with the golang approach just doesn’t get how important it is to deal with errors.

You would rather dismiss other perspectives out of hand than actually reflect on how your chosen language might evolve.

In my perspective, this has been the entire historical progression of golang. Everyone vehemently denies that there’s a problem, eventually the language authors address it, and then everyone insists that it’s always been known that they needed to deal with the issue.

I don’t know why this seems to be so endemic to the golang community. Other languages’ adherents seem more than willing to accept the shortcomings of their preferred tools. But gophers continually insist that all the problems are actually strengths right up until it’s fixed and then they retcon their previous beliefs. It’s extremely off-putting.

Re: An Honest Review of Go (2025)

#137

Earlier quoted context omitted.

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…

Yes, that's correct. The interface limits what guarantees the caller has about the type without runtime introspection. I don't think that really makes it any harder to handle expected error conditions though, since type assertions return a boolean. eg:

    if myErr, ok := err.(MyError); ok {
        // handle MyError case
    }
    ...
But you should always expect that there could be errors you don't expect to exhaustively handle with special logic.

Re: An Honest Review of Go (2025)

#138

Earlier quoted context omitted.

It doesn’t have the enum keyword, but there is an idiomatic way to make enums in the language. They just end up being typed constants.

When people say they want sum types, they generally mean they want both sum types and exhaustive pattern matching. Either of these features on isolation are nice to have, but both together are incredibly powerful to the point where having just one is almost not worth it.

Is this what people mean by Enums? I must not have used languages where Enums have those powers. I have often been very confused by statements people make about Enums so that would make some sense.

How do sum types address the problem that the underlying type (int or string or whatever) is totally capable of describing values other than those your code was compiled with? I'm mostly thinking of version skew with something like a dynamic library or plugin, although casting would probably also have the same effect.

Re: An Honest Review of Go (2025)

#140

One of the things I wish more people talked about isn't just the language or the syntax, but the ecosystem . Programming isn't just typing, it's dealing with dependencies and trying to wire everything up so you can have tests, benchmarks, code-generation and build scripts all working together well. When I use modern languages like Go or Rust I don't have to deal with all the stuff added to other languages over the pa…

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…

There’s cross-rs which simplifies things. But the main problem is less linker flags being unsupported and more cross compiling C dependencies somewhere in the dependency chain and that’s always a nightmare, not really anything to do with Rust (Go should have similar difficulties with cross compilation).
Post reply on HN