
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:

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:
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.

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.

2 min read
Uniqueness of type switch cases
Finally, the last important bit from this paragraph: Type switches … Cases then match actual types T against the dynamic type of the expression x. As with type assertions, x must be of interface type, but not a type parameter, and each non-interface type T listed in a case must implement the type of x. The types listed in the cases of a type switch must all be different. Today we’re examining this part:

2 min read
Type switching to non-implementing types
More live coding today! Join me in just a few hours for some more Go TDD work on my kivik library. Today we’re continuing to disect this paragraph: Type switches … Cases then match actual types T against the dynamic type of the expression x. As with type assertions, x must be of interface type, but not a type parameter, and each non-interface type T listed in a case must implement the type of x.

2 min read
Type switching on a non-interface value. Sorta.
Type switches … Cases then match actual types T against the dynamic type of the expression x. As with type assertions, x must be of interface type, but not a type parameter, and each non-interface type T listed in a case must implement the type of x. The types listed in the cases of a type switch must all be different. TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .

1 min read
Type switches
Back in December we looked at type assertions, which allow us to assert whether an interface type is of a specific underlying type. In that conversation, I promised we’d get to the more flexible type switches. And now, at long last, we have arrived! Type switches A type switch compares types rather than values. It is otherwise similar to an expression switch. It is marked by a special switch expression that has the form of a type assertion using the keyword type rather than an actual type:

2 min read
Expression switches conclusion
We have just two more points (and some examples) before finishing the topic of expression switches, so let’s get to it. Expression switches … The switch expression may be preceded by a simple statement, which executes before the expression is evaluated. You may recall the discussion of “simple statements” from before. They can exist in an if expression as well. switch x := foo(); x { In this example, x := foo() is the simple statement.