Reason for "goto <label> jumps over declaration" being disallowed

200 views
Skip to first unread message

Mike Schinkel

unread,
Aug 26, 2023, 5:11:13 PM8/26/23
to GoLang Nuts Mailing List
Hi All,

Question about disallowing `goto <label>` jumping over a variable declaration?

And please, before bikeshedding opinions about the use of `goto` pro or con — note that the Go standard library uses `goto` in some places — this question is purely for me to gain better understanding the choices made with the Go compiler.

Question. Was it:

1. Somehow logically required by the compiler, and if so can you elaborate why?

2. A design decision made, and if so what what the rationale for the design decision?

3. A limitation place on GoLang for some other reason, and if so, what and why?

I have prepared an example showing use of `goto` that compiles and one that does not at this playground URL: 

https://goplay.tools/snippet/tSAbWhmiCZK

Hoping to hear from someone who actually knows why the decision was made as opposed to someone who might just be guessing at the reason.

Thank you in advance.

-Mike

Ian Lance Taylor

unread,
Aug 26, 2023, 7:01:18 PM8/26/23
to Mike Schinkel, GoLang Nuts Mailing List
Consider a function like

func F() {
goto lab
x := 1
lab:
fmt.Println(x)
}

This function is forbidden today. If it were permitted, what should it print?

If the answer to that question seems obvious, what about a case like

func F() {
goto lab
x := func() int {
fmt.Println("setting x")
return 1
}()
lab:
fmt.Println(x)
}

Should that print "setting x"?

Rather than attempt to answer these kinds of questions, Go simply
forbids cases like this.

Note that Go is not the only language with this restriction. This
similar C++ function is invalid, because the goto crosses the
initialization of the variable.

int f() {
goto lab;
int x = 1;
lab:
std::cout << x;
return 0;
}

If you are interested in this topic you may be interested in
https://go.dev/issue/27165 and https://go.dev/issue/26058.

Ian

Mike Schinkel

unread,
Aug 26, 2023, 9:02:53 PM8/26/23
to Ian Lance Taylor, GoLang Nuts Mailing List
Hi Ian,

Thank you for the explanation. That makes perfect sense.

OTOH, in my quest to provide the simplest example I could, I provided an example that does not expose the use-case I was interested in exploring, unfortunately.

Let me instead present some real code from my current project, specifically the variable declarations on the lines 35-36 of the `Process()` method of `*FileProcessor` where the variables declared at the top are not referenced after the label:


However, your links to https://go.dev/issue/27165 and https://go.dev/issue/26058 seems to be addressing exactly the concern, so I will follow up with use-cases on those tickets after spending enough time with them to determine which one addresses my use-cases better.

Again, thank you.

-Mike

Kurtis Rader

unread,
Aug 26, 2023, 10:52:00 PM8/26/23
to Mike Schinkel, Ian Lance Taylor, GoLang Nuts Mailing List
On Sat, Aug 26, 2023 at 6:02 PM Mike Schinkel <mi...@newclarity.net> wrote:
OTOH, in my quest to provide the simplest example I could, I provided an example that does not expose the use-case I was interested in exploring, unfortunately.

Let me instead present some real code from my current project, specifically the variable declarations on the lines 35-36 of the `Process()` method of `*FileProcessor` where the variables declared at the top are not referenced after the label:


Is the code after the "end" label ever going to be more complicated than a simple "return err"? If not then I don't see the point of the goto statements. Also, since you named the return value you can simply do "return" rather than "return err" (personally I'm not a fan of bare returns that implicitly return the named return parameters). That function can be ten lines (25%) shorter and I would argue would be clearer since the reader doesn't have to look at what follows the "end" label.

--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

Mike Schinkel

unread,
Aug 26, 2023, 11:35:06 PM8/26/23
to Kurtis Rader, GoLang Nuts Mailing List
Hi Kurtis,

Is the code after the "end" label ever going to be more complicated than a simple "return err"? If not then I don't see the point of the goto statements.

Yes, very often. 

I could show examples but don't want to trigger bike shedding.

If you want to see some I'll be happy to send off-list. 

Also, since you named the return value you can simply do "return" rather than "return err" (personally I'm not a fan of bare returns that implicitly return the named return parameters).

I started using this pattern to avoid multiple return statements which can be problematic when you want the debugger to stop before a function returns. If you miss breakpointing a return you can waste time chasing your tail.

Most recommend against naked returns so I prefer one set of return values instead of many repeating ones.

I have also found other beneficial reasons to use the pattern than just the debugging concern, which I can discuss off-list if you like.

That function can be ten lines (25%) shorter

Length is one useful metric, but there are other metrics I consider too.

I would argue would be clearer since the reader doesn't have to look at what follows the "end" label.

The pattern has an `end:` label always at or near the only return in the func, and (almost) never any other labels so a reader need not look for it 
after recognizing the pattern.
 

-Mike

Reply all
Reply to author
Forward
0 new messages