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.


Naked returns

Now we’re going to look at the third and finaly way to return values from a function in Go. But first a warning. ⚠️ NEVER DO THIS!! ⚠️ What we’re about to look at is commonly referred to as “naked returns” or “bare returns”, and it is widely (though, admittedly, not universally) considered bad practice. It’s honestly a mystery to me why this feature exists in Go, and I wish it didn’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.


Proxying return values

We already saw the “normal” way to return values from functions… But did you know there’s a shortcut if you ever want to directly return the values returned from another function? Return statements … The expression list in the “return” statement may be a single call to a multi-valued function. The effect is as if each value returned from that function were assigned to a temporary variable with the type of the respective value, followed by a “return” statement listing these variables, at which point the rules of the previous case apply.


Three ways to return values

Return statements … There are three ways to return values from a function with a result type: Do you know all three off the top of your head? We’ll be looking at each of them over the coming three days. The return value or values may be explicitly listed in the “return” statement. Each expression must be single-valued and assignable to the corresponding element of the function’s result type. func simpleF() int { return 2 } func complexF1() (re float64, im float64) { return -7.


Returning from a function without a return value

Let’s continue our discussion of return statements by looking at functions that don’t actually return anything… Return statements … In a function without a result type, a “return” statement must not specify any result values. func noResult() { return } Simple enough. Within functions without return values, return must not include any result values. But that doesn’t actually mean the example code you see is good code. In the noResult function, the return statement is actually completely redundant, because the function simply ends on the next line.


Return statements

Return statements A “return” statement in a function F terminates the execution of F, and optionally provides one or more result values. Any functions deferred by F are executed before F returns to its caller. ReturnStmt = "return" [ ExpressionList ] . The good ol’ return statement. We’ve all seen them. There’s a good chance you think you understand them pretty well. And you might. But there are a few subtleties that we’ll be looking at for the next couple of days.


Select statements, conclusion

Select statements … If the selected case is a RecvStmt with a short variable declaration or an assignment, the left-hand side expressions are evaluated and the received value (or values) are assigned. This is to say that, given a select case such as the following, where getAChannel() returns a receiving channel: case value, ok := <- getAChannel() the right-hand side of the assignment operator (<- receiveChannel) is evaluated earlier (back in step 1), and the left-hand side is only evaluated if the case is actually selected.


Execution of a select statement

I’m looking for a new client or two. Could your team use some expert Go help? Reach out, and let’s talk! Select statements … Execution of a “select” statement proceeds in several steps: For all the cases in the statement, the channel operands of receive operations and the channel and right-hand-side expressions of send statements are evaluated exactly once, in source order, upon entering the “select” statement. The result is a set of channels to receive from or send to, and the corresponding values to send.

How-Tos

9 min read


First impressions of Go 1.23's range-over-func feature

If I can knit and crochet, surely I can loop over functions in Go!