6 ms·
What is there to figure out about errors vs exceptions? I think the Go position on that matter is very clear.
by joncooper 13y ago
What is there to figure out about errors vs exceptions? I think the Go position on that matter is very clear.
- justinsb 13y agoAs I understand it, the position is that there are error return codes _and_ exceptions. Error return codes are for bad stuff, Exceptions are for really bad stuff. So correct Go code pays the price twice: it should be exception-safe, _and_ you have to manually handle error codes.
- tptacek 13y agoGolang does not have exceptions. It has "panic", which, you can see from the name, is meant to end a program's execution and is presumably "recoverable" only so that programs can wind themselves down (more) gracefully.
- justinsb 13y agoYou say panic, I say exception :-) My concern is not nomenclature, but that correct code must handle paniceptions. And that it must also handle return value errors. Go code IMHO ends up spending a lot of code on error handling, I think because of this double taxation.
- tptacek 13y agoYou say "setjmp", I say "thread library".
- pcwalton 13y agoI think you're misunderstanding justinsb's point a little bit. To be concrete, you have to remember to use "defer" in Go to clean up resources and locks, or else someone trying to use "recover" won't handle panics properly. This won't unlock the mutex on panic, which is observable if someone is trying to recover(): func F() { mutex.Lock() ... do something here that panics ... mutex.Unlock() } But this will: func F() { mutex.Lock() defer mutex.Unlock() ... do something here that panics ... } This is basically the same set of hazards as maintaining exception-safety in C++ or Java. So in this regard panic is very much like an exception system. (Of course, it has very different idiomatic use.)
- ansible 13y ago... To be concrete, you have to remember to use "defer" in Go to clean up resources and locks, ... You should probably be using defer() all the time anyway, unless you have a good reason not to. It also helps with code evolution, in the cases where some yahoo adds a new return statement in the middle of a function.
- beatgammit 13y agoBest practices for try/catch may be similar to idiomatic defer, but it's not the same semantically. For example, there's no analog to this: try { ... do something that throws ... } catch (...) { ... deferred code } ... other code If you don't use `catch`, then I could agree that try/finally is the same as defer, but I would argue that defer is a much cleaner design since cleanup code is located next to the thing they're cleaning up. I think it's much easier to audit this: mutex.Lock() defer mutex.Unlock() Than this: mutex.Lock() try { ... code that panics } finally { mutex.Unlock() } Other languages also make a distinction here, for example Python's `with` and D's `scope` [1]. Also, it's trivial to make a `panic` that is unrecoverable: `go panic("broke your code, lol!!")`. This just cements the idea that `panic` is semantically different than exceptions, and should be treated as such. [1] - http://dlang.org/statement.html#ScopeGuardStatement http://dlang.org/statement.html#ScopeGuardStatement
- pcwalton 13y ago> Best practices for try/catch may be similar to idiomatic defer, but it's not the same semantically. For example, there's no analog to this: You can do that by creating another function. > Also, it's trivial to make a `panic` that is unrecoverable: `go panic("broke your code, lol!!")`. This just cements the idea that `panic` is semantically different than exceptions. That's not different. In, say, Java, you can set the default uncaught exception handler to get the same behavior and then you can write: new Thread() { throw new RuntimeException("..."); }
- beatgammit 13y ago> You can do that by creating another function. You can't emulate the behavior of continuing the current block after an exception is caught. You have to recover() and copy/extract into a function any code that you'd want to run in the recover. For example: try { ... code that throws } catch { } ... other code In Go, to run "other code", you'd have to duplicate all of that logic in the recover(): defer func() { if err := recover(); err != nil { ... other code (duplicated from below) } }() ... code that panics ... other code This isn't really the same thing, but I suppose you could technically get the same effect if you move all of "other code" into a function and called that in both places, but you're still duplicating code. Panics and exceptions are two very different things, which is why there are different idioms in place to make working with them safe.
- mseepgood 13y ago> My concern is not nomenclature, but that correct code must handle paniceptions No, correct code doesn't have to handle panics. Panics are for programming mistakes.
- justinsb 13y agoSadly, you do, but Go makes it tolerable with "defer". Defer also produces nicer code. Without defer, to be correct you would have to explicitly 'recover' (and re-panic?)
- redbad 13y agoNo, you don't. You should never be using recover as a matter of course. You seem really hung-up on this point. Can you link to some code that illustrates your concerns?
- burntsushi 13y agoThat's just not true. There are very useful idioms for panic/recover, like when your code is profligate with errors (parsing, database work, etc.) It's even used in the standard library: http://golang.org/src/pkg/text/template/exec.go#L93 http://golang.org/src/pkg/text/template/exec.go#L93 (I use the pattern myself in certain situations. It's extremely useful.)
- redbad 13y agoNote I said "as a matter of course". I agree it's useful in certain very limited circumstances, like parsing. But certainly not database work, unless you have a very different idea of what that entails than I do. Link to code?
- burntsushi 13y agoIt's the same principle as parsing. Database work involves lots of querying, scanning, etc. All of these operations produce errors. In the work that I do, the response to an error is usually, "rollback, show error to user." This makes it ideal for panic/recover. (And this can work well for either command line applications or web applications.)