Hacker News new | ask | show | jobs
by jackosdev 1358 days ago
Just make it so:

varFoo, err := GetFoo()

if err != nil {

    return err
}

Can be written as:

varFoo := GetFoo()?

Just like Rust, everyone would stop complaining about Go error handling. But they have this absolutist position on syntactic sugar, even for something like this that would make the language that much nicer to look at and work with.

3 comments

While that may look good for a hypothetical example, I'm not sure how beneficial it is in real-world use. If your higher level functions are directly passing errors from your lower level functions then you start to bake implementation details into your abstractions which becomes a nightmare later when your implementation changes and callers are depending on those details. In reality, you need to deal with the error immediately and, if there is no better option, return your own error that describes the problem in a non-implementation-specific way.

It is possible that with other error-related features added to the language you could avoid those traps, but Go doesn't feature those either, so simply adding that construct without thinking about the problem much more deeply doesn't buy you much.

If you are solving a stop the world when you encounter an error-type problem that might be okay, although I'd argue that you may as well panic instead. But, again, Go isn't designed for those problems and I'm not sure it needs to be. There are already plenty of good languages designed for that type of work.

All of these things are better handled by good old exceptions (with optional checking, even). All in all, handling errors is often not possible locally -- there is no reasonable thing to do with a db connection error for example at its immediate caller.

The reasonable thing is perhaps to log it there at most, and bubble it up (possibly wrapped as you mentioned). It can be handled for example by a request handler, by returning a 50_ error.

Casting errors to exceptions (panic/recover) are considered a valid approach in Go within your application logic. Its built-in HTTP handlers will even 500 out of the box if a panic isn't recovered beforehand.

But other layers of abstraction lose their utility value if they start to make assumptions about the caller. Maybe in your web service a 50x stop the world error is all you'll ever need if there is a database error, but the next guy using the code for another purpose could have very different requirements and when you have to actually deal with errors, exceptions become a royal pain very quickly. As such, the official line is simply that you shouldn't let errors casted to exceptions cross package boundaries.

But, again, Go isn't really designed for stop the world programming and it's okay to use another tool if your problem space is suited to stopping the world.

I don’t get what you mean by stopping the world. An exception (in most languages) only interrupts the executing thread.
By the way, Vlang (https://github.com/vlang/v/blob/master/doc/docs.md), uses "?" as well with error handling. To include it had/has a number of Go wishlist features.

The nature and culture of Go makes it harder to change direction and be as amenable, but the merits of such conservatism is a "depends" type of thing and can mean incorporating things many years after it has become fashionable or accepted.

So if GetFoo returned a non-nil error, would the function abort and immediately return the error?

I'm used to a question mark being around null handling, but you know, JVM languages lol, null is thought about a lot.

Yeah exactly, it makes everything so much more ergonomic, especially with combinators, as in chaining method calls that might return an error
This has been used for ages, goddammit. The question mark idea kinda stops half way. In most of languages, the question mark is always there, implicitly. You have to add ugly code to say "this failure doesn't require bubbling up".

Go is an experiment in the exactly opposite direction: language puts pressure to really handle the error in a meaningful way every time. And if you bubble up, at least describe the situation a little bit better. Or explicitly give up and receive a penalty for that: the `return err` is nothing to be proud of, it's just a visual penalty for _lack_ of error handling.

I'm not saying it's better in every project, I'm saying it's valuable on some projects.