proposal: spec: else statement in assign statements #56895
Labels
error-handling
Language & library change proposals that are about error handling.
FrozenDueToAge
LanguageChange
Suggested changes to the Go language
Proposal
v2
An incompatible library change
Milestone
Author background
Related proposals
This proposal is about
else
statements in assign statements. It is exclusively borrowed from thelet-else
statement introduced in Rust RFC 3137, which is also based on Swift'sguard
statement.I haven't been able to find a similar existing proposals. Please close if duplicated.
Proposal
The goal of this proposal is to introduce a guard to simplify some very common error-handling patterns we frequently encounter when writing Go code. A short-hand way to return errors has been proposed a few times already (See #56628, #32437, #56165). I believe the existing proposals don't match 100% Go's mission for simplicity, correctness and readability.
Although introducing this feature could go against R. Pike's comment
Go does not try to be like the other languages
(See https://go.dev/talks/2015/simplicity-is-complicated.slide#9) I think the benefit is hard to ignore.Code examples:
The new
else
statement in a variable statement is easy to read and understand. It allows the developer to write code and think of its immediate error handling by moving the failure case into the body of the assign expression itself.Spec
Only the last value is evaluated as the
else
condition. The last value must implement theerror
interface or be typebool
Variable scope works as expected. Variables are not scoped to the
else
blockOnly available in
assign
statementsOnly valid for a single expression on the right hand of the assignment
It is possible to omit the last returned value in type assertions and map access (as it is already possible)
Motivation
Go's simplicity is great but that simplicity usually come with a cost of repetition, especially when talking about error handling.
Go does not support pointer to boolean conversion hence developers have to write the following block constantly
Although, this can be easily solved with a code snippet, codebases tend to be saturated by
statements.
The proposal avoids repetition of the
if err != nil
code. There is no nil to bool conversion as theelse
statement would internally evaluateerr != nil
as its condition.Readability is maintained or improved if considered that error handling is now part of the assignment statement.
Please refer to Rust RFC 3137 for more details on its motivation as I believe Go developers would agree with them.
Compatibility
Old code will continue to compile on newer versions of Go.
New code will not compile on older versions of Go unless this feature is back-ported to older releases or automated tooling will desugar it.
Costs
What is the cost of this proposal?
An additional rule to understand when assigning variables. Specifically the rule of evaluating only the last result returned by the right hand of the assign statement.
Would this change make Go easier or harder to learn, and why?
Go is already a very simple language to learn. The intention of this new assign expression could seem natural to understand.
The new expression is also intended to be optional and more of a syntax sugar.
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
Linters and formatters would require to be extended to support the new assign expression.
What is the compile time cost?
Probably none. Some compilation step could be affected but it depends on the implementation. A naive approach could imply a
desugar
step of the source code. Otherwise the cost would reside during parsing step, modification to the AssignStmt in Go's AST or a new type of expression would be required.What is the run time cost?
None
Can you describe a possible implementation?
I imagine extending the
AssingStmt
with anElse
statement field (similar to Else in IfStmt).The evaluation of this
Else
statement should work as expected when finding areturn
statement.The text was updated successfully, but these errors were encountered: