1
0
mirror of https://github.com/golang/go synced 2024-11-25 03:07:56 -07:00

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

R=rsc,gri
DELTA=97  (26 added, 42 deleted, 29 changed)
OCL=26436
CL=26527
This commit is contained in:
Rob Pike 2009-03-18 19:23:59 -07:00
parent f7772627ad
commit 70c1a106e6

View File

@ -3123,28 +3123,14 @@ if x := f(); x < y {
An expression or type specifier is compared to the "cases"
inside the "switch" to determine which branch
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.
</p>
<p>
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.
</p>
<pre class="grammar">
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>
<h4>Expression switches</h4>
<p>
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 <code>true</code>.
</p>
<pre class="grammar">
SwitchStat = ExprSwitchStat | TypeSwitchStat .
ExprSwitchStat = "switch" [ [ SimpleStat ] ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
ExprCaseClause = ExprSwitchCase ":" [ StatementList ] .
ExprSwitchCase = "case" ExpressionList | "default" .
</pre>
<p>
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.
</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).
</p>
<p>
@ -3198,57 +3194,29 @@ case x == 4: f3();
}
</pre>
<h4>Type switches</h4>
<p>
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:
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>
<pre>
switch bool_expr {
case x0:
f0();
case x1 := y1.(T1):
f1();
case x2 := y2[z2]:
f2();
case x3 := <-y3:
f3();
default:
f4();
}
<pre class="grammar">
TypeSwitchStat = "switch" [ [ SimpleStat ] ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
TypeSwitchGuard = identifier ":=" Expression "." "(" "type" ")" .
TypeCaseClause = TypeSwitchCase ":" [ StatementList ] .
TypeSwitchCase = "case" type | "default" .
</pre>
<p>
is therefore analogous to the "if" statement
</p>
<pre>
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();
}
</pre>
<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>
that returns a value of interface type,
the following two "switch" statements are analogous:
the following type switch:
</p>
<pre>
@ -3257,20 +3225,36 @@ case int:
printInt(i); // i is an int
case float:
printFloat(i); // i is a float
default:
printString("don't know the type");
}
switch val := f(); true {
case i := val.(int):
printInt(i); // i is an int
case i := val.(float):
printFloat(i); // i is a float
case func(int) float:
printFunction(i); // i is a function
default:
printString("don't know the type");
}
</pre>
<p>
could be rewritten:
</p>
<pre>
v := f();
if i, is_int := v.(int); is_int {
printInt(i); // i is an int
} else if i, is_float := v.(float); is_float {
printFloat(i); // i is a float
} else if i, is_func := v.(func(int) float); is_func {
printFunction(i); // i is a function
} else {
printString("don't know the type");
}
</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>
<p>