Go: Proposal: spec: Bang! notation for error handling boilerplate

Created on 25 Jul 2017  路  9Comments  路  Source: golang/go

Proposal

Add p, q = foo!(a, b, c) notation equivalent to

p, q, err = foo(a, b, c)
if err != nil {
  return err
}

to reduce error handling boilerplate code.

This can simplify great amount of code and make it more readable and composable while preserving the full power of idiomatic error handling in Go. For example

func foo(a, b, c int) (*Foo, error) {
  p, err := mightFail(a)
  if err != nil {
     return nil, err
  }
  q := something(b)
  r := somethingElse(c)
  return &Foo{p, q, r}, nil
}

becomes

func foo(a, b, c int) (*Foo, error) {
  p := mightFail!(a)
  q := something(b)
  r := somethingElse(c)
  return &Foo{p, q, r}, nil
}

or even

func foo(a, b, c int) (*Foo, error) {
  return &Foo{mightFail!(a), something(b), somethingElse(c)}, nil
}
FrozenDueToAge Go2 LanguageChange Proposal error-handling

Most helpful comment

Having the control flow of the function disrupted by a tiny, one-character, 1-pixel-wide, almost invisible symbol placed in the middle of the line is not a good idea, IMO.

They did that in Rust: they had the try! macro and apparently it was too wordy, because in 1.13 they introduced the ? operator which does the same thing and is similar to your proposed !.

In my opinion, syntactic sugar that changes the control flow of the code should be much more prominent on the screen. At least a whole keyword, and certainly not placed in the middle of an otherwise plain-looking line of code.

All 9 comments

Multiple similar proposals have been made in the past, e.g. https://github.com/golang/go/issues/16225.

What sets your proposal apart? If you can't answer that question, it will likely be declined.

Looking through the Go2 issues, #18721 looks closest modulo the proposed here ! syntax.

The change is backwards compatible with Go1 and has clear semantics since it's only syntax sugar for the tons of if err != nil { return err } statements throughout Go code. The result is equivalent to how idiomatic Go error handling works but has the compiler generating all those if statements instead of having them manually typed.

Even if it's backwards compatible, such big changes to the language are not being considered for 1.X. If you look at the last few major releases, very few language changes have been made - and they were all very small.

Having the control flow of the function disrupted by a tiny, one-character, 1-pixel-wide, almost invisible symbol placed in the middle of the line is not a good idea, IMO.

They did that in Rust: they had the try! macro and apparently it was too wordy, because in 1.13 they introduced the ? operator which does the same thing and is similar to your proposed !.

In my opinion, syntactic sugar that changes the control flow of the code should be much more prominent on the screen. At least a whole keyword, and certainly not placed in the middle of an otherwise plain-looking line of code.

I agree, ! syntax might not be optimal and a keyword or some other alternative might work better. While I have no strong opinion about the syntax, I would really like Go2 to address the plethora of if err != nil boilerplate which in my experience is the most repetitive pattern in Go code.

I would really like Go2 to address the plethora of if err != nil boilerplate which in my experience is the most repetitive pattern in Go code.

Sounds like repetitive pattern is something wrong per se. I don't think so. Error handling is critically important from the correctness POV (I know I'm repeating myself from elsewhere). The desire to make important code less visible, or almost invisible as in this proposal, is IMO a mistake.

I agree with you that "error handling is repetitive but critically important". I see it the other way around: "error handling is critically important but repetitive" and this should be addressed.

Coming from Haskell where error handling is entirely implicitly handled by the bind function in the Maybe (or Either) monad, this proposal doesn't look that alien. Also the fact that Rust has an equivalent construct with the ? operator (as @ALTree mentioned), I think provides further validation of the usefulness of this idea.

Coming from Haskell where error handling is entirely implicitly handled by the bind function in the Maybe (or Either) monad, this proposal doesn't look that alien. Also the fact that Rust has an equivalent construct with the ? operator (as @ALTree mentioned), I think provides further validation of the usefulness of this idea.

Well, if Go, Rust and Haskell will do the same and even look the same - why should they exist as different PLs? ;-)

A better articulation of the above: https://www.youtube.com/watch?v=rFejpH_tAHM (much recommended if you've not seen it already.)

This is a known topic of discussion and this specific proposal is very similar to other proposals that have been made in the past. I'm going to close this one in favor of the general discussion that should happen in the context of Go 2 thinking.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

michaelsafyan picture michaelsafyan  路  3Comments

longzhizhi picture longzhizhi  路  3Comments

jayhuang75 picture jayhuang75  路  3Comments

mingrammer picture mingrammer  路  3Comments

rakyll picture rakyll  路  3Comments