1. 14

  2. 6

    The talk from Rob Pike on simplicity in PL design given at the end of the article is worth watching. Less is more!

    1. 5

      Go doesn’t have exceptions, so the common idiom is for the function to return multiple values, the last one being an error. And, of course, the caller should check that error, and react appropriately.

      I don’t use Go much - can someone explain to me why this is preferred over a rust-style Result enum? It seems like returning a separate error value make it more likely that it will be ignored - is there a feature in the language to prevent programmers from ignoring the error?

      1. 7

        If a Go function returns a value and an error (e.g., (T, error)), then in order to get your T, you would need to explicitly ignore the error with _ as other posters have described. However, if a Go function returns only an error, then you can call that function without acknowledging the error at all. Note that the comparison with unwrap in Rust isn’t quite the same, since an unwrap will panic if there is an error, where as using _ to ignore an error in Go just swallows it and the program continues.

        The trade offs between Rust-style error handling and Go-style error handling basically boil down to where you stand on the type safety spectrum. More ceremony in Rust, but less likely to drop errors on the floor. There is also the “the type signature of the function more accurately describes the behavior of the function” aspect of it. On the Go side of things, error handling is enforced basically by very strong convention: if err != nil { return err } and that’s that.

        1. 4

          Using nullable tuples for something that is semantically a disjoint union? Bleh. Just seems like a really awkward way to do it. :/

          1. 3

            Yes and no. This argument has been litigated a billion times on the Internet already. You won’t drag me into it. :-)

        2. 3

          You will get a compilation error if you fail to ignore the returned error.

          You can experiment here: https://play.golang.org/p/9XSOZFGbzT

          I don’t know Rust, and I have only been using Go at work a little bit, so I can’t really compare and contrast their respective error handling methods.

          1. 6

            Rust uses sum types, so you do not need a separate return value for errors. Instead, you use the Result type, which has two variants, Ok carries a successful computation, while Err communicates an error. You can then pattern match the result in the caller using a match or use the ? operator to let errors bubble up.

            Also see: https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html

          2. 2

            You have to explicitly ignore it, doing something like x, _ := getX()

            1. 1

              Cool, makes sense. I guess the part that seems weird to me is that you are able to return both an error and a value. I also suspect that it’s slightly more common to ignore the error using _ than match or unwrap, but I don’t know if that’s actually true or not. I should probably just use go and figure out which one I actually prefer :)

              I am very glad that error handling is something that language designers are thinking about now though - this is far better than in languages like C and Python.

          3. 1

            “there’s no way to make a flag required”

            You can just check for it explicitly in main(), which is what everybody does.

            “No way to enforce initialization of some struct’s field”

            You can write a function to create instances of your struct and then just use that (like a constructor) instead, which will force you to fix all your calls to it if you add a new parameter to it.