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: spec: support new form of switch statement during variable assignment which jumps to function-wide case blocks #65019

Closed
bsoudan opened this issue Jan 8, 2024 · 2 comments
Labels
error-handling Language & library change proposals that are about error handling. LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal Proposal-FinalCommentPeriod
Milestone

Comments

@bsoudan
Copy link

bsoudan commented Jan 8, 2024

Proposal Details

Support a new form of the switch statement during variable assignment, which will jump to function-wide case labels. Intended to ease the boilerplate of repeated error checks, but probably has other applications as well.

Go proposal template attached at end.

Code sample

@rsc's CopyFile example from https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md becomes:

func CopyFile(src, dst string) error {
	r, switch err := os.Open(src)
	defer r.Close()

	w, switch err := os.Create(dst)
	defer w.Close()

	_, switch dstErr := io.Copy(w, r)
        switch dstErr = w.Close()
        
	return nil

case dstErr != nil:
	os.Remove(dst)
	err = dstErr
        fallthrough

case err != nil:
	return fmt.Errorf("copy %s %s: %v", src, dst, err)
}

Notes

  • I thought of this while thinking through my ?/goto proposal proposal: Go 2: use ? during variable assignment as implicit goto statement #64953, wanted to break it out to open up discussion separately, though I hadn't used the switch/case keywords originally.

  • Behaves mostly like a standard switch/case, but some differences. Case tests that use a variable before it gets declared would need to be skipped. For instance, the 'dstErr != nil' case would be skipped for the first two 'switch err' assignments. Also, switch-assign inside of a case statement would jump to a global case, so you could also chain the handlers together like so:

case dstErr != nil:
        os.Remove(dst)
        switch err = dstErr

case err != nil:
        return fmt.Errorf("copy %s %s: %v", src, dst, err)
  • Supporting the default keyword probably doesn't make sense here, but maybe there's no reason to forbid it, either.

  • Not familiar with the go grammar, maybe this is a non-starter due to parsing concerns, but could potentially be solved with a new keyword (check instead of switch, re-use case keyword) or set of keywords (check instead of switch, when instead of case).

  • Provides a bit more structure to the error handling blocks vs my ?/goto proposal, but also significantly complicates the implementation, especially re: variable scoping.

Go Proposal Template

  • Would you consider yourself a novice, intermediate, or experienced Go programmer?
    Experienced.

  • What other languages do you have experience with?
    Assembly, C, C++, Python, Erlang, several others

  • Would this change make Go easier or harder to learn, and why?
    A bit more control flow to learn, but behaves mostly like a normal switch/case statement, so the leap as far as branching is minimal. Probably some confusion with the scope of the function-wide case blocks and how they interact with variable declarations.

  • Has this idea, or one like it, been proposed before?
    I couldn't find this proposal anywhere.

  • Who does this proposal help, and why?
    All gophers that would like more concise error handling.

  • Is this change backward compatible?
    Yes, existing code does not need to be changed.

  • What is the cost of this proposal? (Every language change has a cost).
    Support new form of switch-during-assignment in grammar, in-line switch/case test block after each use, support new form of function-wide case statement in grammar.

  • How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
    Probably many, since this would be a change in language syntax.

  • What is the compile time cost?
    Not familiar enough with the compiler internals to answer this.

  • What is the run time cost?
    Probably negligible if the compiler can optimize out unnecessary case tests.

  • Do you have a prototype? (This is not required.)
    No, but would be happy to put one together with a little guidance.

  • How would the language spec change?
    Switch is now supported as a keyword prefix to a variable assignment. Function-wide case labels are supported.

  • Orthogonality: how does this change interact or overlap with existing features?
    Re-uses existing golang control flow so minimal interactions.

  • Does this affect error handling?
    This change is intended to provide a new control flow mechanism during variable assignment that can be used to make error handling less verbose, but is not exclusive to error handling.

  • If so, how does this differ from previous error handling proposals?
    From spec: error handling meta issue #40432, seems similar to those with this classification: 'Simplifications of if err != nil, to reduce boilerplate.', but I couldn't find a similar proposal. The issue notes state most of these are rejected because 'they don't reduce the boilerplate enough to make it worth changing the language, or because they are cryptic.', but this proposal can reduce the boilerplate quite a bit, and I don't see it as cryptic at all as it's re-using the existing switch/case statement currently offered by go.

@gopherbot gopherbot added this to the Proposal milestone Jan 8, 2024
@seankhliao seankhliao added LanguageChange Suggested changes to the Go language v2 An incompatible library change error-handling Language & library change proposals that are about error handling. labels Jan 13, 2024
@ianlancetaylor
Copy link
Member

This new syntax does not fit well with the rest of the language. It also appears to be ambiguous, as statements like switch dstErr = w.Close() are already valid today. It also puts case statements at the top level of a function, where they currently can't appear; it's unclear how to handle the new switch statement in an inner block.

For these reasons, and the negative emoji voting, this is a likely decline. Leaving open for four weeks for final comments.

@ianlancetaylor ianlancetaylor changed the title proposal: Go 2: support new form of switch statement during variable assignment which jumps to function-wide case blocks proposal: spec: support new form of switch statement during variable assignment which jumps to function-wide case blocks Aug 6, 2024
@ianlancetaylor ianlancetaylor added LanguageChangeReview Discussed by language change review committee and removed v2 An incompatible library change labels Aug 6, 2024
@findleyr
Copy link
Member

findleyr commented Aug 7, 2024

No change in consensus, so declined.
— rfindley for the language proposal review group

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error-handling Language & library change proposals that are about error handling. LanguageChange Suggested changes to the Go language LanguageChangeReview Discussed by language change review committee Proposal Proposal-FinalCommentPeriod
Projects
None yet
Development

No branches or pull requests

5 participants