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: Go 2: extend "goto" - statement #53074

Closed
mmaedel opened this issue May 25, 2022 · 7 comments
Closed

proposal: Go 2: extend "goto" - statement #53074

mmaedel opened this issue May 25, 2022 · 7 comments
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Proposal Proposal-FinalCommentPeriod v2 A language change or incompatible library change
Milestone

Comments

@mmaedel
Copy link

mmaedel commented May 25, 2022

Author background

intermediate -> experienced Go programmer?
n/a

Related proposals

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

Has some similarities to

https://go.dev/issue/32611
https://go.dev/issue/34140
https://go.dev/issue/37035

  • If so, how does this proposal differ?

by making use of an extended "goto" - statement funcionality

  • Does this affect error handling?

yes

  • If so, how does this differ from previous error handling proposals?

n/a

  • Is this about generics?

no

  • If so, how does this relate to the accepted design and other generics proposals?

n/a

Proposal

  • What is the proposed change?

https://groups.google.com/g/golang-nuts/c/5ARY8Pdu3zM

  • Who does this proposal help, and why?

writers and maintainers of code bases with restructuring "if err != nil {}" by inlining func evaluations

  • Please describe as precisely as possible the change to the language.

compiler functionality

  • What would change in the language spec?

goto has extended functionality

  • Please also describe the change informally, as in a class teaching Go.

In Go the "goto" statement transfers control to the statement with the corresponding label within the same function

new:

when put before https://go.dev/ref/spec#Expressions it takes all evaluated values (in lexical right-to-left order; ignoring the zero value for its type), jumps to a label with the same name as the "value holder" (if present) and holds a pointer to the corresponding value.

  • Is this change backward compatible?

yes

  • Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.

n/a

  • Show example code before and after the change.
r,err := os.Open(src)
if err != nil {
//do something
}
goto r,err := os.Open(src)

r: 
defer r.Close()
goto w, err := os.Create(dst)
goto v, err := io.Copy(w, r)
goto err := w.Close()

err: 
//do something
  • Orthogonality: how does this change, interact or overlap with existing features?

scope?
https://go.dev/ref/spec#Goto_statements

  • Is the goal of this change a performance improvement?

n/a

  • If so, what quantifiable improvement should we expect?

n/a

  • How would we measure it?

n/a

Costs

  • Would this change make Go easier or harder to learn, and why?
  • What is the cost of this proposal? (Every language change has a cost).
  • How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
  • What is the compile time cost?
  • What is the run time cost?
  • Can you describe a possible implementation?
  • Do you have a prototype? (This is not required.)
@gopherbot gopherbot added this to the Proposal milestone May 25, 2022
@seankhliao
Copy link
Member

For the example block of code:

goto r,err := os.Open(src)

r: 
defer r.Close()
goto w, err := os.Create(dst)
goto v, err := io.Copy(w, r)
goto err := w.Close()

err: 
//do something

The first instance seems to jump to the label r, which is also the name of the first variable, while the remaining ones jump to the label err, which is everywhere.
What are the rules for what does goto jump to?

@seankhliao seankhliao added LanguageChange v2 A language change or incompatible library change error-handling Language & library change proposals that are about error handling. labels May 25, 2022
@seankhliao seankhliao modified the milestones: Proposal, Go 2 May 25, 2022
@mmaedel
Copy link
Author

mmaedel commented May 25, 2022

For the example block of code:

goto r,err := os.Open(src)

r: 
defer r.Close()
goto w, err := os.Create(dst)
goto v, err := io.Copy(w, r)
goto err := w.Close()

err: 
//do something

The first instance seems to jump to the label r, which is also the name of the first variable, while the remaining ones jump to the label err, which is everywhere. What are the rules for what does goto jump to?

walkthrough:

goto r,err := os.Open(src)

  • goto "evaluates" err: if err != nil -> jump to err-"label"
  • goto "evaluates" r: if not "zero value" of type and r-"label" is present -> r-"label and
    continue
  • ... if any err != nil: -> jump to err-"label"
  • if other value-"labels" are present -> jump...

@ianlancetaylor
Copy link
Contributor

Note that in the example code we normally would not permit goto err. See https://go.dev/ref/spec#Goto_statements which says: "Executing the "goto" statement must not cause any variables to come into scope that were not already in scope at the point of the goto."

@beoran
Copy link

beoran commented May 26, 2022

It is already possible, if a bit verbose to do goto-based error handling. If go had an if qualifier like Ruby, we could shorten this to goto err if err != nil.

https://play.golang.com/p/59VJFBaYnt4

package main

import (
	"fmt"
	"errors"
)

func errorEven(i int) error {
	if i% 2 == 0 {
		return errors.New("even")
	}
	return nil
}

func errorGoto(i int) {
	var err error
	fmt.Printf("Start: %d\n", i)
	err = errorEven(i)
	if err != nil {
		goto err
	}
	goto ok

	err:
	fmt.Printf("There was an error: %s\n", err)
	return
	
	ok:
	fmt.Println("All is ok")
	return
}


func main() {
	errorGoto(1)
	errorGoto(2)
	errorGoto(3)
	errorGoto(4)
}

@mmaedel
Copy link
Author

mmaedel commented Jun 5, 2022

a proposal scheme

> _3: (scope _2)
goto_block {
    if label-name is present (eg err, A): ->  _9 || _5
    (else: -> _4)

    > _2: (scope _1)
    value(s)_block {
        (right-to-left evaluation of returned values: eg err, A)
        if value != zero value of type || value != _: -> _3
        (else -> _4)

        > _1: entry
        func_block(s) {
            evaluation(s):
            if value(s) returned -> _2
            (else -> _4)
        }

    }

}

> _4: (scope _1 || _2)
//do something: eg func_block(s)/goto_block(s)... define exit_block_1 or -> _9 || _10

and/or

label(s)_block {

    A:
    > _7: (scope _6)
    goto_block {
        if label-name is present (eg err, B): -> _9 || _8++
        (else: -> _8++)

            > _6: (scope _5)
            label_block_A {
            (right-to-left evaluation of returned values)
            if value != zero value of type: -> _7
            (else -> _8++)

                > _5: (scope _3)
                func_block(s) {
                    evaluation(s):
                    if value(s) returned -> _6
                    (else -> _8++ || _10)
                }

            }

    }

    (
    > _8++:
    eg B: (func_block(s) or goto_block)
    )

    > _9: (scope _4 || _6 || _7 || _8++)
    err:
    ("error evaluation" - block)

    > _10: (scope _4 || _5 || _8++ || _9)
    Exit:
    exit_block_2

}

(exit_block_3)

@ianlancetaylor
Copy link
Contributor

This proposal overloads variable names and label names, such that the name of a label corresponds to the name of a variable. That is confusing, and would seem to work poorly if one wants to assign to a variable more than once.

The emoji voting on this issue is not in favor.

Therefore, this is a likely decline. Leaving open for four weeks for final comments.

@ianlancetaylor
Copy link
Contributor

No further comments.

@ianlancetaylor ianlancetaylor closed this as not planned Won't fix, can't repro, duplicate, stale Oct 5, 2022
@golang golang locked and limited conversation to collaborators Oct 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Proposal Proposal-FinalCommentPeriod v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

6 participants