mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
go spec: clean-up and consolidation of spec with implementation
Specifically: - introduced notion of "underlying type" - removed notion of type compatibility - consolidated rules about assignment compatibility in assignment compatibility section - be consistent with specyfing that nil is the value for uninitialized variables that can be nil (this was not specified clearly for pointers, functions, interfaces) - added/fixed various related links throughout - clarify language on conversions R=rsc, r, iant, ken2 CC=golang-dev https://golang.org/cl/1536041
This commit is contained in:
parent
129c6c14d1
commit
7bc03718f4
1 changed files with 128 additions and 121 deletions
249
doc/go_spec.html
249
doc/go_spec.html
|
@ -1,5 +1,5 @@
|
|||
<!-- title The Go Programming Language Specification -->
|
||||
<!-- subtitle Version of June 1, 2010 -->
|
||||
<!-- subtitle Version of June 7, 2010 -->
|
||||
|
||||
<!--
|
||||
TODO
|
||||
|
@ -609,6 +609,27 @@ interface, slice, map, and channel types—may be constructed using
|
|||
type literals.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
|
||||
is a predeclared type or a type literal, the corresponding underlying
|
||||
type is <code>T</code> itself. Otherwise, <code>T</code>'s underlying type
|
||||
is the underlying type of the type to which <code>T</code> refers in its
|
||||
<a href="#Type_declarations">type declaration</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type T1 string
|
||||
type T2 T1
|
||||
type T3 []T1
|
||||
type T4 T3
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The underlying type of <code>string</code>, <code>T1</code>, and <code>T2</code>
|
||||
is <code>string</code>. The underlying type of <code>[]T1</code>, <code>T3</code>,
|
||||
and <code>T4</code> is <code>[]T1</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A type may have a <i>method set</i> associated with it
|
||||
(§<a href="#Interface_types">Interface types</a>, §<a href="#Method_declarations">Method declarations</a>).
|
||||
|
@ -626,7 +647,8 @@ The <i>static type</i> (or just <i>type</i>) of a variable is the
|
|||
type defined by its declaration. Variables of interface type
|
||||
also have a distinct <i>dynamic type</i>, which
|
||||
is the actual type of the value stored in the variable at run-time.
|
||||
The dynamic type may vary during execution but is always assignment compatible
|
||||
The dynamic type may vary during execution but is always
|
||||
<a href="#Assignment_compatibility">assignment compatible</a>
|
||||
to the static type of the interface variable. For non-interface
|
||||
types, the dynamic type is always the static type.
|
||||
</p>
|
||||
|
@ -687,7 +709,7 @@ uintptr an unsigned integer large enough to store the uninterpreted bits of a p
|
|||
To avoid portability issues all numeric types are distinct except
|
||||
<code>byte</code>, which is an alias for <code>uint8</code>.
|
||||
Conversions
|
||||
are required when incompatible numeric types are mixed in an expression
|
||||
are required when different numeric types are mixed in an expression
|
||||
or assignment. For instance, <code>int32</code> and <code>int</code>
|
||||
are not the same type even though they may have the same size on a
|
||||
particular architecture.
|
||||
|
@ -753,7 +775,7 @@ multi-dimensional types.
|
|||
A slice is a reference to a contiguous segment of an array and
|
||||
contains a numbered sequence of elements from that array. A slice
|
||||
type denotes the set of all slices of arrays of its element type.
|
||||
A slice value may be <code>nil</code>.
|
||||
The value of an uninitialized slice is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -791,7 +813,6 @@ built-in function <code>cap(a)</code> and the relationship between
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
The value of an uninitialized slice is <code>nil</code>.
|
||||
The length and capacity of a <code>nil</code> slice
|
||||
are 0. A new, initialized slice value for a given element type <code>T</code> is
|
||||
made using the built-in function <code>make</code>, which takes a slice type
|
||||
|
@ -938,7 +959,7 @@ struct {
|
|||
<p>
|
||||
A pointer type denotes the set of all pointers to variables of a given
|
||||
type, called the <i>base type</i> of the pointer.
|
||||
A pointer value may be <code>nil</code>.
|
||||
The value of an unitialized pointer is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -955,8 +976,8 @@ BaseType = Type .
|
|||
|
||||
<p>
|
||||
A function type denotes the set of all functions with the same parameter
|
||||
and result types.
|
||||
A function value may be <code>nil</code>.
|
||||
and result types. The value of an unitialized variable of function type
|
||||
is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -1006,7 +1027,8 @@ func(n int) func(p *T)
|
|||
An interface type specifies a <a href="#Types">method set</a> called its <i>interface</i>.
|
||||
A variable of interface type can store a value of any type with a method set
|
||||
that is any superset of the interface. Such a type is said to
|
||||
<i>implement the interface</i>. An interface value may be <code>nil</code>.
|
||||
<i>implement the interface</i>.
|
||||
The value of an unitialized variable of interface type is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -1110,8 +1132,7 @@ type File interface {
|
|||
A map is an unordered group of elements of one type, called the
|
||||
element type, indexed by a set of unique <i>keys</i> of another type,
|
||||
called the key type.
|
||||
A map value may be <code>nil</code>.
|
||||
|
||||
The value of an uninitialized map is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -1143,7 +1164,6 @@ Values may be added and removed
|
|||
during execution using special forms of <a href="#Assignments">assignment</a>.
|
||||
</p>
|
||||
<p>
|
||||
The value of an uninitialized map is <code>nil</code>.
|
||||
A new, empty map value is made using the built-in
|
||||
function <code>make</code>, which takes the map type and an optional
|
||||
capacity hint as arguments:
|
||||
|
@ -1166,7 +1186,7 @@ stored in them.
|
|||
A channel provides a mechanism for two concurrently executing functions
|
||||
to synchronize execution and communicate by passing a value of a
|
||||
specified element type.
|
||||
A value of channel type may be <code>nil</code>.
|
||||
The value of an uninitialized channel is <code>nil</code>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -1200,7 +1220,7 @@ chan (<-chan int)
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
The value of an uninitialized channel is <code>nil</code>. A new, initialized channel
|
||||
A new, initialized channel
|
||||
value can be made using the built-in function
|
||||
<a href="#Making_slices_maps_and_channels"><code>make</code></a>,
|
||||
which takes the channel type and an optional capacity as arguments:
|
||||
|
@ -1224,21 +1244,17 @@ A channel may be closed and tested for closure with the built-in functions
|
|||
|
||||
<h2 id="Properties_of_types_and_values">Properties of types and values</h2>
|
||||
|
||||
<h3 id="Type_identity">Type identity</h3>
|
||||
|
||||
<p>
|
||||
Two types are either <i>identical</i> or <i>different</i>, and they are
|
||||
either <i>compatible</i> or <i>incompatible</i>.
|
||||
Identical types are always compatible, but compatible types need not be identical.
|
||||
Two types are either <i>identical</i> or <i>different</i>.
|
||||
</p>
|
||||
|
||||
<h3 id="Type_identity_and_compatibility">Type identity and compatibility</h3>
|
||||
|
||||
<h4 id="Type_identity">Type identity</h4>
|
||||
|
||||
<p>
|
||||
Two named types are identical if their type names originate in the same
|
||||
type declaration (§<a href="#Declarations_and_scope">Declarations and scope</a>).
|
||||
type <a href="#Declarations_and_scope">declaration</a>.
|
||||
A named and an unnamed type are always different. Two unnamed types are identical
|
||||
if the corresponding type literals are identical; that is if they have the same
|
||||
if the corresponding type literals are identical, that is, if they have the same
|
||||
literal structure and corresponding components have identical types. In detail:
|
||||
</p>
|
||||
|
||||
|
@ -1272,14 +1288,6 @@ literal structure and corresponding components have identical types. In detail:
|
|||
the same direction.</li>
|
||||
</ul>
|
||||
|
||||
<h4 id="Type_compatibility">Type compatibility</h4>
|
||||
|
||||
<p>
|
||||
Type compatibility is less stringent than type identity: All identical types are
|
||||
compatible, but additionally a named and an unnamed type are compatible if the
|
||||
respective type literals are identical.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Given the declarations
|
||||
</p>
|
||||
|
@ -1307,46 +1315,45 @@ func(x int, y float) *[]string and func(int, float) (result *[]string)
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
<code>T0</code> and <code>T1</code> are neither identical nor compatible
|
||||
because they are named types with distinct declarations.
|
||||
<code>T0</code> and <code>T1</code> are different because they are named types
|
||||
with distinct declarations; <code>func(int, float) *T0</code> and
|
||||
<code>func(x int, y float) *[]string</code> are different because <code>T0</code>
|
||||
is different from <code>[]string</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These types are compatible:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
T0 and T0
|
||||
T0 and []string
|
||||
T3 and struct { a int; c int }
|
||||
T4 and func(x int, y float) (result *T0)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<code>T2</code> and <code>struct { a, c int }</code> are incompatible because
|
||||
they have different field names; <code>T4</code> and
|
||||
<code>func(x int, y float) *[]string</code> are incompatible because the
|
||||
respective type literals are different.
|
||||
</p>
|
||||
|
||||
<h3 id="Assignment_compatibility">Assignment compatibility</h3>
|
||||
|
||||
<p>
|
||||
A value <code>v</code> of static type <code>V</code> is <i>assignment compatible</i>
|
||||
with a type <code>T</code> if one or more of the following conditions applies:
|
||||
A value <code>x</code> is <i>assignment compatible</i> with type <code>T</code>
|
||||
(<code>x</code> <i>can be assigned to</i> <code>T</code>) in any of these cases:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>V</code> is compatible with <code>T</code>.
|
||||
<code>x</code>'s type is identical to <code>T</code>.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type <code>V</code> or <code>T</code> have identical
|
||||
<a href="#Types">underlying types</a> and <code>V</code> or <code>T</code>
|
||||
is not a named type.
|
||||
</li>
|
||||
<li>
|
||||
<code>T</code> is an interface type and
|
||||
<code>V</code> <a href="#Interface_types">implements</a> <code>T</code>.
|
||||
<code>x</code> <a href="#Interface_types">implements</a> <code>T</code>.
|
||||
</li>
|
||||
<li>
|
||||
<code>V</code> is a bidirectional channel and <code>T</code> is a channel type
|
||||
with identical element type and at least one of <code>V</code> or <code>T</code> is unnamed.
|
||||
<code>x</code> is a bidirectional channel value, <code>T</code> is a channel type,
|
||||
<code>x</code>'s type <code>V</code> and <code>T</code> have identical element types,
|
||||
and <code>V</code> or <code>T</code> is not a named type.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code> is the predeclared identifier <code>nil</code> and <code>T</code>
|
||||
is a pointer, function, slice, map, channel, or interface type.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code> is an untyped <a href="#Constants">constant</a> representable
|
||||
by a value of type <code>T</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
@ -1358,18 +1365,6 @@ In other words, a struct value can be assigned to a struct variable only if
|
|||
every field of the struct may be legally assigned individually by the program.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An untyped <a href="#Constants">constant</a> <code>v</code>
|
||||
is assignment compatible with type <code>T</code> if <code>v</code>
|
||||
can be represented accurately as a value of type <code>T</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The predeclared identifier <code>nil</code> is assignment compatible with any
|
||||
pointer, function, slice, map, channel, or interface type and
|
||||
represents the <a href="#The_zero_value">zero value</a> for that type.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>.
|
||||
</p>
|
||||
|
@ -1491,11 +1486,11 @@ The following identifiers are implicitly declared in the universe block:
|
|||
</p>
|
||||
<pre class="grammar">
|
||||
Basic types:
|
||||
bool byte float32 float64 int8 int16 int32 int64
|
||||
string uint8 uint16 uint32 uint64
|
||||
bool byte complex64 complex128 float32 float64
|
||||
int8 int16 int32 int64 string uint8 uint16 uint32 uint64
|
||||
|
||||
Architecture-specific convenience types:
|
||||
float int uint uintptr
|
||||
complex float int uint uintptr
|
||||
|
||||
Constants:
|
||||
true false iota
|
||||
|
@ -1659,10 +1654,9 @@ last non-empty expression list.
|
|||
|
||||
<p>
|
||||
A type declaration binds an identifier, the <i>type name</i>, to a new type
|
||||
that has the same definition (element, fields, channel direction, etc.) as
|
||||
an existing type. The new type is
|
||||
<a href="#Properties_of_types_and_values">compatible</a> with, but
|
||||
<a href="#Properties_of_types_and_values">different</a> from, the existing type.
|
||||
that has the same <a href="#Types">underlying type</a> as
|
||||
an existing type. The new type is <a href="#Type_identity">different</a> from
|
||||
the existing type.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
|
@ -2498,8 +2492,8 @@ The notation <code>x.(T)</code> is called a <i>type assertion</i>.
|
|||
</p>
|
||||
<p>
|
||||
More precisely, if <code>T</code> is not an interface type, <code>x.(T)</code> asserts
|
||||
that the dynamic type of <code>x</code> is identical to the type <code>T</code>
|
||||
(§<a href="#Type_identity">Type identity and compatibility</a>).
|
||||
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>).
|
||||
</p>
|
||||
|
@ -2672,7 +2666,7 @@ Within <code>Greeting</code>, <code>who</code> will have value
|
|||
As a special case, if a function passes its own <code>...</code> parameter,
|
||||
with or without specified type, as the argument
|
||||
for a <code>...</code> in a call to another function with a <code>...</code> parameter
|
||||
of identical type,
|
||||
of <a href="#Type_identity">identical type</a>,
|
||||
the parameter is not wrapped again but passed directly. In short, a formal <code>...</code>
|
||||
parameter is passed unchanged as an actual <code>...</code> parameter provided the
|
||||
types match.
|
||||
|
@ -2700,8 +2694,7 @@ unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
|
|||
|
||||
<p>
|
||||
Comparisons are discussed <a href="#Comparison_operators">elsewhere</a>.
|
||||
For other binary operators, the operand types must be identical
|
||||
(§<a href="#Properties_of_types_and_values">Properties of types and values</a>)
|
||||
For other binary operators, the operand types must be <a href="#Type_identity">identical</a>
|
||||
unless the operation involves channels, shifts, or untyped <a href="#Constants">constants</a>.
|
||||
For operations involving constants only, see the section on
|
||||
<a href="#Constant_expressions">constant expressions</a>.
|
||||
|
@ -2924,8 +2917,8 @@ Comparison operators compare two operands and yield a value of type <code>bool</
|
|||
The operands must be <i>comparable</i>; that is, the first operand
|
||||
must be <a href="#Assignment_compatibility">assignment compatible</a>
|
||||
with the type of the second operand, or vice versa.
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
The operators <code>==</code> and <code>!=</code> apply
|
||||
to operands of all types except arrays and structs.
|
||||
All other comparison operators apply only to integer, floating-point
|
||||
|
@ -2969,7 +2962,7 @@ and string values. The result of a comparison is defined as follows:
|
|||
or if both are <code>nil</code>.
|
||||
</li>
|
||||
<li>
|
||||
Interface values are equal if they have identical dynamic types and
|
||||
Interface values are equal if they have <a href="#Type_identity">identical</a> dynamic types and
|
||||
equal dynamic values or if both are <code>nil</code>.
|
||||
</li>
|
||||
<li>
|
||||
|
@ -3259,51 +3252,65 @@ If the type starts with an operator it must be parenthesized:
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
In general, a conversion is permitted if
|
||||
A value <code>x</code> can be converted to type <code>T</code> in any
|
||||
of these cases:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<code>x</code> can be <a href="#Assignment_compatibility">assigned</a>
|
||||
to <code>T</code>.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type and <code>T</code> have identical
|
||||
<a href="#Types">underlying types</a>.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type and <code>T</code> are unnamed pointer types
|
||||
and their pointer base types have identical underlying types.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type and <code>T</code> are both integer or floating
|
||||
point types.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code>'s type and <code>T</code> are both complex types.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code> is an integer or has type <code>[]byte</code> or
|
||||
<code>[]int</code> and <code>T</code> is a string type.
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code> is a string and <code>T</code> is <code>[]byte</code> or
|
||||
<code>[]int</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Specific rules apply to conversions between numeric types or to and from
|
||||
a string type.
|
||||
These conversions may change the representation of <code>x</code>
|
||||
and incur a run-time cost.
|
||||
All other conversions only change the type but not the representation
|
||||
of <code>x</code>.
|
||||
</p>
|
||||
|
||||
<h4>Conversions between numeric types</h4>
|
||||
<ol>
|
||||
<li>
|
||||
the value of <code>x</code> would be
|
||||
<a href="#Assignment_compatibility">assignment compatible</a> with type
|
||||
<code>T</code> if <code>T</code> were unnamed
|
||||
</li>
|
||||
<li>
|
||||
<code>x</code> is of an unnamed pointer type and type <code>T</code> is another
|
||||
unnamed pointer type and the previous rule applies to the pointer base types.
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
Such a conversion changes the type but not the representation of <code>x</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Specific rules apply to conversions where <code>T</code> is a
|
||||
numeric or string type, or where <code>x</code> is of string type.
|
||||
These conversions may change the representation of a value and incur a run-time cost.
|
||||
</p>
|
||||
|
||||
<h4>Conversions between integer types</h4>
|
||||
<p>
|
||||
If the value is a signed quantity, it is
|
||||
sign extended to implicit infinite precision; otherwise it is zero
|
||||
extended. It is then truncated to fit in the result type's size.
|
||||
For example, if <code>x := uint16(0x10F0)</code>, then <code>uint32(int8(x)) == 0xFFFFFFF0</code>.
|
||||
When converting between integer types, if the value is a signed integer, it is
|
||||
sign extended to implicit infinite precision; otherwise it is zero extended.
|
||||
It is then truncated to fit in the result type's size.
|
||||
For example, if <code>v := uint16(0x10F0)</code>, then <code>uint32(int8(v)) == 0xFFFFFFF0</code>.
|
||||
The conversion always yields a valid value; there is no indication of overflow.
|
||||
</p>
|
||||
|
||||
<h4>Conversions involving floating point and complex types</h4>
|
||||
<ol>
|
||||
</li>
|
||||
<li>
|
||||
When converting a floating-point number to an integer, the fraction is discarded
|
||||
(truncation towards zero).
|
||||
</li>
|
||||
<li>
|
||||
A value of complex type may be converted to a different complex type,
|
||||
but there is no conversion between complex and any other type.
|
||||
</li>
|
||||
<li>
|
||||
When converting a number to a floating-point or complex type,
|
||||
the result value is rounded
|
||||
When converting an integer or floating-point number to a floating-point type,
|
||||
or a complex number to another complex type, the result value is rounded
|
||||
to the precision specified by the destination type.
|
||||
For instance, the value of a variable <code>x</code> of type <code>float32</code>
|
||||
may be stored using additional precision beyond that of an IEEE-754 32-bit number,
|
||||
|
@ -3325,8 +3332,8 @@ implementation-dependent.
|
|||
<ol>
|
||||
<li>
|
||||
Converting a signed or unsigned integer value to a string type yields a
|
||||
string containing the UTF-8 representation of the integer.
|
||||
Negative values are converted to <code>"\uFFFD"</code>.
|
||||
string containing the UTF-8 representation of the integer. Values outside
|
||||
the range of valid Unicode code points are converted to <code>"\uFFFD"</code>.
|
||||
|
||||
<pre>
|
||||
string('a') // "a"
|
||||
|
@ -4486,7 +4493,7 @@ m := make(map[string] int, 100) // map with initial space for 100 elements
|
|||
The built-in function <code>copy</code> copies slice elements from
|
||||
a source <code>src</code> to a destination <code>dst</code> and returns the
|
||||
number of elements copied. Source and destination may overlap.
|
||||
Both arguments must have identical element type <code>T</code> and must be
|
||||
Both arguments must have <a href="#Type_identity">identical</a> element type <code>T</code> and must be
|
||||
<a href="#Assignment_compatibility">assignment compatible</a> to a slice
|
||||
of type <code>[]T</code>. The number of arguments copied is the minimum of
|
||||
<code>len(src)</code> and <code>len(dst)</code>.
|
||||
|
|
Loading…
Reference in a new issue