17 ms·
Go’ing Insane: Endless Error Handling
- majewsky 5y agoMore like "Endless Error Handling Blog Posts". For all the big talk about how horrible the error handling is, it's really not a big deal in my day-to-day (having written Go code pretty regularly for over six years now). For instance, if you have a function that does multiple things in sequence, how common is it to reorder the individual steps? Most times you have an intrinsic ordering between each step. And even if you reorder at some point, flipping some ":=" into "=" or vice versa based on compiler errors is not as big of a deal as the author makes it out to be.
- grenoire 5y agoI don't agree to the := and = issue, I think it's really bothersome primarily for the reasons that the author highlights. Unpacking is indeed inconsistent with its conditional bypasses on the := double-assignment checks. The committee's resistance against syntactic sugar like ? on this is also bothersome.
- janekm 5y agoI hadn't looked at go for a few years but := is terrible for several other reasons too: - small difference in visible syntax (easy to miss) - less clear than explicit var - most crucially, can't be used for const declarations but in most cases where it's used (including the blog post) const should have been used (return from a called function that won't be modified by the caller).
- Andys 5y agoIronically, "easy to miss" is my objection about Rust's "?" suffix
- janekm 5y agoIt's a fair point (and the same objection could be made to Swift's ! and ?). Over time I have given up my objections to verboseness... Clarity of code is far more important than conciseness. I do see the point for some syntactic sugar for error handling though, long if chains are terrible for clarity as well. And arguably ? and ! are typographic symbols our brains are well trained to spot.
- lm28469 5y agoYeah it's really not an issue irl. It feels a bit weird at first but that's just how it is and you learn to design with it, it's not a deal breaker by any stretch of the imagination. People have been talking about it forever because it's "how to shit on golang 101"
- simiones 5y ago> you learn to design with it There is nothing to learn - it's an ugly wart you have to accept if you're using the language. There's no going around the fact that it's verbose, error-prone, and makes code hard to read and review.
- rob74 5y ago...as opposed to error handling with exceptions, which is not error-prone at all and makes code really easy to review (or rather, it make it easy to get a false sense of security, and months later you find out that there is an exception you forgot to handle).
- thiht 5y ago> error-prone, and makes code hard to read and review. Strong disagree on that. The fact that it’s explicit makes it extremely easy to reason about and Go code reviews are a breathe. It’s verbose, I’ll give you that, but the rest doesn’t hold.
- samhw 5y agoIt's true that explicit code is good, but "Go code reviews are a breeze" was not remotely my experience. For me and my past teams, reading through piles of boilerplate verbiage like this - among other 'explicit' syntax - was more of an impediment to understanding the flow of the program. Personally I think what the above commenter said is pretty much spot-on, and typical of Go teams I worked in.
- lm28469 5y ago> my experience. > For me and my past teams > piles of boilerplate verbiage like this I'd love to have a look at your code because this isn't my experience at all. What's your background ? What's your team background ? Are you writing go code with the mindset of a java/cpp/whatever dev ? Have a look at the source code of the top 10 go github repos, you won't find any of what the blog post talks about, because it simply isn't the way it's done
- onionisafruit 5y agoWhen I was new to go I would have written one of these blog posts if I blogged. Over time I’ve come to appreciate go’s approach to errors. Nowadays I find it nerve wracking to write Ruby (my old daily driver). I would still like to find some way to make go’s error handling a little easier on the eyes, but I’ll take this over having to be constantly vigilant about handling every possible exception.
- kybernetikos 5y agoPersonally I think this is a massive footgun, at least somewhat affected by ordering: https://play.golang.org/p/oHFobaOexwR https://play.golang.org/p/oHFobaOexwR Of course, I know now that I was 'holding it wrong'.
- bitfield 5y agoThis piece is both good and original. However...
- mseepgood 5y agoThis person just does error checking, not error handling. Every single example in this post is a bare `return err`. At least wrap the error like `return fmt.Errorf("could not do foo: %w", err)`.
- shaan7 5y agoNote that this can quite problematic in scenarios where the caller wants to inspect the error (example: was the error an http timeout? or a server error?). Returning the error and letting the topmost call site handle that is usually better.
- mseepgood 5y agoThat's what `errors.Is` is for. https://pkg.go.dev/errors#Is https://pkg.go.dev/errors#Is
- simiones 5y agoIt would be interesting if anyone used error types in Go, but you'll be hard pressed to find libraries that do. return fmt.Errorf() all the way.
- noisem4ker 5y agoIn my experience, errors returned by the standard library and recent third party packages are fairly well discernible, although not in all cases. Note that you don't need custom error types, just exported Error instances. These were in use even before wrapping was introduced with Go 1.13 (2019); one had to compare or type-assert directly instead of unwrapping.
- lox 5y agoYou can use %w in fmt.Errorf to accomplish this.
- simiones 5y ago
- furstenheim 5y agoWhen dealing with go errors I like to give them proper names. barErr, fooErr. In the case of the article it fixes reordering (not that you do that a lot in real code). In real code it makes unhandled errors a compile error, because the variable is not used.
- doctor_eval 5y agoThat’s a great idea. I’m going to try that.
- ThePhysicist 5y agoError handling isn't that verbose in Golang compared to other languages. Sure, in Python or Java(script) you can just throw an exception and handle that in a try/catch loop, but IMHO that's worse than explicit error handling, and I don't think that it produces more legible code in general. And error handling that's baked into the type system (as e.g. in Rust or Haskell) also requires pattern matching to handle errors, which really isn't that different from Golang's "if result, err := func(); err != nil { ...} else { ...}" pattern.
- samhw 5y agoYou mentioned Rust: well, Rust has the question mark operator for this case, so you can automatically unwrap a Result<T, E> and return the Err<E> with only one character of code. I worked with Go for years, and it's just not true to say that Go's error handling is not unusually verbose.
- lu4p 5y agoMaybe that's just me, but I find the explicit returns easier to read.
- brundolf 5y agoA thing that helps is that syntax highlighters normally color the question mark differently, helping it stand out
- ThePhysicist 5y agoPassing just the error up the stack is also quite easy in Golang, just use a named error return value and assign to it: func test() (result interface{}, err error) { _, err = someOtherFunction() } The thing is, you probably want to handle the error eventually, and that is just as verbose in Rust [1] as it is in Golang (IMHO). One can of course debate if it's more pleasing to use a "match" operator than an if/then/else loop to handle errors, but to me the difference is marginal. BTW one could even mimick Rust's type-based errors in Golang by returning a single interface{} type that's either a result or an error and then using a type switch, but that seems just silly and I have never seen that in the wild. 1: https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/define_error_type.html https://doc.rust-lang.org/rust-by-example/error/multiple_err...
- FeepingCreature 5y agoIn my language (neat, but don't use it yet, it's pre-alpha), you can propagate error types by picking out the valid return type. For instance, if a function returns `(string | ErrorType) foo()`, you can declare a result variable as `string a <- foo();` ("pick `string a` from `foo()`") and it will automatically do "if (error) return error;" to handle the other case. Go could easily do that too if it weren't as afraid of "complex" features.
- jamespwilliams 5y agoMaybe it’s just Stockholm Syndrome, but IMO Go’s “verbose” error handling approach is a feature, not a bug. I think the expectation that every single error is handled and (importantly) wrapped explicitly is one of the reasons why Go and the Go ecosystem in general is conducive to writing robust and resilient systems. When writing Go, error handling is at the forefront of my mind, and not an afterthought, as it can be in other languages.
- nicoburns 5y agoHave you used Rust? Because it has the same explicit error handling, except it has syntax sugar (the '?' operator) which makes it painless. Additionally it's robustness is even better than Go's, as the Result type it uses for errors makes it impossible (compile time error) to access the return value without first checking for an error.
- toolslive 5y agoexactly! a little sugar would be most welcome.
- chrismorgan 5y agoFor comparison: fn my_func() -> Result<(), Error> { foo()?; bar()?; baz()?; Ok(()) } // --- let val = bar()?; println!("{}", val); // --- fn my_func() -> Result<i32, Error> { foo()?; bar()?; let val = baz()?; // ... more stuff Ok(val) } // --- fn my_func() -> Result<(i32, String), Error> { foo()?; bar()?; let (val1, val2) = baz()?; Ok((val1, val2)) // Those last two lines could even be just `baz()` or `Ok(baz()?)`. } Rather close to the world the author wants to live in.
- thiht 5y agoWhat happens if you want to log something before returning the error, or wrap the error, add some context or something ? Is there a way to override the ? operator? Or do you fallback to a matcher, which is roughly the same as Go error handling?
- andyroid 5y agoThey should have just named it errlang.
- joelbluminator 5y agolol
- kubb 5y agoI’d love discussions on programming languages to be done by people who know various languages with different paradigms. I feel a lot of the discussion is often around things that were in haskell for more than 20 years and we understand them and know how to handle them (in this case the Either monad). There should be a dumbed down version of Haskell that doesn’t make use of any of the math lingo in its documentation and maybe uses curly braces to make it more approachable to young-bloods.
- anentropic 5y agois https://rescript-lang.org/docs/manual/latest/introduction https://rescript-lang.org/docs/manual/latest/introduction close?
- kubb 5y agoSomething like this but for server side.
- gopiandcode 5y agoWhat you're looking for is OCaml: https://ocaml.org/ https://ocaml.org/
- kubb 5y agoYeah like OCaml, just without global lock, modern and cool and with fast compilation (can be at the cost of some convenience features). Ideally interop with something that has all the libraries. And without the imperative and object oriented parts.
- brundolf 5y agoLike Rust?
- kubb 5y agoLike rust, but purely functional and garbage collected.
- joelbluminator 5y agoWhy is Go syntax fugly though? I don't have anything against the language and it's actually on my study plan soon but jeez the syntax looks very unappealing to me.
- tored 5y agoHow so? Missing parenthesis for if-statements and such? Looks like a mix of Pascal and C, missing parenthesis but still have curly braces.
- joelbluminator 5y agoIt could be this blog post. No, I actually like no paranethesis for ifs (just like in Ruby). Maybe the rather alien := thing, I just need to get used to the language I guess, but I didn't get this nice feeling of elegance I got when I first looked at Ruby or Kotlin when looking at Go. I know it's completely subjective though.
- deleted 5y ago[deleted]
- stevefan1999 5y agothe designers of Go are all having Unix background (Rob Pike, Ken Thompson), and they need a language that is simple and stupid just like Unix, and so now you know how painful Go is, just like how painful Unix is when everything is text and files
- samhw 5y agoSomeone needs to write a proposal to make the program play the tune from Stayin' Alive whenever a function returns an error. That way the Go devs can still pretend it's the 70s, meanwhile the rest of us can sneak in some usable error handling underneath.
- etra0 5y agoI completely agree with you. I tried Go a few months ago and I was really surprised by its performance, build sizes and how easy is to write concurrent stuff, but the syntax really did throw me away. It's probably something a bit superfluous, but coming from Rust it's hard to enjoy Go's syntax.
- marcus_holmes 5y agoSo the author's problem really comes down to "I can't re-order things when I declare them with :=". So don't. Do it like this if you think the function order is going to change: func foo() error { var err error err = bar() if err != nil { return err } err = baz() if err != nil { return err } return nil } And the final "?" proposal doesn't actually deal with the errors. Part of the point of Go's error handling is to force us to deal with the errors. Endless "if err != nil {return err}" statements is kinda an antipattern in Go. Yes it's common, but I'm sure that's because we've been trained by exception handling to just pass the errors up. A better (but still not perfect) pattern is to wrap the errors: if err != nil { return fmt.Errorf("tried to foo the bar with parameter %s, failed with: %w", baz, err) } And obviously, an even better pattern is to actually deal with the error - retry after a delay? return a custom "abandon goroutine" error? Endlessly passing the errors up the stack until some function passes an incomprehensible error message to the user is what we're trying to get away from here.
- jesseduffield 5y agousing `var err error` at the top is a sensible solution, I'm surprised this isn't the norm. As for dealing with the errors, there is value in wrapping an error with a message at the source of the error, but much of what follows is just passing the error up to whichever function is responsible for handling it (which may be, as you say, retrying after a period), analogous to rust's `?` operator. There is a proposal for defining a general error handler (see https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md https://go.googlesource.com/proposal/+/master/design/go2draf...) but iirc that's in limbo at the moment
- nicoburns 5y agoIME, "retry after a delay" is often much more of an anti-pattern than "pass the error up the stack". That's how you get system's that take an age to do anything before eventually failing anyway (or worse, just leaving you with a perma-spinner). As a user, I'd much rather use a system that fails fast, and allows me to easily retry myself.
- divan 5y ago> This bloats functions and obscures their logic I start to enjoy those developers' cries realizing that error handling is part of the logic too. Sometimes even more important part. Great job, Go.
- thinkharderdev 5y agoI think the point is that while error handling is part of the program logic it is not necessarily part of every functions logic. Sometimes you just want to pass an error up the stack to be handled at some other error boundary. This is what Rust (with the ? operator and Result type) and functional effect libraries (Scala ZIO or cats-effect) provide. You can ensure at compile time that errors are handled somewhere but each individual function in the call stack can decide whether it wants to explicitly handle an error or just pass it up the stack. And if you just want to pass it up the stack then there is no syntactic overhead associated with it.
- gwd 5y ago> Sometimes you just want to pass an error up the stack to be handled at some other error boundary. Right, but I think the idea is that the programmer should think and decide every time whether that's what you want to do. I haven't programmed in Rust, but I suspect that people use the ? operator more than is ideal because it's so easy.
- thinkharderdev 5y agoProbably so, but I think as long as you ensure the error gets handled somewhere (rather than crashing the program) it is good tradeoff to make. That was the problem (IMHO) with unchecked exceptions in Java. You make everything an unchecked exception because constantly adding code to handle checked exceptions is annoying and verbose, but then if you don't handle the unchecked exceptions somewhere then they crash the JVM. This is where I think the Scala/Rust approach is best. The compiler can force you to handle the error somewhere but there is very little syntactic overhead if you want to ignore an error in any particular function.
- 5y ago
- tored 5y agotry/catch can be as much as verbose try { foo(); val = bar(); baz(); } catch (Exception $e) { // all lumped together, not good } try { foo(); val = bar(); baz(); } catch (RangeException $e) { // who is throwing what? } catch (NotFoundException $e) { // who is throwing what? } catch (SomeOtherException $e) { // who is throwing what? } try { foo(); } catch (SomeOtherException $e) { // very verbose } try { val = bar(); } catch (NotFoundException $e) { // very verbose } try { baz(); } catch (RangeException $e) { // very verbose }
- vips7L 5y agoThat’s only if you’re actually handling your exceptions. The author of the post isn’t handling errors he’s just propagating. When just propagating, exceptions have no verbosity: foo(); bar(); baz();
- masklinn 5y agoI don’t think “in the worst case scenario imaginable exceptions are as verbose as Go’s baseline” is much of a slam dunk.
- daoman 5y agoWow, that's an excellent illustration!
- YuukiRey 5y agoEver since I started writing Go professionally I've gotten into the habit of annotating errors in other languages as well. The difference between Go and Haskell is then mostly one of a few characters and some syntax differences. But conceptually it's exactly the same. Take the error returned by some function call, add a bit more context so I can differentiate this XYZ error from the others, then pass it along to the caller. I really couldn't care less about the details of how that happens and I find it puzzling that someone would write such a lengthy blog post about what is to me a completely trivial matter.
- azth 5y agoOther languages have stack traces, so you don't have to reinvent the wheel in an inferior manner.
- beltsazar 5y agoMany people criticize about the verbosity of Go's error handling — which I'm not a fan of, but I can still live with it — but no one discusses about a problem which I think more fundamental: It's too easy to ignore errors in Go. In exception-based languages, if you don't handle an error, it will be bubbled up and possibly kill the whole program. Similarly, in Rust if you handle an error "lazily" by `unwrap`-ping it, it will possibly terminate the entire program. In these languages, if an error happens in line X and it's handled "lazily" or even not handled at all, line X + 1 won't be executed. Not in Go. Ignoring errors might be okay if the zero value returned when there's an error is expected by the caller. For example: // If the caller expects the default value of `count` is 0, this is fine count, _ := countSomething(...) // return (int, error) However, in many cases the zero values are garbage values because the caller is expected not to use it if there's an error. So, if the caller ignores the error, this can be a problem which may lead to a very subtle bug which may cause data corruption/inconsistency. For example: user, _ := getUser(...) // return (User, error) // If there's an error, `user` will contain the zero value // of `User`: `{"Id": 0, "Email": "", "Name": "", ...}`, which is garbage. // So, if there's an error, the next line, which assumes there's no error returned by `getUser`, // may lead to a subtle bug (e.g. data corruption): doSomething(user) // Oops if `user` is a zero value This is partly due to Go's weak type systems (no sum types) and partly due to Go's dangerous-and-may-lead-to-a-subtle-bug concept of zero values. Someone might argue that good programmers shouldn't ignore errors like this. True, but good languages should be designed such that bad practices should rarely happen, or at least require more conscious effort. For example, to do similarly to the previous example in Python, you need to write: try: user = get_user(...) except: # Catch any exception user = User() do_something(user) In Rust, you can do: let user = get_user(...).unwrap_or(User::new()); do_something(user); In both languages, because there's no concept of zero values, you need to explicitly set a fallback/default value. While I understand why Go needs the concept of zero values (it treats errors as values but it doesn't have sum types), I think it does more harm than good. If a language treats errors as values, it'd better have sum types.
- ctvo 5y agoIsn’t there a Rob Pike quote for these? "Who cares? Shut up" It’s in the context of concerns from newer developers who don’t focus on what’s important. This is the same blog that gave us code smells, abstract more to hide it (https://jesseduffield.com/Type-Keys-Revisited https://jesseduffield.com/Type-Keys-Revisited) -- only to point out the possibly differing perspectives on software development. There’s a philosophy to the language that’s very clearly defined. You have many options these days on what you write in. You’re not changing how Go does error handling because you think it’s needlessly verbose.
- jesseduffield 5y agoThat definitely sounds like Rob Pike. As for changing how Go does error handling, there is actually a proposal in motion to do exactly this, with support among both devs and the language maintainers: https://github.com/golang/go/issues/21182#issuecomment-542416036 https://github.com/golang/go/issues/21182#issuecomment-54241...
- ctvo 5y agoThat looks like lukewarm support at best, on something that hasn't moved beyond an issue with little details, and is closed. I would not represent that as anything else. The entire process is captured here: https://github.com/golang/proposal https://github.com/golang/proposal
- jesseduffield 5y agoI'm not sure what you mean when you say closed: the proposal is clearly open, and the latest comment asking if anybody has issues with the proposal has no downvotes. That sounds promising to me. At the very least, it's clear that the language maintainers see an issue with the current error handling, given how much time they've spent working on proposals. The community also clearly cares: see https://twitter.com/_rsc/status/1146129898383302656 https://twitter.com/_rsc/status/1146129898383302656 Also, I see you amended your original comment with a jab against me for the type keys post. Not sure what to tell you there, I posted something, absorbed the feedback, and incorporated that into the blog. If you have specific issues with the latest post please let me know.
- deleted 5y ago[deleted]
- iainmerrick 5y agoI happen to agree with the author here, but I think Go has cleverly inoculated itself against this kind of criticism by driving away the sort of people who care about this kind of thing. People who use Go generally don't care about the tedious error handling or lack of generics or whatnot; people who do care about those things generally don't use Go.
- jesseduffield 5y agoI've thought about this too: different people have different values and I think I've found myself in a situation where Go simply doesn't align with my values. I'm not claiming that Go's values are therefore wrong, just that they're at odds with mine.
- iainmerrick 5y agoYes! I'm trying not to sound smug or divisive. Plenty of good software is written in Go so it obviously has something going for it. I'd love to hear from somebody who reluctantly tried Go despite initially caring about this stuff, and was won over.
- llimllib 5y agoI guess I would fit that bill, so I'll give it a shot. I still care about stuff like this, and there are definitely ergonomic improvements that could be made. I guess my feeling is that overall, for the programs I write (network services, broadly speaking), the benefits greatly outweigh the annoyances. on the positive site, in my experience, Go: - Is easy to learn - Has a relatively small surface area - Generates static binaries - Forces you to consider error handling - (I'm listing this as a benefit as well as it's a downside!) - Is pretty darn fast, both at build time and run time - Is mostly well documented (text/template documentation excluded) - Takes backwards compatibility seriously - Cross compiles easily - Has generally very good and fast tooling - Has superb network-related libraries - Has excellent support for concurrency on the negative side, it: - Is often not pretty or elegant - It does have an aesthetic of its own once you're used to it, but it's never as satisfying as nailing something exactly right in haskell or rust, or doing something highly dynamic and fancy in python or ruby - Sometimes resists nice algorithms and data structures - this is why I would never want to use it for data science, for example - Is very opinionated - if you want something it doesn't agree with, you just don't get that thing For much of the work I do, the positives outweigh the negatives. Maybe that helps?
- drakedrepar 5y agoI understand the criticism from the author, but he missed a simple case to make the flow a bit better when a function returns a value and an error: From the article: if val, err := bar(); err != nil { // ERROR: val declared but not used return err } fmt.Println(val) // ERROR: undeclared name: val If you want to use the val after the if, you could use it in an else: if val, err := bar(); err != nil { // ERROR: val declared but not used return err } else { fmt.Println(val) // this is ok }
- _pferreir_ 5y agoRust handles this quite nicely, with the `?` operator, which someone already mentioned in the comments. It's still as explicit as you want it to be, but made real easy by that small amount of syntactic sugar. Maybe Go should adopt something similar.
- wing-_-nuts 5y agoThe more I've used golang, the more I've had a creeping suspicion that 'the emperor has no clothes'. Go plays at being a system programming language, but it's really not. It's peers and competitors are languages like java and c#, not rust or c++. When you look at it from that lens, it fares badly. There's just a clunky feel that permeates the entire language, and it's creators seem to have no interest in addressing it. I've said it before, and I'll say it again. Golang is popular because it was written by Thompson, and embraced by google. You have a whole load of devs that will simply embrace anything with such a pedigree because it 'must be state of the art'
- AnimalMuppet 5y ago> You have a whole load of devs that will simply embrace anything with such a pedigree because it 'must be state of the art' That seems rather dismissive of people. The devs I know are not sheep. Now if you had said that we have a whole load of managers that will simply embrace anything because it 'must be state of the art'...
- chakkepolja 5y ago> You have a whole load of devs that will simply embrace anything with such a pedigree because it 'must be state of the art' Dude, at the end of the day I want something done. And golang has good libraries (esp network stuff), good IDE support, and compiles to single binary that's reasonably fast and easy to deploy. Show me another language that covers all these.
- wing-_-nuts 5y agoThe java and .net ecosystem come to mind if you're willing to have the java or .net runtime on your container (I never understood the big deal about binaries outside of embedded or other space constrained environments)
- chakkepolja 5y agoCommand line tools etc.. for some types of servers too, Go has the advantage of less memory usage and faster startup. That said, for internal web apps or websites etc.., PHP / Django / spring boot whatever sails the boat.
- lmilcin 5y ago> I want to live in a world where the function looks like this (...) Here the question mark tells us that if the function returns an error, we should return that error (...) Ever heard of exceptions? This is exactly what exceptions are made for. To allow you to write simple code but still make sure errors are propagated through your code. It also makes it easier to write code that has to run something regardless of an error (using try/finally), while still ensuring that error is passed through your function reliably. The question mark isn't necessary at all. Why would you pollute your code with additional character? It just says "I want to have a broken application that does not react to an error if I forget to put in a question mark"
- ghoward 5y agoNot GP. I think a great article detailing why exceptions are not desirable is http://www.lighterra.com/papers/exceptionsharmful/ http://www.lighterra.com/papers/exceptionsharmful/ . > The question mark isn't necessary at all. Why would you pollute your code with additional character? It just says "I want to have a broken application that does not react to an error if I forget to put in a question mark" I'm no Rust expert, but I think the compiler will error if you don't put the question mark?
- jurschreuder 5y agoIn other languages you have these endless try/catch things and then the error is all the way at the bottom away from the actual problem, plus it feels kinda hacky.
- bmn__ 5y agoWhat is going wrong in the Golang community that Duffield, who is a language designer and implementer, does not know about gofpher <https://news.ycombinator.com/item?id=25648031 https://news.ycombinator.com/item?id=25648031>? Not a rhetorical question; I really want to find out. Hackers, respond with your insights and speculations.
- honkycat 5y agoI agree with this sentiment, though I am glad that Go does not fall into the "throw/try/catch" trap and instead treats errors as variables. I think some sugar around this would be uncontroversial.
- fmakunbound 5y agoI don't get why folks go through such mental gymnastics and contortions to "think" that this strewn through their code bases is a good idea (or at least a slightly positive aspect of the language): if err != nil { return err } No language is perfect and not all are an improvement on languages that have come before. Just admit it's rubbish and move on.
- mohanmcgeek 5y agoThat's exactly what people do. Nobody likes iferr all over their code, but every other way is worse. Admit and move on is the status quo.
- jd3 5y agoIn 2019, Russ Cox acknowledged three of the most commonly reported Go pain points: > The top three pain points for Go users, in surveys and direct feedback, have been consistent for a number of years. They are: package management, generics, and error handling. We are working on all three. The first has been solved, the second is in the process of being solved, and the third has been addressed in two major proposals, both of which were rejected. I sympathize with the author's frustration, though I would argue that better error handling in Go is still being actively discussed and investigated. https://twitter.com/_rsc/status/1146129898383302656 https://twitter.com/_rsc/status/1146129898383302656 https://go.dev/blog/go2draft https://go.dev/blog/go2draft 1. Package management has, more or less, been solved through minimum version selection in modules/vgo. Though not everyone's favorite, at least it doesn't require a SAT-solver (dependency hell is NP-complete https://research.swtch.com/version-sat https://research.swtch.com/version-sat) https://github.com/golang/go/issues/24301 https://github.com/golang/go/issues/24301 https://go.googlesource.com/proposal/+/master/design/24301-versioned-go.md https://go.googlesource.com/proposal/+/master/design/24301-v... https://research.swtch.com/vgo https://research.swtch.com/vgo https://golang.org/ref/mod https://golang.org/ref/mod https://github.com/golang/go/wiki/Modules https://github.com/golang/go/wiki/Modules https://go.dev/blog/using-go-modules https://go.dev/blog/using-go-modules https://golang.org/doc/tutorial/create-module https://golang.org/doc/tutorial/create-module 2. Parametric polymorphism/Type Parameters ("generics") is/are being introduced into the language in 1.18, which is slated for release in early 2022. https://github.com/golang/go/issues/43651 https://github.com/golang/go/issues/43651 https://go.googlesource.com/proposal/+/master/design/43651-type-parameters.md https://go.googlesource.com/proposal/+/master/design/43651-t... 3. There have now been a couple of proposals to make error handling simpler and reduce boilerplate https://github.com/golang/go/wiki/Go2ErrorHandlingFeedback https://github.com/golang/go/wiki/Go2ErrorHandlingFeedback check/handle https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md https://go.googlesource.com/proposal/+/master/design/go2draf... https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md https://go.googlesource.com/proposal/+/master/design/go2draf... try https://github.com/golang/go/issues/32437 https://github.com/golang/go/issues/32437 https://swtch.com/try.html https://swtch.com/try.html https://go.googlesource.com/proposal/+/master/design/32437-try-builtin.md https://go.googlesource.com/proposal/+/master/design/32437-t... https://news.ycombinator.com/item?id=20339697 https://news.ycombinator.com/item?id=20339697 https://news.ycombinator.com/item?id=20100902 https://news.ycombinator.com/item?id=20100902 https://news.ycombinator.com/item?id=20454966 https://news.ycombinator.com/item?id=20454966 related https://go.googlesource.com/proposal/+/master/design/go2draft-error-inspection.md https://go.googlesource.com/proposal/+/master/design/go2draf... https://go.googlesource.com/proposal/+/master/design/go2draft-error-printing.md https://go.googlesource.com/proposal/+/master/design/go2draf... https://go.googlesource.com/proposal/+/master/design/go2draft-error-values-overview.md https://go.googlesource.com/proposal/+/master/design/go2draf...