3 ms·
Having exceptions means that every line in your function is a potential exit point, often without you being aware of it. This can lead to bugs when a non-atomic
by kgeist 2y ago
Having exceptions means that every line in your function is a potential exit point, often without you being aware of it. This can lead to bugs when a non-atomic operation is abruptly terminated, and you might not realize it just by glancing at the code.
When we were rewriting some code from PHP to Go, I remember that simply thinking about "what to do with err" led me to realize we had a ticking time bomb - one that could explode in production. We had never realized that a certain line of PHP code could potentially throw an exception, and letting it bubble up the stack would have resulted in data corruption. With Go's explicit error handling, this issue became immediately obvious.
- gf000 2y agoGo can abort at any point as well. Also, ignoring an error condition (by either forgetting about it, or simply doing the nice and tidy if err dance with no real error handling in place, just a log or whatever) is much worse and can lead to silent data corruption.
- Mawr 2y agoYou can abort via panic(), but that is expected to crash the application, which is perfectly fine. It's the act of attempting to catch the abort that is fraught with problems. While in Go that is rare, in languages with exceptions it's normal and expected. Ignoring an error condition is possible in Go, but so unlikely that it's not practical to worry about it. As an aside, not that it matters, but logging an error is one of the valid ways of handling it, depending on context.
- gf000 2y agoLogging can be a valid handling of error. I just don't believe that most errors can be handled locally so besides returning an error (bubbling up), not much can be done. Go makes this part of the happy path, so neither can be easily seen/reasoned about anymore. Exceptions do auto bubbling up, while languages with ADTs have more strictness than go, and often have some syntactic sugar/macro to help with the common case of returning the error (rust's ?).
- kgeist 2y ago>I just don't believe that most errors can be handled locally so besides returning an error Sure, but explicit error handling reminds you that the call may fail, and you may want to handle it in some way (or not - then you bubble it up). With exceptions, it creates the illusion of a simple linear flow.
- kgeist 2y ago>ignoring an error condition (by either forgetting about it We rely on linters to catch that, which is pretty easy to implement (no expensive intra-procedural analysis needed, which is the case with exceptions). >Go can abort at any point as well. Panics, unlike errors, are exceptional situations which generally should not be caught (a programming error, like index out of range). They're usually much rarer than errors.
- gf000 2y agoLinters can't know if a case has been properly handled or not. Just because it logs something it may or may not be the proper semantic way to handle that error.
- mike_hearn 2y agoIt's rather the opposite, it helps avoid bugs when something is terminated, e.g. by ensuring that if an exception is thrown it rolls back a database transaction. Generally you want to do several classes of things with exceptions in web apps: 1. Return a 500, possibly rendering a nice error page. 2. Log why it occurred. 3. Roll back changes you were making at the time in the database. And you might also want to do other things, like propagate the error via tracing, increment monitored metrics and many other things. All these are easily done with exceptions, and will often be done by frameworks for you. In desktop apps you may also want to trigger a crash reporter, display a sorry message to the user, and if the exception was inside something like a button click handler you may even be able to proceed safely too. Given the level of bugginess in untested error handling codepaths that crop up in languages without them, exceptions are definitely the way to go.
- kgeist 2y agoNot everything can be wrapped in a single transaction, though. The problem in question involved talking to other services. Frameworks wouldn't help out of the box.