Defer statements

We’re at the last item in the “Statements” section of the spec, before we move on to built-in functions. And naturally, the last one is… the defer statement~ Defer statements A “defer” statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.


Fallthrough statements

Fallthrough statements A “fallthrough” statement transfers control to the first statement of the next case clause in an expression “switch” statement. It may be used only as the final non-empty statement in such a clause. FallthroughStmt = "fallthrough" . Well that’s pretty straight forward. for x := range 10 { switch { case x%2 == 0: fmt.Print("X") fallthrough case x%3 == 0: fmt.Print("x") fallthrough case x%5 == 0: fmt.Print("O") } fmt.


Goto statements

We’ve finished the discussion of the new range-over-func feature, so let’s continue where we left off before the Go 1.23 release, with a feature you’ll rarely, if ever, use. Goto statements A “goto” statement transfers control to the statement with the corresponding label within the same function. GotoStmt = "goto" Label . goto Error Unless your only programming experience has been in the BASIC language, you’ve probably learned to eschew “goto”.


Tree walking with range-over-fun

We’ve been looking at Go 1.23’s new range-over-func feature. And we’re just about through what the spec has to say about it. Except for one thing. The example code! // iteration support for a recursive tree data structure type Tree[K cmp.Ordered, V any] struct { left, right *Tree[K, V] key K value V } func (t *Tree[K, V]) walk(yield func(key K, val V) bool) bool { return t == nil || t.

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.


yield

For statements with range clause … For a function f, the iteration proceeds by calling f with a new, synthesized yield function as its argument. Let’s talk about yield today. If I’m honest, this was probably the scariest part of these new function iterators, before I started actually using them. It looks an awful lot like a new keyword, with weird usage. I know I’m not alone in thinking this.


Iterating over functions

As mentioned yesterday, today we’re taking a bit of a step back to an earlier portion of the spec, which was just updated. Here’s the first part of the updated section of the spec (new additions emphasized): For statements with range clause A “for” statement with a “range” clause iterates through all entries of an array, slice, string or map, values received on a channel, integer values from zero to an upper limit [Go 1.


Go 1.23.0 has been released!

I missed the last couple of days. Oops! It’s a busy time here, as I’m preparing for an international move, and balancing a new business venture I’m working on. But I’m back today! The big news in the Go world is that on Tuesday, Go 1.23.0 was released! What this means for us, as we venture through the Go spec, is that there are new changes to the spec we need to talk about!


Continue statements

Let’s continue… haha See what I did there? Bleh, okay. Continue statements A “continue” statement begins the next iteration of the innermost enclosing “for” loop by advancing control to the end of the loop block. The “for” loop must be within the same function. ContinueStmt = "continue" [ Label ] . There’s not a lot necessary to say here. continue works very much like break. The scoping rules are essentially the same.


Break statements with labels

Break statements … If there is a label, it must be that of an enclosing “for”, “switch”, or “select” statement, and that is the one whose execution terminates. In other words, you can’t break to a label that labels a more deeply nested for, switch or select statement, or to one that’s completely unrelated. But that’s only intuitive, right? OuterLoop: for i = 0; i < n; i++ { for j = 0; j < m; j++ { switch a[i][j] { case nil: state = Error break OuterLoop case item: state = Found break OuterLoop } } } Speaking of labels, did you know that you can have blank labels?


Break statements

Break statements A “break” statement terminates execution of the innermost “for”, “switch”, or “select” statement within the same function. BreakStmt = "break" [ Label ] . We’ll discuss the Label mentioned tomorrow. Until then, the key word here is innermost. This shouldn’t be very surprising to anyone familiar with other programming languages. But despite its familiarity, I’ve been bitten more than once by forgetting this key detail. It’s perhaps easiet to forget when you have, say, a switch statement within a for loop, for example.


Return statements, conclusion

Just a couple small notes before we move on from return statements… Return statements … Regardless of how they are declared, all the result values are initialized to the zero values for their type upon entry to the function. A “return” statement that specifies results sets the result parameters before any deferred functions are executed. For the most part, this can be considered trivia, for Quiz night at your next Go meetup.