6 ms·
I've been reading about Go a lot lately, starting with Effective Go, and now the tutorial book Learning Go. (and periodically referring to the FAQ when I'm stum
by aschroder 14y ago
I've been reading about Go a lot lately, starting with Effective Go, and now the tutorial book Learning Go. (and periodically referring to the FAQ when I'm stumped by design decisions)
It's been enjoyable learning it, though I'm yet to write any code in anger with Go. I find some of the concepts around concurrency and OO design have really made me think about the way I write in other languages.
One thing I cannot quite make sense of though is the treatment of errors/exceptions. This article says:
"Exceptions make it too easy to ignore them rather than handle them, passing the buck up the call stack.."
But the example given seems to me to do exactly that:
if err != nil {
return err
}
Worse still if you forget to do something with err, or don't handle a specific err !=nil situation, it seems easy for control to flow past the error handling and into code that expects no errors.
Are there small, easily understood open source projects written in Go, that would provide tangible examples of the benefit of this error handling approach?
The learning materials thus far have not really convinced me, maybe code in the wild would.
- enneff 14y agoI don't think you'll be convinced until you have worked on a Go project of your own. Even then it might take a little while to fully see the point. Go's error handling model is simpler than exception handling. There are fewer surprises. That's pretty much it.
- frou_dh 14y agoDo you know whether any calls to the standard library panic over the package boundary? Edit - Things like regexp.MustCompile aside.
- 4ad 14y agoNo panics over package boundaries. Breaking this is almost sacrilegious in Go.
- frou_dh 14y agoYet the standard library does just that? Only on package regexp or elsewhere too? I'm not trying to say I know better than the designers, just that the waters are muddied by supposed rules being broken off the bat.
- 4ad 14y agoRegexp.MustCompile is for initialisation of global variables that is done before main starts. You need a different function than regexp.Compile because you can't process the error at this stage or level. The panic is for exiting the program, since you can't do anything else. It isn't destined to be recovered from.
- frou_dh 14y agoI understand why that's useful. Now, is it safe to say that nothing else in the standard library intentionally surfaces a panic? I'm not trying to troll: I genuinely want to establish this!
- burntsushi 14y agoYou have been mislead. Better advice for panicing in Go is to panic in truly exceptional or unrecoverable circumstances. For example, a programmer error (violating the terms of a function contract) is a perfectly reasonable justification for panicing across package boundaries. The Go standard library: grep -nrHIF 'panic(' /opt/go/src/pkg/* | wc -l 632 Note that this is somewhat inflated with a lot of `panic("unreachable")` calls. They are a symptom of the standard Go Compiler requiring a `return` on every code path of a function that returns at least one value. A `panic(...)` relaxes this requirement. In this case, a panic arising would indicate a bug in the package. Which is another good reason to panic across package boundaries :-)
- frou_dh 14y agoAlright, that makes more sense to me. Do you know if they intend to fix the need for phoney code paths? It seems odd that a language with nice support for first class functions and closures can't acknowledge when "if ... else ..." has complete flow coverage.
- jlgreco 14y agoThe idea, as I understand it, is to use panic/recover in truly exceptional cases to unwind the stack and handle error conditions, but to never do so across package/api boundaries. So essentially, use panic/recover as you would a much nicer version of longjmp. (I believe) the only thing panic/recover lack compared to a more traditional try/catch is typed catching, but idiomatic usage is much different. Honestly, I really like it. The typed-catching would be nice but the idiomatic usage of exceptions in languages like Java has always rubbed me the wrong way. Exceptions crossing package/api boundaries just seems wrong to me.
- danieldk 14y agoTo expand on that: one of the typical occasions you could use recover is in web applications, where you want a server to continue running even if something exceptional happened during the handling of a request.
- EdiX 14y ago> (I believe) the only thing panic/recover lack compared to a more traditional try/catch is typed catching, but idiomatic usage is much different. You can use reflection with recover to do it, the upside is that it's a more general mechanism the downside is that you need to manually rethrow exceptions you don't handle. BUT the bottom line is that the standard library doesn't throw exceptions. What you do in your code is really up to you, if you really think panicking across api boundaries is the right thing to do you can, there is no go police coming after you.
- burntsushi 14y ago> but to never do so across package/api boundaries. There are good reasons to panic across package boundaries. See my other comment. [1] [1] - http://news.ycombinator.com/item?id=4879994 http://news.ycombinator.com/item?id=4879994
- electrograv 14y agoI think the criticism with exception handling is that it's a bad idea to silently pass errors up the stack by default. This encourages deferring your problems to outer scopes, at which point you often aren't sure precisely what the error means (or you may not have known to expect it at all). With Go, although you can pass error codes up the stack if you want, you have to do it explicitly. This forces you to think twice before doing so. This is a key difference: exception handling subtly encourages ignoring errors and letting outer scopes handle them, while error codes force you to deal with your problems within the immediate scope, and then decide what to do from there explicitly.
- burntsushi 14y agoEh, I don't think this is a good characterization of exception handling. It's certainly an accurate portrayal of exception handling in some languages---like Python---but in a staticly typed language like Java, I believe exceptions are quite explicit. (i.e., if you don't handle an exception, or explicitly state that you are ignoring it, the compiler will complain.) Although it's been a while since I've used Java, and if this is no longer true, I'm sure I could find a language in which it is true. Personally, I would be OK with that kind of exception handling. I also enjoy Go's error handling. I think Python's exception handling is abhorrent and it constantly bites me in the ass.
- electrograv 14y agoIt's been a while since I've used Java too, but I don't remember it requiring try..catch around ALL code. If you don't catch immediately, it defers the error to somewhere up the stack. This is what I meant by "ignoring" exceptions being the default behavior.
- shoopy 14y agoIf you don't catch a checked exception in your code, then you need to pass the buck to your callers, by adding a "throws" clause into the method signature.
- 14y ago