1
0
mirror of https://github.com/golang/go synced 2024-11-22 01:24:42 -07:00

Continue editing types section.

Do a little work polishing the "zero value" discussion.

R=gri
DELTA=486  (129 added, 120 deleted, 237 changed)
OCL=25392
CL=25444
This commit is contained in:
Rob Pike 2009-02-25 16:20:44 -08:00
parent cdbf619750
commit 8f2330dd7a

View File

@ -366,10 +366,8 @@ the destination must be able to represent the assigned value.
</p> </p>
<p> <p>
Implementation restriction: A compiler may implement ideal numbers Implementation restriction: A compiler may implement ideal numbers
by choosing a large internal representation of such numbers. by choosing an internal representation with at least twice the precision
<br> of any machine type.
<font color=red>TODO: This is too vague. It used to say "sufficiently"
but that doesn't help. Define a minimum?</font>
</p> </p>
<h3>Character literals</h3> <h3>Character literals</h3>
@ -517,11 +515,6 @@ These examples all represent the same string:
"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // The explicit UTF-8 bytes "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e" // The explicit UTF-8 bytes
</pre> </pre>
<pre>
"Alea iacta est."
"Alea " /* The die */ `iacta est` /* is cast */ "."
</pre>
<p> <p>
If the source code represents a character as two code points, such as If the source code represents a character as two code points, such as
a combining form involving an accent and a letter, the result will be a combining form involving an accent and a letter, the result will be
@ -534,18 +527,17 @@ literal.
<h2>Types</h2> <h2>Types</h2>
<p> <p>
A type determines a set of values and operations specific to values of that type. A type determines the set of values and operations specific to values of that type.
A type may be specified by a (possibly qualified (§Qualified identifiers)) A type may be specified by a (possibly qualified (§Qualified identifiers))
type name (§Type declarations) or a <i>type literal</i>, type name (§Type declarations) or a <i>type literal</i>,
which composes a new type in terms of previously declared types. which composes a new type in terms of previously declared types.
</p> </p>
<pre class="grammar"> <pre class="grammar">
Type = TypeName | TypeLit | "(" Type ")" . Type = TypeName | TypeLit | "(" Type ")" .
TypeName = QualifiedIdent. TypeName = QualifiedIdent.
TypeLit = TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
ArrayType | StructType | PointerType | FunctionType | InterfaceType | SliceType | MapType | ChannelType .
SliceType | MapType | ChannelType .
</pre> </pre>
<p> <p>
@ -667,37 +659,11 @@ A sequence of string literals is concatenated into a single string.
StringLit = string_lit { string_lit } . StringLit = string_lit { string_lit } .
</pre> </pre>
<h3>Array types</h3>
<p>
An array is a numbered sequence of elements of a single
type, called the element type, which must be complete
(§Types). The number of elements is called the length and is never
negative.
</p>
<pre class="grammar">
ArrayType = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = CompleteType .
</pre>
<p>
The length is part of the array's type and must must be a constant
expression (§Constant expressions) that evaluates to a non-negative
integer value. The length of array <code>a</code> can be discovered
using the built-in function <code>len(a)</code>, which is a
compile-time constant. The elements can be indexed by integer
indices 0 through the <code>len(a)-1</code> (§Indexes).
</p>
<pre> <pre>
[32]byte "Alea iacta est."
[2*N] struct { x, y int32 } "Alea " /* The die */ `iacta est` /* is cast */ "."
[1000]*float64
</pre> </pre>
<h3>Struct types</h3> <h3>Struct types</h3>
<p> <p>
@ -782,12 +748,42 @@ struct {
} }
</pre> </pre>
<h3>Array types</h3>
<p>
An array is a numbered sequence of elements of a single
type, called the element type, which must be complete
(§Types). The number of elements is called the length and is never
negative.
</p>
<pre class="grammar">
ArrayType = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = CompleteType .
</pre>
<p>
The length is part of the array's type and must must be a constant
expression (§Constant expressions) that evaluates to a non-negative
integer value. The length of array <code>a</code> can be discovered
using the built-in function <code>len(a)</code>, which is a
compile-time constant. The elements can be indexed by integer
indices 0 through the <code>len(a)-1</code> (§Indexes).
</p>
<pre>
[32]byte
[2*N] struct { x, y int32 }
[1000]*float64
</pre>
<h3>Pointer types</h3> <h3>Pointer types</h3>
<p> <p>
A pointer type denotes the set of all pointers to variables of a given A pointer type denotes the set of all pointers to variables of a given
type, called the ``base type'' of the pointer, and the value <code>nil</code>. type, called the ``base type'' of the pointer.
A pointer value may be <code>nil</code>.
</p> </p>
<pre class="grammar"> <pre class="grammar">
@ -797,38 +793,43 @@ BaseType = Type .
<pre> <pre>
*int *int
map[string] chan *map[string] *chan int
</pre> </pre>
<p>
The pointer base type may be an incomplete type (§Types).
</p>
<h3>Function types</h3> <h3>Function types</h3>
<p>TODO: stopped fine-grained editing here </p> <p>
A function type denotes the set of all functions with the same parameter A function type denotes the set of all functions with the same parameter
and result types, and the value "nil". and result types.
A function value may be <code>nil</code>.
</p>
<pre class="grammar"> <pre class="grammar">
FunctionType = "func" Signature . FunctionType = "func" Signature .
Signature = "(" [ ParameterList ] ")" [ Result ] . Signature = Parameters [ Result ] .
ParameterList = ParameterDecl { "," ParameterDecl } . Result = Parameters | CompleteType .
ParameterDecl = [ IdentifierList ] ( Type | "..." ) . Parameters = "(" [ ParameterList ] ")" .
Result = Type | "(" ParameterList ")" . ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] ( CompleteType | "..." ) .
</pre> </pre>
In ParameterList, the parameter names (IdentifierList) either must all be
present, or all be absent. If the parameters are named, each name stands
for one parameter of the specified type. If the parameters are unnamed, each
type stands for one parameter of that type.
<p> <p>
For the last incoming parameter only, instead of a parameter type one Within a list of parameters or results, the names (IdentifierList)
may write "...". The ellipsis indicates that the last parameter stands must either all be present or all be absent. If present, each name
for an arbitrary number of additional arguments of any type (including stands for one item (parameter or result) of the specified type; if absent, each
no additional arguments). If the parameters are named, the identifier type stands for one item of that type. Parameter and result
list immediately preceding "..." must contain only one identifier (the lists are always parenthesized except that if there is exactly
name of the last parameter). one unnamed result that is not a function type it may writen as an unparenthesized type.
The types of parameters and results must be complete.
(TODO: is completeness necessary?)
</p>
<p>
For the last parameter only, instead of a type one may write
<code>...</code> to indicate that the function may be invoked with
an arbitrary number (including zero) of additional arguments of any
type. If parameters of such a function are named, the final identifier
list must be a single name, that of the <code>...</code> parameter.
</p>
<pre> <pre>
func () func ()
@ -839,39 +840,41 @@ func (a, b int, z float) bool
func (a, b int, z float) (bool) func (a, b int, z float) (bool)
func (a, b int, z float, opt ...) (success bool) func (a, b int, z float, opt ...) (success bool)
func (int, int, float) (float, *[]int) func (int, int, float) (float, *[]int)
</pre>
If the result type of a function is itself a function type, the result type
must be parenthesized to resolve a parsing ambiguity:
<pre>
func (n int) (func (p* T)) func (n int) (func (p* T))
</pre> </pre>
<h3>Interface types</h3> <h3>Interface types</h3>
Type interfaces may be specified explicitly by interface types. <p>
An interface type denotes the set of all types that implement at least An interface type specifies an unordered set of methods. A variable
the set of methods specified by the interface type, and the value "nil". of interface type can store, dynamically, any value that implements
at least that set of methods.
An interface value may be <code>nil</code>.
</p>
<pre class="grammar"> <pre class="grammar">
InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] . InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] .
MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] . MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] .
MethodSpec = IdentifierList Signature | TypeName . MethodSpec = IdentifierList Signature | InterfaceTypeName .
InterfaceTypeName = TypeName .
</pre> </pre>
<pre> <pre>
// An interface specifying a basic File type. // A simple File interface
interface { interface {
Read, Write (b Buffer) bool; Read, Write (b Buffer) bool;
Close (); Close ();
} }
</pre> </pre>
Any type (including interface types) whose interface has, possibly as a <p>
subset, the complete set of methods of an interface I is said to implement Any type (including interface types) whose interface includes,
interface I. For instance, if two types S1 and S2 have the methods possibly as a subset, the complete set of methods of an interface <code>I</code>
is said to implement interface <code>I</code>.
For instance, if two types <code>S1</code> and <code>S2</code>
have the methods
</p>
<pre> <pre>
func (p T) Read(b Buffer) bool { return ... } func (p T) Read(b Buffer) bool { return ... }
@ -879,18 +882,28 @@ func (p T) Write(b Buffer) bool { return ... }
func (p T) Close() { ... } func (p T) Close() { ... }
</pre> </pre>
(where T stands for either S1 or S2) then the File interface is <p>
implemented by both S1 and S2, regardless of what other methods (where <code>T</code> stands for either <code>S1</code> or <code>S2</code>)
S1 and S2 may have or share. then the <code>File</code> interface is implemented by both <code>S1</code> and
<code>S2</code>, regardless of what other methods
<code>S1</code> and <code>S2</code> may have or share.
</p>
All types implement the empty interface: <p>
A type implements any interface comprising any subset of its methods
and may therefore implement several distinct interfaces. For
instance, all types implement the <i>empty interface</i>:
</p>
<pre> <pre>
interface {} interface { }
</pre> </pre>
In general, a type implements an arbitrary number of interfaces. <p>
For instance, consider the interface Similarly, consider this interface specification,
which appears within a type declaration (§Type declarations)
to define an interface called <code>Lock</code>:
</p>
<pre> <pre>
type Lock interface { type Lock interface {
@ -898,19 +911,26 @@ type Lock interface {
} }
</pre> </pre>
If S1 and S2 also implement <p>
If <code>S1</code> and <code>S2</code> also implement
</p>
<pre> <pre>
func (p T) Lock() { ... } func (p T) Lock() { ... }
func (p T) Unlock() { ... } func (p T) Unlock() { ... }
</pre> </pre>
they implement the Lock interface as well as the File interface.
<p> <p>
An interface may contain a type name T in place of a method specification. they implement the <code>Lock</code> interface as well
T must denote another, complete interface type. as the <code>File</code> interface.
Using this notation is equivalent to enumerating the methods of T explicitly </p>
in the interface containing T. <p>
An interface may contain an interface type name <code>T</code>
in place of a method specification.
In this notation, <code>T</code> must denote a different, complete interface type
and the effect is equivalent to enumerating the methods of <code>T</code> explicitly
in the interface.
</p>
<pre> <pre>
type ReadWrite interface { type ReadWrite interface {
@ -924,128 +944,113 @@ type File interface {
} }
</pre> </pre>
Forward declaration:
A interface type consisting of only the reserved word "interface" may be used in
a type declaration; it declares an incomplete interface type (§Type declarations).
This allows the construction of mutually recursive types such as:
<pre>
type T2 interface
type T1 interface {
foo(T2) int;
}
type T2 interface {
bar(T1) int;
}
</pre>
<h3>Slice types</h3> <h3>Slice types</h3>
A slice type denotes the set of all slices (segments) of arrays <p>
(§Array types) of a given element type, and the value "nil". A slice is a reference to a contiguous segment of an array and
The number of elements of a slice is called its length; it is never negative. contains a numbered sequence of elements from that array. A slice
The elements of a slice are designated by indices which are type denotes the set of all slices of arrays of its element type.
integers from 0 through the length - 1. A slice value may be <code>nil</code>.
</p>
<pre class="grammar"> <pre class="grammar">
SliceType = "[" "]" ElementType . SliceType = "[" "]" ElementType .
</pre> </pre>
Syntactically and semantically, arrays and slices look and behave very
similarly, but with one important difference: A slice is a descriptor
of an array segment; in particular, different variables of a slice type may
refer to different (and possibly overlapping) segments of the same underlying
array. Thus, with respect to the underlying array, slices behave like
references. In contrast, two different variables of array type always
denote two different arrays.
<p> <p>
For slices, the actual array underlying the slice may extend past the current Like arrays, slices are indexable and have a length. The length of a
slice length; the maximum length a slice may assume is called its capacity. slice <code>s</code> can be discovered by the built-in function
The capacity of any slice "a" can be discovered using the built-in function <code>len(s)</code>; unlike with arrays it may change during
execution. The elements can be addressed by integer indices 0
through <code>len(s)-1</code> (§Indexes). The slice index of a
given element may be less than the index of the same element in the
underlying array.
</p>
<p>
A slice, once initialized, is always associated with an underlying
array that holds its elements. A slice therfore shares storage
with its array and with other slices of the same array; by contrast,
distinct arrays always represent distinct storage.
</p>
<p>
The array underlying a slice may extend past the end of the slice.
The <i>capacity</i> is a measure of that extent: it is the sum of
the length of the slice and the length of the array beyond the slice;
a slice of length up to that capacity can be created by `slicing' a new
one from the original slice (§Slices).
The capacity of a slice <code>a</code> can be discovered using the
built-in function
</p>
<pre> <pre>
cap(a) cap(s)
</pre> </pre>
and the following relationship between "len()" and "cap()" holds: <p>
and the relationship between <code>len()</code> and <code>cap()</code> is:
</p>
<pre> <pre>
0 <= len(a) <= cap(a) 0 <= len(a) <= cap(a)
</pre> </pre>
The value of an uninitialized slice is "nil", and its length and capacity <p>
are 0. A new, initialized slice value for a given element type T is The value of an uninitialized slice is <code>nil</code>, and its length and capacity
made using the built-in function "make", which takes a slice type 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
and parameters specifying the length and optionally the capacity: and parameters specifying the length and optionally the capacity:
</p>
<pre> <pre>
make([]T, length) make([]T, length)
make([]T, length, capacity) make([]T, length, capacity)
</pre> </pre>
The "make()" call allocates a new underlying array to which the returned <p>
slice value refers. More precisely, calling "make" The <code>make()</code> call allocates a new, hidden array to which the returned
slice value refers. That is, calling <code>make</code>
</p>
<pre> <pre>
make([]T, length, capacity) make([]T, length, capacity)
</pre> </pre>
is effectively the same as allocating an array and slicing it
<pre>
new([capacity]T)[0 : length]
</pre>
<p> <p>
Indexing: Given a (pointer to) a slice variable "a", a slice element is produces the same slice as allocating an array and slicing it:
specified with an index operation: </p>
<pre> <pre>
a[i] make([capacity]T)[0 : length]
</pre> </pre>
This denotes the slice element at index "i". "i" must be within bounds,
that is "0 &lt;= i &lt; len(a)".
<p>
Slicing: Given a a slice variable "a", a sub-slice is created with a slice
operation:
<pre>
a[i : j]
</pre>
This creates the sub-slice consisting of the elements "a[i]" through "a[j - 1]"
(that is, excluding "a[j]"). The values "i" and "j" must satisfy the condition
"0 &lt;= i &lt;= j &lt;= cap(a)". The length of the new slice is "j - i". The capacity of
the slice is "cap(a) - i"; thus if "i" is 0, the slice capacity does not change
as a result of a slice operation. The type of a sub-slice is the same as the
type of the slice. Unlike the capacity, the length of a sub-slice may be larger
than the length of the original slice.
<h3>Map types</h3> <h3>Map types</h3>
A map is a composite type consisting of a variable number of entries <p>
called (key, value) pairs. For a given map, the keys and values must A map is an unordered group of elements of one type, called the
each be of a specific complete type (§Types) called the key and value type, value type, indexed by a set of unique <i>keys</i> of another type,
respectively. The number of entries in a map is called its length; it is never called the key type. Both key and value types must be complete.
negative. (§Types).
(TODO: is completeness necessary here?)
A map value may be <code>nil</code>.
</p>
<pre class="grammar"> <pre class="grammar">
MapType = "map" "[" KeyType "]" ValueType . MapType = "map" "[" KeyType "]" ValueType .
KeyType = CompleteType . KeyType = CompleteType .
ValueType = CompleteType . ValueType = CompleteType .
</pre> </pre>
The comparison operators "==" and "!=" (§Comparison operators) must be defined
for operands of the key type; thus the key type must be a basic, pointer,
interface, or channel type. If the key type is an interface type,
the dynamic key types must support these comparison operators. In this case,
inserting a map value with a key that does not support testing for equality
is a run-time error.
<p> <p>
Upon creation, a map is empty and values may be added and removed The comparison operators <code>==</code> and <code>!=</code>
during execution. (§Comparison operators) must be fully defined for operands of the
key type; thus the key type must be a basic, pointer, interface,
map, or channel type. If the key type is an interface type, these
comparison operators must be defined for the dynamic key values;
failure will cause a run-time error.
</p>
<pre> <pre>
map [string] int map [string] int
@ -1053,42 +1058,47 @@ map [*T] struct { x, y float }
map [string] interface {} map [string] interface {}
</pre> </pre>
The length of a map "m" can be discovered using the built-in function
<pre>
len(m)
</pre>
The value of an uninitialized map is "nil". A new, empty map value for given
map type M is made using the built-in function "make" which takes the map type
and an optional capacity as arguments:
<pre>
my_map := make(M, 100);
</pre>
<p> <p>
The map capacity is an allocation hint for more efficient incremental growth The number of elements is called the length and is never negative.
of the map. The length of a map <code>m</code> can be discovered using the
built-in function <code>len(m)</code> and may change during execution.
The value of an uninitialized map is <code>nil</code>
</p> </p>
<p>
Upon creation, a map is empty. Values may be added and removed
during execution using special forms of assignment (§Assignments).
A new, empty map value is made using the built-in
function <code>make</code>, which takes the map type and an optional
capacity, an allocation hint, as arguments:
</p>
<pre>
make(map[string] int, 100);
</pre>
<h3>Channel types</h3> <h3>Channel types</h3>
<p>
A channel provides a mechanism for two concurrently executing functions A channel provides a mechanism for two concurrently executing functions
to synchronize execution and exchange values of a specified type. This to synchronize execution and communicate by passing a value of a
type must be a complete type (§Types). specified element type. The element type must be complete (§Types).
(TODO: is completeness necessary here?)
A channel value may be <code>nil</code>.
</p>
<pre class="grammar"> <pre class="grammar">
ChannelType = Channel | SendChannel | RecvChannel . ChannelType = Channel | SendChannel | RecvChannel .
Channel = "chan" ValueType . Channel = "chan" ValueType .
SendChannel = "chan" "&lt;-" ValueType . SendChannel = "chan" "&lt;-" ValueType .
RecvChannel = "&lt;-" "chan" ValueType . RecvChannel = "&lt;-" "chan" ValueType .
</pre> </pre>
Upon creation, a channel can be used both to send and to receive. <p>
Upon creation, a channel can be used both to send and to receive values.
By conversion or assignment, a channel may be constrained only to send or By conversion or assignment, a channel may be constrained only to send or
to receive. This constraint is called a channel's ``direction''; either to receive. This constraint is called a channel's <i>direction</i>; either
bi-directional (unconstrained), send, or receive. <i>send</i>, <i>receive</i>, or <i>bi-directional</i> (unconstrained).
</p>
<pre> <pre>
chan T // can send and receive values of type T chan T // can send and receive values of type T
@ -1096,108 +1106,88 @@ chan &lt;- float // can only be used to send floats
&lt;-chan int // can only receive ints &lt;-chan int // can only receive ints
</pre> </pre>
The value of an uninitialized channel is "nil". A new, initialized channel <p>
value for a given element type T is made using the built-in function "make", The value of an uninitialized channel is <code>nil</code>. A new, initialized channel
value is made using the built-in function <code>make</code>,
which takes the channel type and an optional capacity as arguments: which takes the channel type and an optional capacity as arguments:
</p>
<pre> <pre>
my_chan = make(chan int, 100); make(chan int, 100);
</pre> </pre>
The capacity sets the size of the buffer in the communication channel. If the <p>
The capacity, in number of elements, sets the size of the buffer in the channel. If the
capacity is greater than zero, the channel is asynchronous and, provided the capacity is greater than zero, the channel is asynchronous and, provided the
buffer is not full, sends can succeed without blocking. If the capacity is zero, buffer is not full, sends can succeed without blocking. If the capacity is zero
the communication succeeds only when both a sender and receiver are ready. or absent, the communication succeeds only when both a sender and receiver are ready.
</p>
<h2>General properties of types and values</h2>
<h3>Type equality</h3>
<p> <p>
Types may be ``different'', ``structurally equal'', or ``identical''. Types may be <i>different</i>, <i>structurally equal</i> (or just <i>equal</i>),
Go is a type-safe language; generally different types cannot be mixed or <i>identical</i>.
in binary operations, and values cannot be assigned to variables of different Go is <i>type safe</i>: different types cannot be mixed
types. However, values may be assigned to variables of structurally in binary operations and values cannot be assigned to variables of different
equal types. Finally, type guards succeed only if the dynamic type types. They can be assigned to variables of equal type.
is identical to or implements the type tested against (§Type guards). </p>
<p>
Structural type equality (equality for short) is defined by these rules: <h3>Type equality and identity </h3>
<p> <p>
Two type names denote equal types if the types in the corresponding declarations Two type names denote equal types if the types in the corresponding declarations
are equal. Two type literals specify equal types if they have the same are equal (§Declarations and Scope).
literal structure and corresponding components have equal types. Loosely Two type literals specify equal types if they have the same
speaking, two types are equal if their values have the same layout in memory. literal structure and corresponding components have equal types.
More precisely: In detail:
</p> </p>
<ul> <ul>
<li>Two array types are equal if they have equal element types and if they <li>Two pointer types are equal if they have equal base types.</li>
have the same array length.
<li>Two struct types are equal if they have the same number of fields in the <li>Two array types are equal if they have equal element types and
same order, corresponding fields either have both the same name or the same array length.</li>
are both anonymous, and corresponding field types are identical.
<li>Two pointer types are equal if they have equal base types. <li>Two struct types are equal if they have the same sequence of fields,
with the same names and equal types. Two anonymous fields are
considered to have the same name.</li>
<li>Two function types are equal if they have the same number of parameters <li>Two function types are equal if they have the same number of parameters
and result values and if corresponding parameter and result types are and result values and if corresponding parameter and result types are
equal (a "..." parameter is equal to another "..." parameter). the same. All "..." parameters have equal type.
Note that parameter and result names do not have to match. Parameter and result names are not required to match.</li>
<li>Two slice types are equal if they have equal element types. <li>Two slice types are equal if they have equal element types.</li>
<li>Two channel types are equal if they have equal value types and <li>Two channel types are equal if they have equal value types and
the same direction. the same direction.</li>
<li>Two map types are equal if they have equal key and value types. <li>Two map types are equal if they have equal key and value types.</li>
<li>Two interface types are equal if they have the same set of methods <li>Two interface types are equal if they have the same set of methods
with the same names and equal function types. Note that the order with the same names and equal function types. The order
of the methods in the respective type declarations is irrelevant. of the methods is irrelevant.</li>
</ul> </ul>
<p> <p>
Type identity is defined by these rules: Type identity is more stringent than type equality.
It requires for type names
that they originate in the same type declaration, while for equality it requires
only that they originate in equal type declarations.
Also, the names of parameters and results must match for function types.
In all other respects, the definition of type identity is the
same as for type equality listed above but with ``identical''
substitued for ``equal''.
</p> </p>
<p> <p>
Two type names denote identical types if they originate in the same By definition, identical types are also equal types.
type declaration. Two type literals specify identical types if they have the Two types are different if they are not equal.
same literal structure and corresponding components have identical types.
More precisely:
</p> </p>
<ul>
<li>Two array types are identical if they have identical element types and if
they have the same array length.
<li>Two struct types are identical if they have the same number of fields in
the same order, corresponding fields either have both the same name or
are both anonymous, and corresponding field types are identical.
<li>Two pointer types are identical if they have identical base types.
<li>Two function types are identical if they have the same number of
parameters and result values both with the same (or absent) names, and
if corresponding parameter and result types are identical (a "..."
parameter is identical to another "..." parameter with the same name).
<li>Two slice types are identical if they have identical element types.
<li>Two channel types are identical if they have identical value types and
the same direction.
<li>Two map types are identical if they have identical key and value types.
<li>Two interface types are identical if they have the same set of methods
with the same names and identical function types. Note that the order
of the methods in the respective type declarations is irrelevant.
</ul>
Note that the type denoted by a type name is identical only to the type literal
in the type name's declaration.
<p> <p>
Finally, two types are different if they are not structurally equal. Given the declarations
(By definition, they cannot be identical, either). </p>
For instance, given the declarations
<pre> <pre>
type ( type (
@ -1210,17 +1200,22 @@ type (
) )
</pre> </pre>
these are some types that are equal <p>
these types are equal
</p>
<pre> <pre>
T0 and T0 T0 and T0
T0 and T1
T0 and []string T0 and []string
T2 and T3 T2 and T3
T4 and T5 T4 and T5
T3 and struct { a int; int } T3 and struct { a int; int }
</pre> </pre>
and these are some types that are identical <p>
and these types are identical
</p>
<pre> <pre>
T0 and T0 T0 and T0
@ -1228,22 +1223,13 @@ T0 and T0
struct { a, b *T5 } and struct { a, b *T5 } struct { a, b *T5 } and struct { a, b *T5 }
</pre> </pre>
As an example, "T0" and "T1" are equal but not identical because they have <p>
different declarations. <code>T0</code> and <code>T1</code> are equal but not
identical because they have distinct declarations.
</p>
<h3>Assignment compatibility</h3> <h3>Assignment compatibility</h3>
<!--
TODO in another round of editing:
It may make sense to have a special section in this doc containing these rule
sets for:
equality of types
identity of types
comparisons
assignment compatibility
-->
<p> <p>
Values of any type may always be assigned to variables Values of any type may always be assigned to variables
of equal static type. Some types and values have conditions under which they may of equal static type. Some types and values have conditions under which they may
@ -1605,7 +1591,7 @@ If there are expressions, their number must be equal
to the number of identifiers, and the n<sup>th</sup> variable to the number of identifiers, and the n<sup>th</sup> variable
is initialized to the value of the n<sup>th</sup> expression. is initialized to the value of the n<sup>th</sup> expression.
Otherwise, each variable is initialized to the <i>zero</i> Otherwise, each variable is initialized to the <i>zero</i>
of the type (§Program initialization and execution). of the type (§The zero value).
The expressions can be general expressions; they need not be constants. The expressions can be general expressions; they need not be constants.
</p> </p>
<p> <p>
@ -1882,7 +1868,7 @@ pi := Num(Rat(22, 7), 3.14159, "pi");
The length of an array literal is the length specified in the LiteralType. The length of an array literal is the length specified in the LiteralType.
If fewer elements than the length are provided in the literal, the missing If fewer elements than the length are provided in the literal, the missing
elements are set to the appropriate zero value for the array element type. elements are set to the zero value for the array element type.
It is an error to provide more elements than specified in LiteralType. The It is an error to provide more elements than specified in LiteralType. The
notation "..." may be used in place of the length expression to denote a notation "..." may be used in place of the length expression to denote a
length equal to the number of elements in the literal. length equal to the number of elements in the literal.
@ -2112,7 +2098,7 @@ TODO: Need to expand map rules for assignments of the form v, ok = m[k].
<h3>Slices</h3> <h3>Slices</h3>
Strings, arrays, and slices can be ``sliced'' to construct substrings or descriptors Strings, arrays, and slices can be <i>sliced</i> to construct substrings or descriptors
of subarrays. The index expressions in the slice select which elements appear of subarrays. The index expressions in the slice select which elements appear
in the result. The result has indexes starting at 0 and length equal to the in the result. The result has indexes starting at 0 and length equal to the
difference in the index values in the slice. After slicing the array "a" difference in the index values in the slice. After slicing the array "a"
@ -2129,8 +2115,11 @@ s[0] == 2
s[1] == 3 s[1] == 3
</pre> </pre>
The index values in the slice must be in bounds for the original The slice length must be non-negative.
array (or string) and the slice length must be non-negative. For arrays or strings,
the index values in the slice must be in bounds for the original
array or string;
for slices, the index values must be between 0 and the capacity of the slice.
<p> <p>
If the sliced operand is a string, the result of the slice operation is another If the sliced operand is a string, the result of the slice operation is another
string (§String types). If the sliced operand is an array or slice, the result string (§String types). If the sliced operand is an array or slice, the result
@ -2173,8 +2162,8 @@ v, ok := x.(T)
the result of the guarded expression is a pair of values with types "(T, bool)". the result of the guarded expression is a pair of values with types "(T, bool)".
If the type guard succeeds, the expression returns the pair "(x.(T), true)"; If the type guard succeeds, the expression returns the pair "(x.(T), true)";
that is, the value stored in "x" (of type "T") is assigned to "v", and "ok" that is, the value stored in "x" (of type "T") is assigned to "v", and "ok"
is set to true. If the type guard fails, the value in "v" is set to the initial is set to true. If the type guard fails, the value in "v" is set to the zero
value for the type of "v" (§Program initialization and execution), and "ok" is value for the type of "v" (§The zero value), and "ok" is
set to false. No run-time exception occurs in this case. set to false. No run-time exception occurs in this case.
<p> <p>
<font color=red> <font color=red>
@ -3490,7 +3479,7 @@ have to be written as type guards? (§Type guards)
The built-in function "new" takes a type "T" and returns a value of type "*T". The built-in function "new" takes a type "T" and returns a value of type "*T".
The memory is initialized as described in the section on initial values The memory is initialized as described in the section on initial values
Program initialization and execution). The zero value).
<pre> <pre>
new(T) new(T)
@ -3518,7 +3507,7 @@ The built-in function "make" takes a type "T", optionally followed by a
type-specific list of expressions. It returns a value of type "T". "T" type-specific list of expressions. It returns a value of type "T". "T"
must be a slice, map, or channel type. must be a slice, map, or channel type.
The memory is initialized as described in the section on initial values The memory is initialized as described in the section on initial values
Program initialization and execution). The zero value).
<pre> <pre>
make(T [, optional list of expressions]) make(T [, optional list of expressions])
@ -3665,29 +3654,38 @@ func main() {
<h2>Program initialization and execution</h2> <h2>Program initialization and execution</h2>
<h3>The zero value</h3>
<p>
When memory is allocated to store a value, either through a declaration When memory is allocated to store a value, either through a declaration
or "new()", and no explicit initialization is provided, the memory is or <code>new()</code>, and no explicit initialization is provided, the memory is
given a default initialization. Each element of such a value is given a default initialization. Each element of such a value is
set to the ``zero'' for that type: "false" for booleans, "0" for integers, set to the zero value for its type: <code>false</code> for booleans,
"0.0" for floats, '''' for strings, and "nil" for pointers and interfaces. <code>0</code> for integers, <code>0.0</code> for floats, <code>""</code>
for strings, and <code>nil</code> for pointers and interfaces.
This initialization is done recursively, so for instance each element of an This initialization is done recursively, so for instance each element of an
array of integers will be set to 0 if no other value is specified. array of structs will have its fields zeroed if no value is specified.
</p>
<p> <p>
These two simple declarations are equivalent: These two simple declarations are equivalent:
</p>
<pre> <pre>
var i int; var i int;
var i int = 0; var i int = 0;
</pre> </pre>
<p>
After After
</p>
<pre> <pre>
type T struct { i int; f float; next *T }; type T struct { i int; f float; next *T };
t := new(T); t := new(T);
</pre> </pre>
<p>
the following holds: the following holds:
</p>
<pre> <pre>
t.i == 0 t.i == 0
@ -3695,43 +3693,54 @@ t.f == 0.0
t.next == nil t.next == nil
</pre> </pre>
<h3>Program execution</h3>
<p>
A package with no imports is initialized by assigning initial values to A package with no imports is initialized by assigning initial values to
all its global variables in declaration order and then calling any init() all its global variables in declaration order and then calling any init()
functions defined in its source. Since a package may contain more functions defined in its source. Since a package may contain more
than one source file, there may be more than one init() function, but than one source file, there may be more than one init() function, but
only one per source file. only one per source file.
</p>
<p> <p>
Initialization code may contain "go" statements, but the functions Initialization code may contain "go" statements, but the functions
they invoke do not begin execution until initialization of the entire they invoke do not begin execution until initialization of the entire
program is complete. Therefore, all initialization code is run in a single program is complete. Therefore, all initialization code is run in a single
thread of execution. thread of execution.
</p>
<p> <p>
Furthermore, an "init()" function cannot be referred to from anywhere Furthermore, an "init()" function cannot be referred to from anywhere
in a program. In particular, "init()" cannot be called explicitly, nor in a program. In particular, "init()" cannot be called explicitly, nor
can a pointer to "init" be assigned to a function variable). can a pointer to "init" be assigned to a function variable).
</p>
<p> <p>
If a package has imports, the imported packages are initialized If a package has imports, the imported packages are initialized
before initializing the package itself. If multiple packages import before initializing the package itself. If multiple packages import
a package P, P will be initialized only once. a package P, P will be initialized only once.
</p>
<p> <p>
The importing of packages, by construction, guarantees that there can The importing of packages, by construction, guarantees that there can
be no cyclic dependencies in initialization. be no cyclic dependencies in initialization.
</p>
<p> <p>
A complete program, possibly created by linking multiple packages, A complete program, possibly created by linking multiple packages,
must have one package called main, with a function must have one package called main, with a function
</p>
<pre> <pre>
func main() { ... } func main() { ... }
</pre> </pre>
defined. The function main.main() takes no arguments and returns no <p>
defined. The function <code>main.main()</code> takes no arguments and returns no
value. value.
</p>
<p> <p>
Program execution begins by initializing the main package and then Program execution begins by initializing the main package and then
invoking main.main(). invoking <code>main.main()</code>.
</p>
<p> <p>
When main.main() returns, the program exits. When main.main() returns, the program exits.
</p>
<hr/> <hr/>