From: Rob Pike true
.
There are two forms: expression switches and type switches.
-
In an expression switch, the cases contain expressions that are compared against the value of the switch expression. In a type switch, the cases contain types that are compared against the type of a specially annotated switch expression.
--SwitchStat = ExprSwitchStat | TypeSwitchStat . -ExprSwitchStat = "switch" [ [ SimpleStat ] ";" ] [ Expression ] "{" { CaseClause } "}" . -TypeSwitchStat = "switch" [ [ SimpleStat ] ";" ] TypeSwitchExpression "{" { CaseClause } "}" . -TypeSwitchExpression = identifier ":=" Expression "." "(" "type" ")" . -CaseClause = SwitchCase ":" [ StatementList ] . -SwitchCase = "case" ExpressionList | SwitchAssignment | Type | "default" . -SwitchAssignment = Expression ( "=" | ":=" ) Expression . -SwitchExpression = Expression. -+
In an expression switch,
@@ -3158,7 +3144,17 @@ If no case matches and there is a "default" case,
its statements are executed.
There can be at most one default case and it may appear anywhere in the
"switch" statement.
+A missing expression is equivalent to
+the expression true
.
+SwitchStat = ExprSwitchStat | TypeSwitchStat . +ExprSwitchStat = "switch" [ [ SimpleStat ] ";" ] [ Expression ] "{" { ExprCaseClause } "}" . +ExprCaseClause = ExprSwitchCase ":" [ StatementList ] . +ExprSwitchCase = "case" ExpressionList | "default" . ++
In a case or default clause, the last statement only may be a "fallthrough" statement @@ -3168,7 +3164,7 @@ the first statement of the next clause. Otherwise control flows to the end of the "switch" statement.
-Each case clause effectively acts as a block for scoping purposes +Each case clause acts as a block for scoping purposes (§Declarations and scope rules).
@@ -3198,57 +3194,29 @@ case x == 4: f3(); } -
-If the expression in an expression switch is a boolean, the cases -may take a special form that tests a type guard, map index, or -channel operation and stores the value in a variable, which may -be declared using a simple variable declaration. The success -of the case's operation is compared against the value of the boolean. -A switch of the form: -
- --switch bool_expr { -case x0: - f0(); -case x1 := y1.(T1): - f1(); -case x2 := y2[z2]: - f2(); -case x3 := <-y3: - f3(); -default: - f4(); -} -+
-is therefore analogous to the "if" statement
+A type switch compares types rather than values. It is otherwise similar
+to an expression switch. It is introduced by special
+notation in the form of a simple declaration whose right hand side
+has the form of a type guard (§Type guards)
+using the reserved word type
rather than an actual type.
+Cases then match literal types against the dynamic type of the expression
+in the type guard.
-if x0 == bool_expr { - f0(); -} else if x1, ok1 := y1.(T1); ok1 == bool_expr { - f1(); -} else if x2, ok2 := y2[z2]; ok2 == bool_expr { - f2(); -} else if x3, ok3 := <-y3; ok3 == bool_expr { - f3(); -} else { - f4(); -} ++TypeSwitchStat = "switch" [ [ SimpleStat ] ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" . +TypeSwitchGuard = identifier ":=" Expression "." "(" "type" ")" . +TypeCaseClause = TypeSwitchCase ":" [ StatementList ] . +TypeSwitchCase = "case" type | "default" .-A type switch compares types rather than values. In other respects it has -the same properties as an expression switch and may in fact be rewritten -as an expression switch using type guards. It is introduced by special -notation in the form of a generic type guard using the reserved word -
type
rather than an actual type. Given a functionf
that returns a value of interface type, -the following two "switch" statements are analogous: +the following type switch:@@ -3257,20 +3225,36 @@ case int: printInt(i); // i is an int case float: printFloat(i); // i is a float +case func(int) float: + printFunction(i); // i is a function default: printString("don't know the type"); } +-switch val := f(); true { -case i := val.(int): ++could be rewritten: +
+ ++v := f(); +if i, is_int := v.(int); is_int { printInt(i); // i is an int -case i := val.(float): +} else if i, is_float := v.(float); is_float { printFloat(i); // i is a float -default: +} else if i, is_func := v.(func(int) float); is_func { + printFunction(i); // i is a function +} else { printString("don't know the type"); }++In a type switch, the guard is mandatory, +there can be only one type per "case", and +the "fallthrough" statement is not allowed. +
+For statements