Go lacks a construct comparable to "with" in Python, or WITH-OPEN-FILE in Lisp, to guarantee that things get closed out on scope exit. Go has "defer", but that's a clunky replacement. You have to explicitly write the "defer", and it's always function-scope, not construct-scope.<p>Most of the problems with exceptions in C++ come from the C++ memory model - allocation and deallocation in exceptions are usually painful, and care must be taken to clean up and unlock things. Go doesn't have that problem - it's garbage collected.<p>Go does have "panic", which is Go's answer to "longjmp". People keep trying to use that as an exception mechanism, which is not a good thing.<p>Python seems to have the best track record with exceptions. Python's usual problem with exceptions comes from library functions which, under some rare circumstance, raise an unexpected exception and take down the whole program. This is mostly a legacy problem due to the poor original design of Python's exception hierarchy. You would like, for example, for everything that can possibly go wrong with an HTTP read or a network operation to be a subclass of EnvironmentError, as caused by an external event or data. That wasn't the case originally. There are still problems in Python 2.7 with getting a ValueError because some low-level data item was bad UTF8 or something like that.<p>The trouble with the "errors are values" concept is that error details tend to get lost as errors propagate upward. This came up yesterday on HN in connection with network errors for GoGo's airborne networking service. I once argued that D's error type should have a "why" pointer slot, so that, when you passed an error upward, you could link the lower-level error to the higher level error. The error message printer would then list
out the errors, yielding something like<p><pre><code> Unable to complete transaction
because database update failed
because database connection was lost
because of network error "Host down".</code></pre>