3 ms·
Also OP missed the ever-present: defer s.Close() I assume it should be: defer func() { err := s.Close(); // handle error }(); Bu
by 0xABADC0DA 14y ago
Also OP missed the ever-present:
defer s.Close()
I assume it should be:
defer func() {
err := s.Close();
// handle error
}();
But how do you handle the error? Say the method returned successfully until the defer, do you then 'unreturn' the success return value and set the error return value? Return both a success and error value? Or say it returned failure, do you trash that value and replace it with the s.Close() error? Create some ad hoc meta error that contains both?
Error handling in golang is a total mess all by itself... then you throw panic/recover into the mix and it just gets worse.
EDIT: forgot hacker news readers get offended by "Google Go" so changed to golang.
- jlgreco 14y agoThe language is "Go", not "Google Go".
- oinksoft 14y agoPresumably code affected by an error state is also affected by a success state. The reasonable place to take action based on this result is directly in the async function, or otherwise in some callback.
- scarboy 14y agoYou can modify the state by using named return values. func ContrivedExample() (file *os.File, err error) { file, err = os.Open("something.txt") defer func() { if err = file.Close(); err != nil { file = nil } }() return }
- wonderzombie 14y agoThat is incorrect. session.Close() doesn't return an error. Still, there are cases where Close() methods return an error, so let's pretend it does. You're in the mess you describe above because you insist on making the wrong choice up front, which is to use defer for something which is non-trivial. If your error handling is so important, why would you bury it in an anonymous function? That's a bad decision in any language. Write it out explicitly. People will notice and give it due care because if it weren't special, you'd use defer. Look at sql.go in the standard library: http://golang.org/src/pkg/database/sql/sql.go?s=5813:5840#L202 http://golang.org/src/pkg/database/sql/sql.go?s=5813:5840#L2.... You can see that the error handling in such as putConn() and Close() do not use defer because it's the wrong choice. Conversely, if you grep the codebase for defer, there are plenty of places where it is useful.
- 0xABADC0DA 14y agoThe 'defer file.Close()' ignoring errors is used throughout the examples for golang so I assumed it was the same here. My bad. you insist on making the wrong choice up front, which is to use defer for something which is non-trivial. Closing a file is non-trivial? So you have multiple returns in the function and you also need to close the file... better repeat it several times instead of using 'defer'. I'm not sure what the point of 'defer' is if that is the case. Also the code you linked silently ignores the first N-1 errors, only returning the last one. Maybe in this case it is acceptable, but what kind of error does it return? Could the ignored errors be more relevant than the final one? Who knows.
- wonderzombie 14y agoI was just trying to argue in good faith by addressing the spirit of your criticism, not the letter of it. As I said, go and look at the prevailing usage of defer. Closing a file is trivial most of the time. When closing something (a file, net connection, db connection) you're really worried about, that's when you ought to think twice about using defer. That's really all I'm saying. I'm not sure what's wrong with multiple returns, as you're no worse off than if you were using exceptions. At least return is a standard, predictable mechanism which behaves the same regardless of what codebase you're in: exit the current function. You don't have to guess what file you need to look at next; control reverts to the caller. And, as far as the example code is concerned, it is completely orthogonal to exceptions vs. error codes. You still have to prioritize what's catastrophic enough to abort and notify the caller, and what isn't. The author decided those errors weren't important. So what's the big deal?