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?


Terminating statements

Terminating statements A terminating statement interrupts the regular flow of control in a block. The following statements are terminating: A “return” or “goto” statement. The return statement should be familiar to virtually everyone. And the fact that it interrupts the regular flow of control should be no surprise: func foo() { fmt.Println("Hello there") return fmt.Println("You'll never see me!") } In this above example, the second fmt.Println is never called for fairly obvious reasons: The preceeding return statement interrupts the flow, and returns control control flow back to whatever code called foo() in the first place.


Statements

At long last, we have completed the section of the spec on expressions… and now we move on to: Statements Statements control execution. Statement = Declaration | LabeledStmt | SimpleStmt | GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | DeferStmt . SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl . In my experience, the terms “expression” and “statement” and “declaration” are often confused and conflated.


Order of evaluation and floating point numbers

Today I’ll be live streaming again! This time, picking up where we left off last week, and adding another feature to my new Go code rewriter and simplifier. Join me! Order of Evaluation … Floating-point operations within a single expression are evaluated according to the associativity of the operators. Explicit parentheses affect the evaluation by overriding the default associativity. In the expression x + (y + z) the addition y + z is performed before adding x.


Initialization dependencies

Here’s a thing you’ve likely never thought about: What if you have a compound assignment statement, where one of the variables depends on the other in the same statement. That’s what we’re looking at today. Order of Evaluation … At package level, initialization dependencies override the left-to-right rule for individual initialization expressions, but not for operands within each expression: var a, b, c = f() + v(), g(), sqr(u()) + v() func f() int { return c } func g() int { return a } func sqr(x int) int { return x*x } // functions u and v are independent of all other variables and functions So first notice that calling f() returns c, and calling g() returns a.


Unordered evaluation

Yesterday’s spec quote included a sentence we breezed over. Today we’re going to dig in a bit more: Order of Evaluation … the order of those events compared to the evaluation and indexing of x and the evaluation of y and z is not specified, except as required lexically. What exactly does that mean? Well, the example that follows in the spec makes it a bit more clear, but in a nutshell, the order of evaluation for index expressions is not defined.


Order of Evaluation

Let’s talk about… the order of evaluation! You might think you have a strong grasp on this concept, but many languages have their own nuanced take on evaluation order in some cases. And then JavaScript has “hoisting”, which kinda spits in the face of order of evaluation. Before we dive in, here’s a short pop-quiz. What does this short program output when executed? package main import "fmt" func init() { fmt.

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.


Constant expressions, part III

Did you miss yesterday’s Ask-me-anything session? You probably did. I had about 10-15 people there. But even with a small group, we had a ton of great questions! The Q&A session lasted about an hour, and covered topics such as book recommendations for going deeper into Go, what project to build to learn concurrency, and much more. Catch the replay on YouTube. Let’s continue our discussion of constant expressions, with some more miscellaneous rules:


Constant expressions, continued

Today I’ll be answering your questions on my weekly live stream. Have a question about Go? About CI/CD? About my favorite pizza toppings? Join me! Or submit your question early and catch the replay, if you can’t join live. Today we continue the section on Constant expressions, with a grab bag of miscellaneous rules. Constant expressions … Applying the built-in function complex to untyped integer, rune, or floating-point constants yields an untyped complex constant.


Constant expressions

We made it through all the conversion rules! Let’s change gear and talk about… Constant expressions Constant expressions may contain only constant operands and are evaluated at compile time. Or framed differently: Any expression that contains non-constant operands, is not a constant expression. If you have a constant expression (e.g. 1 + 2) then extend it with a non-constant operand (e.g. 1 + 2 + userCount()), then it is no longer a constant expression.


Conversions from slice to array or array pointer

Conversions from slice to array or array pointer … Converting a slice to an array yields an array containing the elements of the underlying array of the slice. Similarly, converting a slice to an array pointer yields a pointer to the underlying array of the slice. In both cases, if the length of the slice is less than the length of the array, a run-time panic occurs. s := make([]byte, 2, 4) a0 := [0]byte(s) a1 := [1]byte(s[1:]) // a1[0] == s[1] a2 := [2]byte(s) // a2[0] == s[0] a4 := [4]byte(s) // panics: len([4]byte) > len(s) s0 := (*[0]byte)(s) // s0 !