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 function f
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