Hacker News new | past | comments | ask | show | jobs | submit login

I've been using go for a month now in a new job and hate it. It feels like they learned nothing from the past 20 years of language development.

Just one huge problem is that they REPEATED Java's million/billion dollar mistake with nulls. The usual way to get HTTP Headers using Go cannot distinguish between an empty header value and no header at all because the method returns "nil" for both these cases. They could've adopted option types but instead we are back to this 90s bullshit of conflating error types with valid values. If you're programming defensively, every single object reference anywhere has to be checked for nil or risk panicking now.. like why, after we literally named this a billion dollar mistake in Java, why would anyone fucking do this again?

We have helper methods in our codebase just do to this:

    fn checkThingIsA(ctx) {
      thing := ctx.get(thing)
      if thing == nil || thing != Thing.A {
        return false
      }
      return true
    }
In any sane language this is one line:

  ctx.get(thing).map(|x| x == Thing.A).unwrap_or(false)
In Go, we have to make helper methods for the simplest things because the simplest 1-liner becomes 4 lines with the nil/error check after. We have 100 helpers that do some variation of that because everything is so verbose that could would become unreadable without it.

I hate that they made and popularized this backwards dumpster fire of a language when we should know much better by now.




> The usual way to get HTTP Headers using Go cannot distinguish between an empty header value and no header at all

HTTP headers in Go are maps, which have a built-in mechanism for checking key existence, which distinguishes b/t empty and missing. No nils involved.

  if vals, ok := headers["Content-Length"]; !ok {
    // no content-length header was passed
  }


It looks like this idiom is specifically for maps, but the recommended way (by their own docs) to access Headers is using the `.Get` method, which canonicalizes header names before looking at the map. This method predictably does not support the idiom, because they made a stupid special case idiom that applies only to maps instead of using an Option type that would work in all cases, including custom types that might have similar requirements.

Like this doesn't work:

    nonexist, ok := req.Header.Get("X-Custom-Header")


Sounds like you're actually just mad that it didn't have generics from the beginning. That horse has been beaten to death for years.

I don't think it's fair though to characterize different points on a tradeoff curve as "stupid". If you're mad that you're forced to use a language with inappropriate tradeoffs for your context, then the right person to blame would be whoever picked it for your project to begin with.


I don't think your example is very compelling but I completely agree with your general point.

I read the Go book by Donovan and Kernighan and I have been working full-time in Go for the last year (my work is otherwise interesting so this is tolerable). It is painfully obvious that the authors are stuck in 1986 in terms of language design. Go is C with modernized tooling (in some ways it's worse...).

It's a horrible idea that has been extremely well executed. And the idea is essentially to make a language as easy as possible for people with imperative language brain damage to learn, make it as simple as possible and then make it simpler than that.

A good example is that despite taking almost everything verbatim from C, the authors decided that the ability to specify that some variable is read-only (i.e. `const`) is "not useful", so one of the few redeeming qualities of C is simply absent from Go.


Go does have const: https://go.dev/tour/basics/15


> people with imperative language brain damage to learn, ..

Perhaps this attitude is why function languages are not as popular as they could be.


Go as a language is not fun at all. Nor very good. Weaker type system and less language features that increase productivity and readability than C#, Java, Kotlin and Typescript, no null checks.

Go as a runtime is outstanding.

Go's tooling, stability and governance are very good.

Nothing is perfect. Enter into your compromise.


I understand the pragmatic point of view but that doesn't mean I can't point out its flaws or that this was some necessary compromise - it was a choice. There's no reason the Go platform couldn't be as stable as it is and also not be a braindead language from the 90s.

As an example Rust has its flaws but it does have all the modern language niceties with great tooling, build system and a solid platform.


Sounds like you are storing interfaces in the context. I wouldn't do that. I do hit the occasional nil reference error, but it is usually very rare. If you deal with concrete types, not interfaces, you don't have to worry about that very weird nil but not nil thing. And always use constructors.


I fully agree that Go's error handling needs improvement, but you have gone into a rage about the language while fully forgetting the VERY basic Go "comma ok" idiom used everywhere.

Please read Effective Go https://go.dev/doc/effective_go before making production software.


Your "sane" language looks quite insane to me, unreadable mess at a glance.


It almost looks like a Rust syntax to me, which is only one way to do that. A concise syntax is always possible if that's prioritized, like `(ctx.get(thing)? == Thing.A) ?? false` or `ctx.get(thing)?.(_ == Thing.A)`. Actual Rust programmers would also prefer to check against the explicit value whenever possible: `thing == Some(Thing.A)`.


Yes, language design should cater to people who have spent a little bit of time using and learning it, because they represent the majority of hours spent using that language. What a language looks like to someone who's never seen it is sort of irrelevant. That code could also have been written more imperatively, and probably would be by many people for those who don't like the functional style.


Not to talk about the lack of sake error handling in Go.


Saké is rarely an error.


I hate that they made and popularized this backwards dumpster fire ..

Well I think you should hate the fact that other language authors despite using better programming paradigm and using advancement in last 2 decades have not been able popularize their efforts enough to wipe out Go.

Go devs did what they did and made it open source. And from what I see they did not do any relentless marketing to make it popular.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: