Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: add token to syntax to reduce error boilerplate #25273

Closed
mccolljr opened this issue May 6, 2018 · 1 comment

Comments

@mccolljr
Copy link

commented May 6, 2018

Proposal

Reduce error boilerplate by enabling the use of the _! token as syntactic sugar to cause a panic when assigned a non-nil error value

val, err := something.MayError()
if err != nil {
    panic(err)
}

could become

val, _! := something.MayError()

and

if err := something.MayError(); err != nil {
    panic(err)
}

could become

_! = something.MayError()

Of course, the particular symbol is up for debate. I also considered _^, _*, @, and others. I chose _! as the de-facto suggestion because I thought it would be the most familiar at a glance.

Syntactically, _! (or the chosen token) would be a symbol of type error available in the scope in which it is used. It starts out as nil, and any time it is assigned to, a nil check is performed. If it is set to a non-nil error value, a panic is started. Because _! (or, again, the token chosen) would not a syntactically valid identifier in go, name collision wouldn't be a concern. This ethereal variable would only be introduced in scopes where it is used, similar to named return values. If a syntactically valid identifier is needed, perhaps a placeholder could be used that would be re-written to a unique name at compile time.

Justification

One of the more common criticisms I see leveled at go is the verbosity of error handling. Errors at API boundaries aren't a bad thing. Having to get the errors to the API boundaries can be a pain though, especially for deeply recursive algorithms. To get around the added verbosity error propagation introduces to recursive code, panics can be used. I feel that this is a pretty commonly used technique. I've used it in my own code, and I've seen it used in the wild, including in go's parser. Sometimes, you've done validation elsewhere in your program and are expecting an error to be nil. If a non-nil error were to be received, this would violate your invariant. When an invariant is violated, it's acceptable to panic. In complex initialization code, sometimes it makes sense to turn errors into panics and recover them to be returned somewhere with more knowledge of the context. In all of these scenarios, there's an opportunity to reduce error boilerplate.

I realize that it is go's philosophy to avoid panics as much as possible. They are not a tool for error propagation across API boundaries. However, they are a feature of the language and have legitimate use cases, such as those described above. Panics are a fantastic way to simplify error propagation in private code, and a simplification of the syntax would go a long way to make code cleaner and, arguably, clearer. I feel that it is easier to recognize _! (or @, or `_^, etc...) at a glance than the "if-error-panic" form. A token can dramatically decrease the amount of code that must be written/read to convey/understand:

  1. there could be an error
  2. if there is an error, we're not expecting it
  3. if there is an error, it's probably being handled up the chain

As with any syntax feature, there's the potential for abuse. In this case, the go community already has a set of best practices for dealing with panics. Since this syntax addition is syntactic sugar for panic, that set of best practices can be applied to its use.

In addition to simplification of the acceptable use cases for panic, this also makes fast prototyping in go easier. If I have an idea I want to jot down in code, and just want errors to crash the program while I toy around, I could make use of this syntax addition rather than the "if-error-panic" form. If I can express myself in less lines in the early stages of development allows me to get my ideas into code faster. Once I have a complete idea in code, I go back and refactor my code to return errors at appropriate boundaries. I wouldn't leave free panics in production code, but they can be a powerful development tool.

Discussion

I am open to any and all feedback from the go team and the community.

@gopherbot gopherbot added this to the Proposal milestone May 6, 2018

@gopherbot gopherbot added the Proposal label May 6, 2018

@mccolljr

This comment has been minimized.

Copy link
Author

commented May 6, 2018

Closing, and moving to #21161

@mccolljr mccolljr closed this May 6, 2018

@golang golang locked and limited conversation to collaborators May 6, 2019

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
2 participants
You can’t perform that action at this time.