2 min read
Rangeable values
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, or integer values from zero to an upper limit [Go 1.22]. Wow, that’s a long list. And it’s about to get longer! Go 1.23 is scheduled to add iterator functions to that list, but we’ll talk about that when the time comes (in August).
2 min read
Final notes on for loop variable scope
For statements with for clause … The variable used by the first iteration is declared by the init statement. The variable used by each subsequent iteration is declared implicitly before executing the post statement and initialized to the value of the previous iteration’s variable at that moment. So let’s break this down. In fact, the pseudo code I showed you during my earlier breakdown really more closely demonstrated the behavior prior to Go 1.
2 min read
Unique loop variables and the Go 1.22 fix
If you haven't joined me for a livestream in the past, consider [joining today](https://youtube.com/live/BYOsoZ5ywx8)! I'll be doing some refactoring, and adding new features to [Kivik](https://kivik.io/), with TDD. For statements with for clause … Each iteration has its own separate declared variable (or variables) [Go 1.22]. This seemingly simple sentence carries a lot of weight. So that’s what we’ll be talking about today. Prior to Go 1.22 (which only came out earlier this year!
2 min read
Omitting for clause elements
For statements with for clause … Any element of the ForClause may be empty but the semicolons are required unless there is only a condition. If the condition is absent, it is equivalent to the boolean value true. for cond { S() } is the same as for ; cond ; { S() } for { S() } is the same as for true { S() } So this goes to show that the single condition form of the for loop is really just a special case of the “for clause” for loop, with the init and post statements omitted.
2 min read
For statements with for clause
Today we’ll look at the second, of three, types of for statements: Those with a for clause. For statements with for clause A “for” statement with a ForClause is also controlled by its condition, but additionally it may specify an init and a post statement, such as an assignment, an increment or decrement statement. The init statement may be a short variable declaration, but the post statement must not. ForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .
2 min read
For statements
Go is known as a simple language, with straightforward concepts. For loops may be one of rare exceptions to that straightforward character, with three different forms: For statements A “for” statement specifies repeated execution of a block. There are three forms: The iteration may be controlled by a single condition, a “for” clause, or a “range” clause. ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . Condition = Expression .
2 min read
Type switches conclusion
Two final items with regard to type switches, before we move on to the next topic: Type switches … The type switch guard may be preceded by a simple statement, which executes before the guard is evaluated. This is pretty straight forward. It works just like the simple statements in if statements and normal switch statements. A simple statement can be used both with or without a temporary variable. In other words, both of these are valid:
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.
2 min read
Type switches with generics
More live coding today! Join me! And bring your questions. Type switches … A type parameter or a generic type may be used as a type in a case. If upon instantiation that type turns out to duplicate another entry in the switch, the first matching case is chosen. func f[P any](x any) int { switch x.(type) { case P: return 0 case string: return 1 case []P: return 2 case []byte: return 3 default: return 4 } } var v1 = f[string]("foo") // v1 == 0 var v2 = f[byte]([]byte{}) // v2 == 2 The example included is nice, because it shows two examples of the type parameter P being used: Both the first case (case P) and third (case []P) use the type parameter.
3 min read
A long type switch example
We’ve been looking at type switches since last week. Today the spec shows us a large example, comparing type switches to the equivalent expressed without them. Type switches … Given an expression x of type interface{}, the following type switch: switch i := x.(type) { case nil: printString("x is nil") // type of i is type of x (interface{}) case int: printInt(i) // type of i is int case float64: printFloat64(i) // type of i is float64 case func(int) float64: printFunction(i) // type of i is func(int) float64 case bool, string: printString("type is bool or string") // type of i is type of x (interface{}) default: printString("don't know the type") // type of i is type of x (interface{}) } could be rewritten:
1 min read
nils in type switches
Type switches … Instead of a type, a case may use the predeclared identifier nil; that case is selected when the expression in the TypeSwitchGuard is a nil interface value. There may be at most one nil case. Straight forward, right? Here’s an example: switch x.(type) { case int: case string: case nil: } But now here’s a question: If we assign x.(type) to a temporary variable the TypeSwitchGuard, what is its type in the nil case?
2 min read
Temporary variables in type switches
Type switches … TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" . TypeSwitchGuard = [ identifier ":=" ] PrimaryExpr "." "(" "type" ")" . TypeCaseClause = TypeSwitchCase ":" StatementList . TypeSwitchCase = "case" TypeList | "default" . The TypeSwitchGuard may include a short variable declaration. When that form is used, the variable is declared at the end of the TypeSwitchCase in the implicit block of each clause.