Hacker News new | ask | show | jobs
by solox3 3145 days ago
Novice here. Why is having no exceptions a good thing, in your opinion?
4 comments

In Go’s philosophy most problems are not exceptional. File can’t be opened? This is to be expected on systems with file permissions. The common pattern is for functions to return an error type as last return argument (Go supports returning multiple arguments). Programmers can then handle the problem right then and there if the error is not nil. This approach also helps to keep control flow straight forward. The happy path flows from top to bottom. If an error occurs, it is typically handled in an if-block. There are no nested exception blocks or exception blocks that follow each other and do things far removed from the exception’s origin in the code. As a result Go code looks very clean and is easy to follow.
It's actually pretty common for a file exception to be exceptional.

In all programs I've ever worked on you don't want to have to check useless junk like that and just want the general exception handler to handle it.

This isn't true at all depending on your work. I program software that has to work alongside other programs on busy file systems...failing to read/write a file is not someone else's problem...it needs to be handled, logged, there is potentially a retry and/or notification.
For exceptional, unforeseen situations you do have exceptions, aka "panic".

For signaling error conditions that the caller has to expect and handle, you have the `result, err = func(...)` idiom, and a compiler that would warn you if you forget to use the value of `err`.

If Rob Pike's opinion on this is not enough, here's Martin Fowler saying essentially the same thing: https://martinfowler.com/articles/replaceThrowWithNotificati...

In general: http://wiki.c2.com/?DontUseExceptionsForFlowControl

Go does not warn you if you forget to handle an error. It only does so if the function in question also returned a value that you're using. There exist important functions that don't return non-error values and report errors that you very much would like to avoid dropping on the floor: os.Chdir() for example.
While this is technically true, I've considered `errcheck` to be standard tooling for what feels like forever now, and it does exactly this; make sure you're checking your errors.
I’ve read the first article. It was eye opening, cause I am writing a bot right now and using exceptions to control input flow. Made me think about my design.

That said, it does not argue against exceptions. So, I am not sure what your argument is.

Exceptions are bad outside the "your computer just started burning" cases, but Go has replaced them with something even worse, "multiple return values".

So instead of some imagined return of "int or throw Exception" you now have "(int, error)", which basically means that the result of a function call can be any of these four options:

  - (   value, no error)
  - (no value,    error)
  - (   value,    error)
  - (no value, no error)
And due to the lack of Generics you can't abstract over your error handling.

And due to the lack of proper ADTs you can't even properly model "value OR error" manually.

The last case is rarely seen in Go (at least not in the standard library).

Accepting for the moment that Go has no exceptions and and error returns are the way to go, the first two cases make sense.

The third case ( value, error) is actually useful in several scenarios. For instance, considering you're writing bytes to a stream that fail partway. The value is the number of bytes return so far and the error is the error that was encountered. In fact, this is the signature that the ubiquitous io.Writer's Write method uses.

If all you had was single return values (aka "int or throw Exception"), how would you model the io.Writer?

> If all you had was single return values (aka "int or throw Exception"), how would you model the io.Writer?

This is not an problem, because a single return value is _not_ everything one has.

The last two options are not idiomatic Go. (zero, err) and (nonZero, nil) are. So the error check is almost always a simple `if err != nil {return err}`.
> The last two options are not idiomatic Go.

Who are the authors of https://golang.org/pkg/io again?

Yeah, 90% of Go devs agree with you.

10% think it is a really great idea.

So you can never be sure without reading the documentation.

Feels like Javascript callback error handling. Which was not much fun.
Just without the callbacks. At least you could abstract over error handling with callbacks...
Because it makes you handle errors by value, which makes you handle them one by one, and not group everything into one try statement.

This usually makes the error handling much better and better thought through.

You can see the same thing happening in all the functional languages using the Either monad instead of exceptions.

Exceptions are one of those things which are really nifty when programming in the small. However, they can create outsize problems when programming in the large.