4 ms·
An issue with a Rust-like ? operator is that it is sanctifying the "result, error" return values. It's entirely possible to return three or four values from a G
by ferdowsi 5y ago
An issue with a Rust-like ? operator is that it is sanctifying the "result, error" return values. It's entirely possible to return three or four values from a Go method (if not common).
With generics Go is opening up the possibility of honest sum types. But, to be honest, I'm one of those people who are not upset by Go's error verbosity. The error shortcuts in Rust confuse me more often than not.
- kelnos 5y agoI don't think that's a problem. The semantics of `?` would likely be defined for any number of (including zero) non-error return values, followed by an error value as the last return value. And when you use `?`, the call site will return however many non-error return values there are. func foo() error { ... } func bar() (string, error) { ... } func baz() (string, int, error) { ... } func doStuff() error { foo()? s1 := bar()? s2, i2 := baz()? }
- akira2501 5y agoGo authors have explicitly stated that while the branches are clunky, they are so intentionally to make the points where your code branches much more obvious. I wasn't sold at first, but 6 months ago I decided to use it for a project where it's ease of cross-compilation was the deciding factor, and since then I have to agree. Anyways, you're entirely free to use a named return value in the second (or later) part of a multi valued := statement. An example is noted below, the clunky and obvious branches are there, but the intent and flow is obvious at a glance. Example: https://play.golang.org/p/56Jv9Cvrw-s https://play.golang.org/p/56Jv9Cvrw-s
- unscaled 5y agoThe "Go authors" (by that I assume you mean the Go team) have very explicitly stated that they view the current way Go does error handling as a major problem[1][2]. [1] https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md https://go.googlesource.com/proposal/+/master/design/go2draf... [2] https://github.com/golang/go/issues/32437#issuecomment-512035919 https://github.com/golang/go/issues/32437#issuecomment-51203...
- akira2501 5y agoI was referring to what is written in "Effective Go" which seems to contradict [1] on style. Effective Go, on if: https://golang.org/doc/effective_go#if https://golang.org/doc/effective_go#if
- unscaled 5y agoThe section that you're linking to in Effective Go does not state anywhere that "branches are clunky, they are so intentionally to make the points where your code branches much more obvious". It only promotes the concept that of using guard-clause style ifs that return an error and have no else clause, gradually eliminating each possible error condition. This style of programming was later termed in the Go community "Aligning the happy path to the left"[1][2] [1] https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88 https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea... [2] https://maelvls.dev/go-happy-line-of-sight/ https://maelvls.dev/go-happy-line-of-sight/ I wholeheartedly agree that this style makes code more readable and I have adopted it - and encouraged others to adopt it - in other languages besides Go. This style would stil be followed with the try or check/handle proposals. For instance, let's take the example: f, err := os.Open(name) if err != nil { return err } d, err := f.Stat() if err != nil { f.Close() return err } codeUsing(f, d) f.Close() return nil With the simple try proposal that would be: f := try(os.Open(name)) defer f.Close() d := try(f.Stat()) codeUsing(f, d) With OP's variant of the try proposal, using a question mark this is arguably even more readable (less noisy): f := os.Open(name)? defer f.Close() d := f.Stat()? codeUsing(f, d) As you can see, these proposal reduce - not increase - nesting, so they are completely in line with what Effective Go is saying.
- sagichmal 5y agoYou continue to assert that error handling adds noise to a block of code. This is an opinion, that's fine, but it's not an objective truth. In many many domains -- in fact the domains which Go targets -- error handling is equally important to business logic.
- sagichmal 5y ago
- trevyn 5y agoYou can return multiple values in a tuple or struct in a Result in Rust, e.g. Result<(String, String, u64), E>
- masklinn 5y agoGo does not have tuples (MRVs are special syntax because), so that would not be an option.
- masklinn 5y ago> It's entirely possible to return three or four values from a Go method (if not common). Not sure how it’s an issue, you just could not use the shortcut for this “not common” situation, or the case where the result is an actual product. That Rust added ? Did not make every developer forget how to process values. > The error shortcuts in Rust confuse me more often than not. I have a hard time understanding that. The desugaring is hardly complicated, and the semantics are straightforward.
- sofixa 5y ago> Not sure how it’s an issue, you just could not use the shortcut for this “not common” situation, or the case where the result is an actual product But the whole point of Go is that code is more often read than written, so legibility is paramount. Having a `?` operator alongside the traditional `if err != nil` would be very confusing.
- masklinn 5y ago> But the whole point of Go is that code is more often read than written, so legibility is paramount. Having a `?` operator alongside the traditional `if err != nil` would be very confusing. Are you confused by unnamed returns? By the ability to declare variables initialised or not? By there being two syntaxes to declare variables? By it being possible to elide types in declarations or parameters lists? Go is already full of shortcuts which I would say are more confusing and less useful than`?`
- murph-almighty 5y agoOne perk I've enjoyed with error verbosity is the ability to spit out different logs depending on where in the function you've failed. I'm not super familiar with the shortcut being described but if I could do something like: ```x := potentiallyBuggyFunction ? genericErrorHandler("log message here", http.StatusNotFound,...)``` Where the `?` is kind of like a null coalescing operator, it might help?