Commit 70c1a106 authored by Rob Pike's avatar Rob Pike

drop the ,ok switch; keep the straight type switch.

R=rsc,gri
DELTA=97  (26 added, 42 deleted, 29 changed)
OCL=26436
CL=26527
parent f7772627
...@@ -3123,28 +3123,14 @@ if x := f(); x < y { ...@@ -3123,28 +3123,14 @@ if x := f(); x < y {
An expression or type specifier is compared to the "cases" An expression or type specifier is compared to the "cases"
inside the "switch" to determine which branch inside the "switch" to determine which branch
to execute. to execute.
A missing expression or type specifier is equivalent to
the expression <code>true</code>.
There are two forms: expression switches and type switches. There are two forms: expression switches and type switches.
</p>
<p>
In an expression switch, the cases contain expressions that are compared In an expression switch, the cases contain expressions that are compared
against the value of the switch expression. against the value of the switch expression.
In a type switch, the cases contain types that are compared against the In a type switch, the cases contain types that are compared against the
type of a specially annotated switch expression. type of a specially annotated switch expression.
</p> </p>
<pre class="grammar"> <h4>Expression switches</h4>
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.
</pre>
<p> <p>
In an expression switch, In an expression switch,
...@@ -3158,7 +3144,17 @@ If no case matches and there is a "default" case, ...@@ -3158,7 +3144,17 @@ If no case matches and there is a "default" case,
its statements are executed. its statements are executed.
There can be at most one default case and it may appear anywhere in the There can be at most one default case and it may appear anywhere in the
"switch" statement. "switch" statement.
A missing expression is equivalent to
the expression <code>true</code>.
</p> </p>
<pre class="grammar">
SwitchStat = ExprSwitchStat | TypeSwitchStat .
ExprSwitchStat = "switch" [ [ SimpleStat ] ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
ExprCaseClause = ExprSwitchCase ":" [ StatementList ] .
ExprSwitchCase = "case" ExpressionList | "default" .
</pre>
<p> <p>
In a case or default clause, In a case or default clause,
the last statement only may be a "fallthrough" statement the last statement only may be a "fallthrough" statement
...@@ -3168,7 +3164,7 @@ the first statement of the next clause. ...@@ -3168,7 +3164,7 @@ the first statement of the next clause.
Otherwise control flows to the end of the "switch" statement. Otherwise control flows to the end of the "switch" statement.
</p> </p>
<p> <p>
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). (§Declarations and scope rules).
</p> </p>
<p> <p>
...@@ -3198,57 +3194,29 @@ case x == 4: f3(); ...@@ -3198,57 +3194,29 @@ case x == 4: f3();
} }
</pre> </pre>
<p> <h4>Type switches</h4>
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:
</p>
<pre>
switch bool_expr {
case x0:
f0();
case x1 := y1.(T1):
f1();
case x2 := y2[z2]:
f2();
case x3 := <-y3:
f3();
default:
f4();
}
</pre>
<p> <p>
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 <code>type</code> rather than an actual type.
Cases then match literal types against the dynamic type of the expression
in the type guard.
</p> </p>
<pre> <pre class="grammar">
if x0 == bool_expr { TypeSwitchStat = "switch" [ [ SimpleStat ] ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
f0(); TypeSwitchGuard = identifier ":=" Expression "." "(" "type" ")" .
} else if x1, ok1 := y1.(T1); ok1 == bool_expr { TypeCaseClause = TypeSwitchCase ":" [ StatementList ] .
f1(); TypeSwitchCase = "case" type | "default" .
} else if x2, ok2 := y2[z2]; ok2 == bool_expr {
f2();
} else if x3, ok3 := <-y3; ok3 == bool_expr {
f3();
} else {
f4();
}
</pre> </pre>
<p> <p>
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
<code>type</code> rather than an actual type.
Given a function <code>f</code> Given a function <code>f</code>
that returns a value of interface type, that returns a value of interface type,
the following two "switch" statements are analogous: the following type switch:
</p> </p>
<pre> <pre>
...@@ -3257,20 +3225,36 @@ case int: ...@@ -3257,20 +3225,36 @@ case int:
printInt(i); // i is an int printInt(i); // i is an int
case float: case float:
printFloat(i); // i is a float printFloat(i); // i is a float
case func(int) float:
printFunction(i); // i is a function
default: default:
printString("don't know the type"); printString("don't know the type");
} }
</pre>
switch val := f(); true { <p>
case i := val.(int): could be rewritten:
</p>
<pre>
v := f();
if i, is_int := v.(int); is_int {
printInt(i); // i is an 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 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"); printString("don't know the type");
} }
</pre> </pre>
<p>
In a type switch, the guard is mandatory,
there can be only one type per "case", and
the "fallthrough" statement is not allowed.
</p>
<h3>For statements</h3> <h3>For statements</h3>
<p> <p>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment