Hacker News new | ask | show | jobs
by bedobi 844 days ago
You're right.

Go is not simple, it is idiotically designed to deliberately exclude common sense features that ironically makes it less simple and more error prone to code in and read Go.

Other languages are objectively better than Go for every imaginable use case. Rust is better for embedded. Kotlin is better for back end. I could go on.

The creator of Go is very open and candid that he thinks his target audience, Google Engineers, are too stupid to use "advanced" features like oh I don't know, sane error handling? and any number of basic things other languages have.

I know how cringe it is to start flame wars about programming languages, but srsly, Go, PHP, Perl, JS and a few others really are objectively worse (for every context and use case) than widely used alternatives.

1 comments

> sane error handling?

Golang _has_ sane error handling. It just considers errors a normal and expected situation.

When you perform a http request, and the result is successful you expect the result to be assigned a variable, right? Then why would you expect non-successful outcome to be returned in a different way? Why is it different? Why do you unwind the stack? Something terrible happened? Definitely not, it's as real life as 200 OK.

For unrecoverable things golang has panics, and if you don't like the idiomatic way of handling errors, you can just throw them like exceptions.

100% agree, and Go gets oh so close

But the correct and only sane way to do this is Either<Error, Success> that you can then pass on, map over both or either of the two, flatMap to chain with other Eithers, fold into a single thing etc etc. Not endless sprinkling of

if err != nil { log.Fatal(err) }

everywhere (and no, those operations are not obscure, esoteric or difficult to learn or understand - they're the same for other types like Option, List etc and are trivial to learn in a day for people who aren't familiar with them)

+ not making the compiler distinguish between null and non-nully values (as eg Kotlin, Rust and Haskell does) in itself as well is inexcusable for a modern language

Btw, tried to implement Result[T] flatmaps etc, it looks uglier than err != nil

func myfunc(url string) Result[string] {

  tup := FromTuplePtr(http.Get(url))

  return FlatMap(tup, func(r http.Response) Result[string] {

    return Map(FromTuple(io.ReadAll(r.Body)), func(b []byte) string {

      return string(b)

    })

  })

}
I agree that the type system should be better. And for some reasons, golang didn't even implement proper tuple types. However, now with generics, you can actually do Result[T] with all functions you described.

> in itself as well is inexcusable for a modern language

In Go, you can assign nils only to pointers

What language typically returns the `Either<Error,Success>` you refer to here? I get (and love) the idea but have never seen it in official documentation (sure I could go off the beaten path and implement in my language of choice).

Also, did you come up with this on your own, or were you exposed to it?

not as many languages as you'd hope unfortunately, but plenty do (see eg other reply you got, there are more still including F# etc etc)

+ other languages get close, eg Kotlin has nullable types (which is a poor substitute) and Result (which is also poor because it's not a true Either)

that said lots of languages these days have libraries that do it (Arrow, Vavr and countless others)

IMO the killer simple language that Go tries and fails to be would be something like a Kotlin+Arrow with heavily reduced syntax and features, eg

no exceptions (use Either or a correct Result type)

no loops (use map, fold etc)

no nulls (use a correct Option/Maybe type)

etc etc

= in such a language, we learn that methods return things, those things will be what they say they are (guaranteed by the compiler), they will tell you what you can do with them, and if a program compiles, you can be pretty damn sure it works as intended

insert "all the languages are broken, I should create a new language" meme here...

C# gets pretty close with NRTs, pattern matching, terse record declaration and task-based async syntax, lambdas and Result libraries if you like those. Also nicely builds to self-contained binaries, both JIT and AOT.
> Why do you unwind the stack? Something terrible happened? Definitely not,

Definitely do.

In Go we just have to emulate it, badly, by manually writing code to forward the error up the stack so you can finally top-level print “error bad thing happen” or maybe some unholy stringification of wrapped errors possibly collected along the way.

Please explain how errors are fundamentally different so they require drastically different way of returning.
I still can't understand how anyone designing a language can defend self-rolled stack traces as a good thing.
You can in theory unwrap them but that seems to rarely be something people use in the real world