logoalt Hacker News

jchwlast Wednesday at 5:59 AM2 repliesview on HN

I strongly do not like try/catch. Just to list the limitations of exceptions that come to mind,

- try/catch exceptions obscure what things can throw errors. Just looking at a function body, you can't see what parts of the functions could throw errors.

- Relatedly, try/catch exceptions can unwind multiple stack frames at once, sometimes creating tricky, obscure control flow. Stack unwinding can be useful, especially if you really do want to traverse an arbitrary number of stack frames (e.g. to pass an error up in a parser or interpreter, or for error cases you really don't want to think about handling as part of the normal code flow) but it's tricky enough that it's undesirable for ordinary error handling.

- I think most errors, like I/O errors, are fairly normal occurrences, i.e. all code should be written with handling I/O errors in mind; this is not a good use case for this type of error handling mechanism—you might want to pass the error up the stack, but it's useful to be confronted with that decision each time! With exceptions, it might be hard to even know whether a given function call might throw an I/O error. Function calls that are fallible are not distinguishable from function calls that are infallible.

- This is also a downside of Go's current error handling; with try/catch exceptions you can't usually tell what exceptions a function could throw. (Java has checked exceptions, but everyone hates them. The same problem doesn't happen for enum error types in Rust Result, people generally like this.)

(...But that's certainly not all.)

Speaking just in terms of language design, I feel that Rust Result, C++ std::expected, etc. are all going in the right direction. Even Go just having errors be regular values is still better in my opinion.

(Still, traditional exceptions have been proposed too, of course, but it wasn't a mistake to not have exceptions in Go, it was intentional.)


Replies

9rxlast Wednesday at 5:29 PM

> but it wasn't a mistake to not have exceptions in Go, it was intentional.

It does have them, though, and always has. Use is even found in the standard library (e.g. encoding/json). They are just not commonly used for this because of the inherit problems with using them in this way as you have already mentioned. But you can. It is a perfectly valid approach where the tradeoffs are acceptable.

But, who knows what the future holds? Ruby in the early days also held the same preference for error values over exceptions... Until Ruby on Rails came along and shifted the prevailing attitude. Perhaps Go will someday have its "Ruby on Rails" moment too.

show 1 reply