3 ms·
Yes, it's the ability to unwind the stack to an exception handler without having to propagate errors manually. Go programs end up doing the exact same thing as
by tadfisher 3y ago
Yes, it's the ability to unwind the stack to an exception handler without having to propagate errors manually. Go programs end up doing the exact same thing as "try/catch around multiple lines" with functions that can return an error from any point, and every caller blindly propagating the error up the stack. The practice is so common that it's like semicolons in Java or C, it just becomes noise that you gloss over.
- Mawr 3y agoThe difference is that all code paths are explicitly spelled out and crucially that the programmer had to consider each path at the time of writing the code. The resulting code is much more reliable than what you end up with exceptions.
- bootsmann 3y agoDo you really do that in practice, or do you just blindly go 'if err != nil return nil, err'? Because fundamentally the function you called can return different errors at any point so if you just propagate the error the code paths are in fact not spelled out at all because the function one above in the hierarchy has to deal with all the possible errors two calls down which are not transparent at all.
- throwaway894345 3y agoIn Go, no one really blindly returns nil, err. People very clearly think about errors—if an error may need to be actioned on up the stack, people will either create a named error value (e.g., `ErrInvalidInput = errors.New(“invalid input”)` or a named error type that downstream users can check against. Moreover, even when propagating errors many programmers will attach error context: `return nil, fmt.Errorf(“searching for the flux capacitor `%s`: %w”, fluxCap, err)`. I think there’s room for improvement, but Go error handling (and Rust error handling for that matter) seem to be eminently thoughtful.
- 4star3star 3y agoComing from dotnet, I rather like the Go pattern as you've described it. I would normally catch and error and then write out a custom message with relevant information, anyway, and I hate the ergonomics of the try{}catch(Exception ex){} syntax. And yes, it is tempting to let the try block encompass more code than it really should.
- throwaway894345 2y agoYeah, I was pretty skeptical when they added the error wrapping stuff to the standard library, and it still feels a little too squishy, but in practice it works very well. I prefer Go’s error handling even to Rust’s much more explicit error handling.
- Mawr 3y agoI don't see how it's possible to do it blindly unless the code gets autogenerated. If you're typing the `if err != nil` then you've clearly understood that an error path is there. There's no requirement for the calling function to handle each possible type of error of the callee. It can, as long as the callee properly wrapped the error, but it's relatively rare for that to be required. Usually the exact error is not important, just that there was one, so it gets handled generically.
- Capricorn2481 3y agoTheir point was writing `if err != nil return nil, err` is the same thing that stack traces from exceptions do, but with even less information. And if that's most of a Golang codebases error handling, it's not a compelling argument against exceptions.
- throwaway2037 2y agoI understand your sentiment. The debate of error codes vs exceptions will be debated until the year 3000, and further. One point to consider with exceptions: It is "impossible" to ignore an exception. The function implementation is telling (nay: dictating[!] to) the caller: You cannot ignore this error code. At the very least, you must catch, then discard. Another point this is overlooked in these discussions: Exceptions and error codes can, and do, peacefully co-exist. Look at Python, C#, and Java. In the standard library for all three, there are cases where error codes are used and cases where exceptions are thrown. Another thing about exceptions, especially in enterprise programming, you can add a human readable error message. That is not possible when only returning error codes. EDIT Inspired by this comment: https://news.ycombinator.com/item?id=40220147 https://news.ycombinator.com/item?id=40220147 I forgot about exception stack traces, including "chained" exceptions. These are incredibly powerful when writing enterprise software that commonly has a stack 50+ levels deep.
- Mawr 2y ago> One point to consider with exceptions: It is "impossible" to ignore an exception. The function implementation is telling (nay: dictating[!] to) the caller: You cannot ignore this error code. At the very least, you must catch, then discard. Error returns are no different, assuming a proper implementation like the Result type in Rust. The difference is, unhandled error returns are found at compile time but unhandled exceptions only show up at runtime, when it's too late. > Another point this is overlooked in these discussions: Exceptions and error codes can, and do, peacefully co-exist. Both Go and Rust have panics, which are basically exceptions that are generally not supposed to be caught. They are used for unrecoverable cases like running out of memory or programmer mistakes. There's otherwise no reason to mix the two. > Another thing about exceptions, especially in enterprise programming, you can add a human readable error message. That is not possible when only returning error codes. I don't really know what you mean, it's equally possible in both cases. If anything, the error return implementation that Go uses is probably the most optimal out there when it comes to error messages. Most look like: return nil, fmt.Errorf("opening file %s as user %s: %w", file, user, err) Whereas most exception code will just dump a stacktrace since that's the default.
- throwaway894345 3y agoGo programs generally do not “blindly prepare the error up the stack”. I’ve been writing Go since 2011 and Python since 2008, and for the last ~decade I’ve been doing DevOps/SRE for a couple of places that were both Go and Python shops. Go programs are almost universally more diligent about error handling than Python programs. That doesn’t mean Go programs are fre from bugs, but there are far, far fewer of them in the error path compared to Python programs.
- sethammons 3y agoThis matches my experience _hard_; there is simply no comparison in practice. Go does it better nearly every time