Skip to content

proposal: spec: for/else block #73857

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

Closed
4 tasks
VoxelPrismatic opened this issue May 24, 2025 · 7 comments
Closed
4 tasks

proposal: spec: for/else block #73857

VoxelPrismatic opened this issue May 24, 2025 · 7 comments
Labels
LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee LanguageProposal Issues describing a requested change to the Go language specification. Proposal
Milestone

Comments

@VoxelPrismatic
Copy link

VoxelPrismatic commented May 24, 2025

Go Programming Experience

Intermediate

Other Languages Experience

Go, Python, JS, Lua

Related Idea

  • Has this idea, or one like it, been proposed before?
  • Does this affect error handling?
  • Is this about generics?
  • Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit

Has this idea, or one like it, been proposed before?

I could not find one similar

Does this affect error handling?

No.

Is this about generics?

No.

Proposal

Python has a "for/else" block, which will only run the "else" block if the for-loop hasn't been broken out of. I am not a fan of the "else" keyword, but the pattern of only running some code if a loop doesn't break is incredibly handy, so you don't have to keep track of a "success" variable

Language Spec Changes

https://go.dev/ref/spec#For_statements

For statements

A "for" statement specifies repeated execution of a block. There are three forms: The iteration may be controlled by a single condition, a "for" clause, or a "range" clause.

ForStmt   = "for" [ Condition | ForClause | RangeClause ] Block .
Condition = Expression .

changes to

ForStmt   = "for" [ Condition | ForClause | RangeClause ] Block [ "else" Block ] .
Condition = Expression .

(perhaps we could use the "default" keyword)

Informal Change

No response

Is this change backward compatible?

I believe so, but you can double check

Before:

broken := false
for e := range arr {
    // ...
    if cond {
        broken = true
        break
    }
    // ...
    if another_cond {
        broken = true
        break
    }
}

if broken {
    // only ran if never broken
    arr = append(arr, val)
}

// do more stuff with arr

After:

for e := range arr {
    // ...
    if cond {
        break
    }
    // ...
    if another_cond {
        break
    }
} else {
    // only ran if never broken
    arr = append(arr, val)
}

// do more stuff with arr

One such case is some sort of lookup in an array of structs, and creating a new such struct if one does not exist. Eg, editing an article. If an article does not exist, immediately create a new one and render the same edit page.

Orthogonality: How does this change interact or overlap with existing features?

It's mainly just syntactic sugar got managing a variable yourself

Would this change make Go easier or harder to learn, and why?

Coming from Python, it's easier, since it mirrors Py's existing syntax. Otherwise, no, because not many languages feature for/else blocks.

Cost Description

Intermediate, as now the compiler will have to keep track of an implicit variable before running the "else" block

Changes to Go ToolChain

minimal; gopls: same scope; gofmt: another indent block & follows if {} else {} chain; goimports: unchanged

Performance Costs

Minimal

Prototype

No response

@VoxelPrismatic VoxelPrismatic added LanguageChange Suggested changes to the Go language Proposal LanguageChangeReview Discussed by language change review committee labels May 24, 2025
@gopherbot gopherbot added this to the Proposal milestone May 24, 2025
@Mizommz
Copy link

Mizommz commented May 24, 2025

#73857

@VoxelPrismatic
Copy link
Author

@Mizommz is that supposed to be a reference to a different issue?

@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale May 24, 2025
@seankhliao
Copy link
Member

I think in Go where errors are values, the typical pattern is to use those directly rather than using an extra condition variable.

Given it's a python only syntax, it's not even clearer to the reader: on seeing it I thought it was only run of the for loop didn't execute at all.

@gabyhelp gabyhelp added the LanguageProposal Issues describing a requested change to the Go language specification. label May 24, 2025
@VoxelPrismatic
Copy link
Author

how do you find these tickets so quickly? searching "for else" gave me 20 pages

@VoxelPrismatic
Copy link
Author

oh, it's a bot.

@VoxelPrismatic
Copy link
Author

I think in Go where errors are values, the typical pattern is to use those directly rather than using an extra condition variable.

Given it's a python only syntax, it's not even clearer to the reader: on seeing it I thought it was only run of the for loop didn't execute at all.

Yeah, I wasn't a fan of the else keyword either. But the pattern is generally where a condition is never met, but not necessarily an error, since the case is handled immediately.

It is sparingly used, but is very handy when available. (But I suppose maybe there are better ways of writing code if no other language has implemented it)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee LanguageProposal Issues describing a requested change to the Go language specification. Proposal
Projects
None yet
Development

No branches or pull requests

5 participants