Labeled statements

Today we’ll talk about labeled statements, which we’ve just recently mentioned in the context of terminating statements. Labeled statements A labeled statement may be the target of a goto, break or continue statement. LabeledStmt = Label ":" Statement . Label = identifier . Error: log.Panic("error encountered") If I may say so, the example provided is pretty bad. I mean, yeah, it technically is a labeled statement. It contains the label Error, followed by a colon (:), followed by a statement.


Empty statements

Empty statements The empty statement does nothing. EmptyStmt = . I don’t think there’s much to say here. I suppose we could spend some time debating if/when an empty statement exists in our code. How many empty statements in the following? Is it one? Zero? An infinite number? How many “nothings” does this code do? I can honestly say I’m not sure why “the empty statement” is even defined. It’s only mentioned four other times in the spec, once as one of the possible components of a simple statement:


Terminating statements conclusion

So we’ve made it through the list of 8 types of terminating statements. We conclude this section with a couple additional comments: Terminating statements … All other statements are not terminating. A statement list ends in a terminating statement if the list is not empty and its final non-empty statement is terminating. What is a statement list? It’s, well, eh… a list of statements! It’s not as interesting or profound as it sounds.


Terminating labeled statements

Today’s live stream is starting an hour later than usual. Join me at 16:00, CEST, for some live Go coding using TDD. Terminating statements … A labeled statement labeling a terminating statement. Labeled statement’s are not used a lot in Go. Terminating labeled statements even less so. But they do exist, just the same. Here’s an example, using goto, and a labeled terminating statement. func foo() { if someCondition { goto end } fmt.


Terminating select statements

Terminating statements … A “select” statement in which: there are no “break” statements referring to the “select” statement, and the statement lists in each case, including the default if present, end in a terminating statement. This is quite similar to the “switch” case we looked at yesterday. Let’s consider an example: select { case <-ctx.Done(): return ctx.Err() case msg := <-messageChannel fmt.Println(message) return nil } This select statement has two cases, each of which terminates (by virtue of returning).


Terminating switch statements

Terminating statements … A “switch” statement in which: there are no “break” statements referring to the “switch” statement, there is a default case, and the statement lists in each case, including the default, end in a terminating statement, or a possibly labeled “fallthrough” statement. This should make good sense, but let’s look at an example, and a counter-example, to illustrate. func greet(args ...string) error { switch len(args) { case 0: return errors.


Terminating for loops

Terminating statements … A “for” statement in which: there are no “break” statements referring to the “for” statement, and the loop condition is absent, and the “for” statement does not use a range clause. Put another way, a for statement is terminating if it either never ends (an infinite loop), or it unconditionally terminates. This one “bit” me the other day, as I was refactoring code for a client. (Speaking of clients—I have some availability starting in May for a new client.

Subscribe to Boldly Go: Daily

Every day I'll send you advice to improve your understanding of Go. Don't miss out! I will respect your inbox, and honor my privacy policy.

Unsure? Browse the archive.


Terminating if statements

Last week we saw that a block that ends in a terminaging statement is itself a terminating statement. Today we expand a bit on that idea: Terminating statements … An “if” statement in which: the “else” branch is present, and both branches are terminating statements. In other words, the following counts as a terminating statement: if somethingInterestingHappened() { fmt.Println("Wow, that was interesting!") return } else { fmt.Println("That was boring.") return } Both branches of the if statement terminate, so the statement as a whole is a terminating statement.


Happy April Fool's Day

I’ll be streaming some live coding again, on this April Fool’s day. No joke. I hope you’ll join me. It’s April Fool’s day. And I also recently learned of #AprilCools – the idea of doing something off-topic, but serious, rather than cringey on April first. So this year, I, eh… extended my “Learn Go” book review series to review a book about learning Go…. the game, not the language. Have a watch.


Terminating blocks

Terminating statements … A block in which the statement list ends in a terminating statement. What exactly does this mean? It means that if you have an (explicit) code block that ends in a terminating statement, the block itself is considered a terminating statement. Confused? How about an example: func foo() { if somethingInterestingHappened() { fmt.Println("Wow, that was interesting!") return } fmt.Println("That was boring.") } In this example, return is a terminating statement, as we saw [two days ago](/ archive/2024-03-27-terminating-statements/).


Don't panic!

Later today, at 15:00 UTC, I’ll be joining Denis Čahuk and Adrian Stanek on their regular Livestream, Our Tech Journey, to talk about TDD, Go, and do some live coding. Join us! The second in our list of terminating statements is… panic! Terminating statements … A call to the built-in function panic. Don’t panic. Don’t panic is such ubiquitous Go advice that it’s one of the famous Go proverbs. So why do we have a built-in panic function if we’re not supposed to use it?