FAQ
Reviewers: rsc, iant, r, ken2,

Message:
Hello rsc@golang.org, iant@golang.org, r@golang.org, ken@golang.org (cc:
golang-dev@googlegroups.com),

I'd like you to review this change to
https://code.google.com/p/go


Description:
spec: type assertions and type switches must be valid

The spec didn't preclude invalid type assertions and
type switches, i.e., cases where the actual type doesn't
implement the interface type in the assertio in the first
place. Both, the gc and gccgo compiler exclude these cases.
This is documenting the status quo.

Also:
- minor clean up of respective examples
- added sentence about default case in select statements

Fixes issue 4472.

Please review this at https://codereview.appspot.com/6869050/

Affected files:
M doc/go_spec.html


Index: doc/go_spec.html
===================================================================
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
- "Subtitle": "Version of November 29, 2012",
+ "Subtitle": "Version of December 3, 2012",
"Path": "/ref/spec"
}-->

@@ -2669,7 +2669,10 @@
that the dynamic type of <code>x</code> is <a
href="#Type_identity">identical</a>
to the type <code>T</code>.
If <code>T</code> is an interface type, <code>x.(T)</code> asserts that
the dynamic type
-of <code>x</code> implements the interface <code>T</code> (§<a
href="#Interface_types">Interface types</a>).
+of <code>x</code> implements the interface <code>T</code>.
+Type <code>T</code> must <a href="#Method_sets">implement</a> the
(interface) type of <code>x</code>,
+otherwise the type assertion is invalid since it is not possible for
<code>x</code>
+to store a value of type <code>T</code> in the first place.
</p>
<p>
If the type assertion holds, the value of the expression is the value
@@ -2679,8 +2682,17 @@
is known only at run time, the type of <code>x.(T)</code> is
known to be <code>T</code> in a correct program.
</p>
-<p>
-If a type assertion is used in an assignment or initialization of the form
+
+<pre>
+var x interface{} = 7 // x has dynamic type int and value 7
+i := x.(int) // i has type int and value 7
+
+var y interface { m() }
+s := y.(string) // illegal: string does not implement the type of y
(missing method m)
+</pre>
+
+<p>
+If a type assertion is used in an <a href="#Assignments">assignment</a> or
initialization of the form
</p>

<pre>
@@ -2696,7 +2708,7 @@
is the <a href="#The_zero_value">zero value</a> for type <code>T</code>.
No run-time panic occurs in this case.
The type assertion in this construct thus acts like a function call
-returning a value and a boolean indicating success. (§<a
href="#Assignments">Assignments</a>)
+returning a value and a boolean indicating success.
</p>


@@ -4157,9 +4169,18 @@
A type switch compares types rather than values. It is otherwise similar
to an expression switch. It is marked by a special switch expression that
has the form of a <a href="#Type_assertions">type assertion</a>
-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 assertion.
+using the reserved word <code>type</code> rather than an actual type:
+</p>
+
+<pre>
+x.(type)
+</pre>
+
+<p>
+Cases then match actual types <code>T</code> against the dynamic type of
the
+expression <code>x</code>. As for type assertions, <code>x</code> must be
of
+<a href="#Interface_types">interface type</a>, and each type <code>T</code>
+listed in each case must implement the type of <code>x</code>.
</p>

<pre class="ebnf">
@@ -4195,17 +4216,17 @@
<pre>
switch i := x.(type) {
case nil:
- printString("x is nil")
+ printString("x is nil") // type of i is type of x
(interface{})
case int:
- printInt(i) // i is an int
+ printInt(i) // type of i is int
case float64:
- printFloat64(i) // i is a float64
+ printFloat64(i) // type of i is float64
case func(int) float64:
- printFunction(i) // i is a function
+ printFunction(i) // type of i is func(int) float64
case bool, string:
- printString("type is bool or string") // i is an interface{}
+ printString("type is bool or string") // type of i is type of x
(interface{})
default:
- printString("don't know the type")
+ printString("don't know the type") // type of i is type of x
(interface{})
}
</pre>

@@ -4216,22 +4237,23 @@
<pre>
v := x // x is evaluated exactly once
if v == nil {
+ i := v // type of i is type of x
(interface{})
printString("x is nil")
} else if i, isInt := v.(int); isInt {
- printInt(i) // i is an int
+ printInt(i) // type of i is int
} else if i, isFloat64 := v.(float64); isFloat64 {
- printFloat64(i) // i is a float64
+ printFloat64(i) // type of i is float64
} else if i, isFunc := v.(func(int) float64); isFunc {
- printFunction(i) // i is a function
+ printFunction(i) // type of i is func(int) float64
} else {
- i1, isBool := v.(bool)
- i2, isString := v.(string)
+ _, isBool := v.(bool)
+ _, isString := v.(string)
if isBool || isString {
- i := v
- printString("type is bool or string") // i is an interface{}
+ i := v // type of i is type of x (interface{})
+ printString("type is bool or string")
} else {
- i := v
- printString("don't know the type") // i is an interface{}
+ i := v // type of i is type of x (interface{})
+ printString("don't know the type")
}
}
</pre>
@@ -4498,7 +4520,8 @@
chosen and the corresponding communication and statements are
evaluated. Otherwise, if there is a default case, that executes;
if there is no default case, the statement blocks until one of the
communications can
-complete.
+complete. There can be at most one default case and it may appear anywhere
in the
+"select" statement.
If there are no cases with non-<code>nil</code> channels,
the statement blocks forever.
Even if the statement blocks,

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-dev @
categoriesgo
postedDec 3, '12 at 6:37p
activeDec 3, '12 at 10:37p
posts5
users3
websitegolang.org

3 users in discussion

Gri: 3 posts Rsc: 1 post Iant: 1 post

People

Translate

site design / logo © 2022 Grokbase