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

- modified type switches (replacement for CL 32659)

- takes into account new scoping rules

DELTA=52  (21 added, 7 deleted, 24 changed)
OCL=33967
CL=33982
This commit is contained in:
Robert Griesemer 2009-08-27 14:22:51 -07:00
parent 9bf597a210
commit 9ecd30a286

View File

@ -3272,9 +3272,9 @@ case x < 0: return -x
default: return x default: return x
} }
switch { // missing expression means "true" switch { // missing expression means "true"
case x < y: f1(); case x &lt; y: f1();
case x < z: f2(); case x &lt; z: f2();
case x == 4: f3(); case x == 4: f3();
} }
</pre> </pre>
@ -3283,9 +3283,8 @@ case x == 4: f3();
<p> <p>
A type switch compares types rather than values. It is otherwise similar A type switch compares types rather than values. It is otherwise similar
to an expression switch. It is introduced by special to an expression switch. It is marked by a special switch expression which
notation in the form of a simple declaration whose right hand side has the form of a <a href="#Type_assertions">type assertion</a>
has the form of a type assertion (§<a href="#Type_assertions">Type assertions</a>)
using the reserved word <code>type</code> rather than an actual type. using the reserved word <code>type</code> rather than an actual type.
Cases then match literal types against the dynamic type of the expression Cases then match literal types against the dynamic type of the expression
in the type assertion. in the type assertion.
@ -3293,23 +3292,30 @@ in the type assertion.
<pre class="ebnf"> <pre class="ebnf">
TypeSwitchStmt = "switch" [ [ SimpleStmt ] ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" . TypeSwitchStmt = "switch" [ [ SimpleStmt ] ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
TypeSwitchGuard = identifier ":=" Expression "." "(" "type" ")" . TypeSwitchGuard = [ identifier ":=" ] Expression "." "(" "type" ")" .
TypeCaseClause = TypeSwitchCase ":" [ StatementList ] . TypeCaseClause = TypeSwitchCase ":" [ StatementList ] .
TypeSwitchCase = "case" Type | "default" . TypeSwitchCase = "case" Type | "default" .
</pre> </pre>
<p> <p>
As a special case, the type in the type switch case may be an The TypeSwitchGuard may include a
identifier denoting the predeclared constant <code>nil</code> <a href="#Short_variable_declarations">short variable declaration</a>.
<a href="#Predeclared_identifiers">Predeclared identifiers</a>). When that form is used, the variable is declared in each clause.
If the interface value equals <code>nil</code>, In clauses with a case listing exactly one type, the variable
only an explict <code>nil</code> case or "default" has that type; otherwise, the variable has the type of the expression
case will execute. in the TypeSwitchGuard.
</p> </p>
<p> <p>
Given a function <code>f</code> The type in a case may be <code>nil</code>
that returns a value of interface type, <a href="#Predeclared_identifiers">Predeclared identifiers</a>);
that case is used when the expression in the TypeSwitchGuard
is a nil interface value.
</p>
<p>
Given a function <code>f</code> that returns
a value of type <code>interface{}</code>,
the following type switch: the following type switch:
</p> </p>
@ -3318,11 +3324,13 @@ switch i := f().(type) {
case nil: case nil:
printString("f() returns nil"); printString("f() returns nil");
case int: 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: case func(int) float:
printFunction(i); // i is a function printFunction(i); // i is a function
case bool, string:
printString("type is bool or string"); // i is an interface{}
default: default:
printString("don't know the type"); printString("don't know the type");
} }
@ -3337,25 +3345,31 @@ v := f();
if v == nil { if v == nil {
printString("f() returns nil"); printString("f() returns nil");
} else if i, is_int := v.(int); is_int { } else if i, is_int := v.(int); is_int {
printInt(i); // i is an int printInt(i); // i is an int
} else if i, is_float := v.(float); is_float { } else if i, is_float := v.(float); is_float {
printFloat(i); // i is a float printFloat(i); // i is a float
} else if i, is_func := v.(func(int) float); is_func { } else if i, is_func := v.(func(int) float); is_func {
printFunction(i); // i is a function printFunction(i); // i is a function
} else { } else {
printString("don't know the type"); i1, is_bool := v.(bool);
i2, is_string := v.(string);
if is_bool || is_string {
i := v;
printString("type is bool or string"); // i is an interface{}
} else {
i := v;
printString("don't know the type"); // i is an interface{}
}
} }
</pre> </pre>
<p> <p>
In a type switch, the guard is mandatory, The type switch guard may be preceded by a simple statement, which
there can be only one type per "case", and executes before the guard is evaluated.
the "fallthrough" statement is not allowed.
</p> </p>
<p> <p>
The type switch guard may be preceded by a simple statement, which The "fallthrough" statement is not permitted in a type switch.
executes before the guard is evaluated.
</p> </p>
<h3 id="For_statements">For statements</h3> <h3 id="For_statements">For statements</h3>