3 ms·
if err != nil is continuously painful. f(g(), h()) with error handling takes nine lines, maybe twelve? Everybody has to use Errorf() everywhere or nobody gets a
by erik_seaberg 4y ago
if err != nil is continuously painful. f(g(), h()) with error handling takes nine lines, maybe twelve? Everybody has to use Errorf() everywhere or nobody gets a stack trace.
There are no stdlib filter/map/reduce yet, and generics are new enough that most people are still writing the same for-range loops over and over. Lambdas don’t capture loop variable values.
x, y := f() sometimes assigns and sometimes shadows an outer scope.
defer isn’t block scoped, you have to simulate the code to figure out which calls are stacked at this point. Hopefully they’re added deterministically, but you can keep deferring stuff in a loop if you want.
(This is aside from the many ways Scala and Kotlin are far more readable than Java.)
- johnisgood 4y agoI thought that "if err != nil" is much less common now because of the changes in error handling. I personally do like "if err != nil" better. I can easily ignore that when I want, and I can easily check if I am handling the error properly without any cognitive overhead.
- erik_seaberg 4y agoHave a link? I don’t see any changes in https://tip.golang.org/doc/go1.19 https://tip.golang.org/doc/go1.19 that seem likely to help. How do you easily ignore the majority of the screen? Is there an editor plugin that just doesn’t display those ifs?
- ainar-g 4y agoThe fact that you think that error handling should be ignored is probably what prevents you from seeing the point of the Go error handling. The point is that one should never only consider the happy path. That one should actually think about how things can fail, what to do about those failures, and how to report those failures with enough context to figure something out on the outside if no appropriate handing is available in the code. Stack traces only give you line numbers. Properly used explicit error handling gives you more context in which a failure occurred. Here's one example that might make it clearer: https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html https://commandcenter.blogspot.com/2017/12/error-handling-in....
- joshuamorton 4y agoYou can write custom exceptions too. If the only thing you're doing is saying `if err != nil { return nil, err }` anyway, which is what empirically the majority of go's error handling code does, yes, you should have a better way of representing that, whether it's a "?", ASSIGN_OR_RETURN, or exceptions, which take a single character, a single line, or a no characters at all, as opposed to golang's 3 lines of visual noise! Saying that "you can use custom error types to give finer grained error information" is great and all, but I learned that in my CS101 class, in Java, in like 2012. It's not fancy or better or good, except compared to C. Its a worse way of doing a thing that Java and Python (and...) have been doing for decades.
- ainar-g 4y agoOnce again, you're referring to the conditional as “visual noise” as opposed to the actual thing that reminds you that there is a bifurcation here. The point is not to do this: // Bad, most of the time. result, err := foo(x) if err != nil { return err } But to do this: // Better, most of the time. result, err := foo(x) if err != nil { return fmt.Errorf("performing foo on x = %v: %s", x, err) } This isn't noise. This is meaningful logic. That is what exception mechanisms seem to discourage, as they are invisible (unless you wrap every call to everything that throws into a try{}, but then it's not better than an if{} is it?), and this is what the ? operator in some languages discourages as well, because it adds no human- or machine-readable context. There must be syntax that indicates what to do when an error occurs, and that syntax must support addition of information about the context in which the error has occurred. And why not have the most basic conditional take the role of that syntax?
- 8n4vidtmkvmk 4y agoeven if you wrap in try catch its worse because it moves the error to the bottom, messes with your scopes, and you can't tell which line actually threw
- kaba0 4y ago
- ainar-g 4y agoI'm not sure what you're talking about. Besides the standardization of error wrapping, there weren't any changes to how error handling is done.
- ainar-g 4y agoMost of these are a part of the syntax though. When the parent comment talked about syntax, I'd assume that they said it the way most people say that Perl or Rust syntaxes are hard to read. I agree about defer and the walrus operator though. Both can be quite confusing at times, and I think that Go with block-scoped defer and no walrus would be a more consistent language.