iTranslated by AI
Labels in Go
Here's a small tip from the "The Go Programming Language Online Reading Group" after a while.
First, let's write a simple countdown program.
//go:build run
// +build run
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Commencing countdown.")
tick := time.Tick(1 * time.Second)
for countdown := 10; countdown > 0; countdown-- {
fmt.Println(countdown)
<-tick
}
}
(From Chapter 8.7 of "The Go Programming Language")
Running this will display a countdown every second.
$ go run sample1.go
Commencing countdown.
10
9
8
7
6
5
4
3
2
1
So far, so simple.
Next, let's consider how to interrupt this countdown program. In Chapter 8.7 of "The Go Programming Language", an arbitrary abort channel was created to trigger an event upon pressing the Return key, but in this article, I'll take a shortcut and use the os/signal package. It looks like this[1].
//go:build run
// +build run
package main
import (
"fmt"
"os"
"os/signal"
"time"
)
func main() {
abort := make(chan os.Signal, 1)
defer func() {
close(abort)
fmt.Println("Close abort channel.")
}()
signal.Notify(abort, os.Interrupt)
fmt.Println("Commencing countdown. Press Ctrl+C to abort.")
tick := time.Tick(1 * time.Second)
LOOP:
for countdown := 10; countdown > 0; countdown-- {
fmt.Println(countdown)
select {
case <-tick:
// do nothing
case <-abort:
fmt.Println("Countdown aborted!")
break LOOP
}
}
}
Let's start this program and try stopping it halfway with the [Ctrl+C] key.
$ go run sample2.go
Commencing countdown. Press Ctrl+C to abort.
10
9
8
^CCountdown aborted!
Close abort channel.
Alright. It successfully reaches the point where the channel is closed.
Now, the LOOP label appears here, but didn't old-timer engineers like myself think something like this?
If it goes back to the LOOP label with break, won't the for loop just restart, meaning it won't actually stop?
That's what I initially thought, and someone actually asked this question during the reading group (it wasn't just me).
There is almost no explanation regarding labels in "The Go Programming Language". There is only a brief mention in Chapter 2.7, "Scopes":
The scope of a control-flow label used in a break, continue, or goto statement is the entire function containing it.
(From Chapter 2.7 of "The Go Programming Language")
Other than that, there is no mention at all until the actual label syntax appears in the sample code in Chapter 8.7. No wonder it's confusing! (lol)
In fact, labels in Go do not represent a processing location (address), but are rather statements that designate the statement that follows them.
A labeled statement may be the target of a goto, break or continue statement.
LabeledStmt = Label ":" Statement .
Label = identifier .
(via “The Go Programming Language Specification”)
In the previous code, the LOOP label points to the for statement that immediately follows it, and the break LOOP inside the for loop means exiting the processing of the for statement labeled with LOOP, rather than the inner select statement.
Incidentally, the scope of target labels for goto, break, and continue is quite limited:
The scope of a label is the body of the function in which it is declared and excludes the body of any nested function.
(via “The Go Programming Language Specification”)
It is quite limited. In particular, for goto statements, jumping over a variable declaration that has not been declared at the point of the goto statement, like this:
goto L // BAD
v := 3
L:
...
or jumping into a block from the outside,
if n%2 == 1 {
goto L1 // BAD
}
for n > 0 {
f()
n--
L1:
f()
n--
}
is also apparently not allowed. It seems quite difficult to find a use case for it—or rather, I wouldn't feel inclined to use it unless there was a very compelling reason.
This style of label syntax and behavior isn't unique to Go (I believe Java and others are the same), and younger developers today might consider this usage of labels to be perfectly normal. However, for an old-timer who spent their youth writing in Assembly or BASIC, it felt a bit counter-intuitive and took a while to get used to.
Anyway, it ended up sounding like an old man's trip down memory lane, but please forgive me.
Discussion