6 ms·
We need a shortcut for the if x,err = f(); err!=nil { return _,err } pattern that is so common in go code. This is my biggest daily gripe and I work around
by PaulKeeble 5y ago
We need a shortcut for the
if x,err = f(); err!=nil {
return _,err
}
pattern that is so common in go code. This is my biggest daily gripe and I work around it with a snippet but so much of integration code is this or a variant of it which captures the stack trace and it constantly distracts from the main flow of algorithm.
- dullgiulio 5y agoPlease no. I am still fighting the battle of adding contextual information to the error using fmt.Errorf. I am tired of seeing SocketException: hostname.com as full error message.
- AYBABTME 5y agoThis, errors that are bubbled up should have some context added to them. Otherwise every error ends up being totally meaningless.
- stouset 5y agoI repeatedly fail to understand why golang proponents insist on flogging themselves into becoming human stacktrace authors. This is a solved problem the computer can do better than you, automatically, on your behalf. Certainly any shortcut syntax should not prevent you from adding human-curated context to your errors. But the current situation comes at an enormous cost, and I truly think there's a bit of Stockholm Syndrome going on here.
- kevinmgranger 5y agoNot that I agree with how Go handles it, but the computer is not always better at it. It's a tradeoff, a compromise, or a catch-22. If you use the full stacktrace, you could get 50 frames of irrelevant library code worsening the signal:noise ratio, hiding what the real issue is. If you write your own context, then when it _is_ a problem with library code, you're hopelessly lost. I think we need better tooling: the ability to add your own contextual information, to propagate errors explicitly but without boilerplate, and the ability to _choose_ the level of information you see afterward. We have log viewers that can filter out by severity level, why don't we have a standardization for stack traces to let you filter to what you want?
- feffe 5y agoIt's not the same thing. In Java and Python programs, especially Java programs, developers seems to think it's perfectly reasonable to present the end user with a 100 entries stack trace. This may be of use to the developer to debug issues but it's not a substitute for good error messages that are to be presented to the end user. I don't think Go errors are perfect either as you just tend to concatenate strings together but the information they include are more user friendly if done right, i.e. not just bubble up the error, but adding context that the user is aware of.
- pg_1234 5y agoLanguages that bubble errors up still let you catch and categorize the errors at the top, allowing for very presentable formats for the end user ... in fact, in my experience, because they don't have to deal with tiers of pointless boilerplate, devs put the effort instead into better end user/public errors. I say this as an ex-(for now)-Python dev, currently suffering though Go's tedious error handling.
- feffe 5y agoI agree that in theory the same is possible in languages that use exceptions but in my experience laziness often wins out. The exception is caught on the level where it's suitable to terminate the stack unwinding and deal with the error from the applications point of view. At that point it's too late to add user recognizable context to the error that what Go advocates by its design. My opinion is that a syntax shortcut such as "?" to just bubble up errors without adding context would still be useful. I would welcome it. There are cases where I find that no additional context is needed. I think the Go designers are afraid what it would lead to though (the laziness wins out hypothesis)
- OldHand2018 5y ago> especially Java programs, developers seems to think it's perfectly reasonable to present the end user with a 100 entries stack trace Try debugging something in Spark/DataBricks. It is so incredibly tedious; stack traces can easily reach 200 lines or more.
- geodel 5y ago> I truly think there's a bit of Stockholm Syndrome going on here. I agree in sense Stockholm Syndrome going on but not just for Go but with almost every technology including Go. When we have folks defending Rust slow builds, Swift breaking changes, Half-assed tooling for Scala, poor power management on linux laptops and on and on. It could mean either plain old stockholm syndrome or that people can work around these minor irritants and get main benefit of technology. Just like with anything else in life.
- AYBABTME 5y agoAttributing this to stockholm syndrome is a bit convenient and reductionist. Stacktraces are better than just bubbling up, and yes a mechanism to minimize if-err could also allow for human annotations. I'd love if Go had a stronger type system, but I know it'd probably come with longer compile times like Rust has. I think it's not a dogmatic take, and I think a lot of golang proponent do take the same nuanced position.
- jatone 5y agojust use pkg/errors? it includes the stack trace. there wasn't a need to include this in the stdlib thats all.
- deleted 5y ago[deleted]
- epage 5y agoIt can be done well, see Zig's traces [0]. [0] https://ziglang.org/documentation/master/#Error-Return-Traces https://ziglang.org/documentation/master/#Error-Return-Trace...
- ladberg 5y agoI don't see how those are mutually exclusive. You could do something like: x, err := f(); if err != nil return fmt.Errorf("More context -> %s", err) (I'm not attached to that specific syntax, it's just an example of a hypothetical one-liner)
- silisili 5y agoWhat shortcuts would you recommend? The pattern itself as written above is rather useless. What you end up with is a call 3 libraries deep that returns nothing but "EOF", and you have no idea what happened. In practice, you should really wrap every error return in a message and/or with a callstack. If the shortcut method can a) accomplish that, and b) avoid everything being nested, like try/except tends to do, I think I'd be more interested in the concept.
- morelisp 5y agoPlease no allocations hidden in the short syntax. I use `errors.WithMessage` / `fmt.Errorf` with `%w` often within my application's main execution flow, but I don't need a stack trace attached to every missing file, parse failure, or connection reset.
- silisili 5y agoApologies, to be more precise, my team wraps every error in a filename/line number pair, not an entire stacktrace.
- morelisp 5y agoWhat is the (moral or performance) difference between wrapping every error you return anywhere with a filename/lineno pair, and a stack trace? If anything, the stacktrace proper probably only needs to allocate once, at the lowest level.
- silisili 5y agoThe specifics of it are deep enough in runtime that I've never actually looked, but it's designed as a chain to return a specific caller - it looks like - _, file, line, _ := runtime.Caller(2) locTxt := fmt.Sprintf(" (at %s:%d)", filepath.Base(file), line) I think if the above on errors became a performance concern, I'd heavily rethink what I considered an error. But, it is also possible the systems we've designed are miles apart in function and philosophy.
- 0des 5y agoAbsolutely not.
- sethammons 5y agoDoing some analysis, "naked" if-err-return-err shows up in about 5% of error handling cases in my team's most critical service. The rest of the error blocks do something more (attempt a fallback, add context, log something, metric something, etc). This is code base that has been worked on for about 6 years, around 40k lines of code, 32 contributors, and over 450 releases. This is a legit production mail transfer agent. Take this as an experience report on a real system: that pattern is not as common as you think. 5% is pretty low.
- irq-1 5y agoCurious if there is a one liner that would cover 80%+ of the error handling: onerror add context and return ; onerror function(err) and return ;
- sethammons 5y agoError handling differs. But we try to move up metrics and logs as high as possible in the call chain. Handling an error may be a retry with a strategy, moving items to different queues, changing concurrency, potentially triggering jobs to run, feeding different events to event streams, and, of course, retuning errors to callers so they can programmatically respond.
- deleted 5y ago[deleted]