diff --git a/doc/go_spec.html b/doc/go_spec.html index 9f44543c18..0ccf431191 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -366,10 +366,8 @@ the destination must be able to represent the assigned value.

Implementation restriction: A compiler may implement ideal numbers -by choosing a large internal representation of such numbers. -
-TODO: This is too vague. It used to say "sufficiently" -but that doesn't help. Define a minimum? +by choosing an internal representation with at least twice the precision +of any machine type.

Character literals

@@ -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 -
-"Alea iacta est."
-"Alea " /* The die */ `iacta est` /* is cast */ "."
-
-

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 @@ -534,18 +527,17 @@ literal.

Types

-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)) type name (§Type declarations) or a type literal, which composes a new type in terms of previously declared types.

-Type = TypeName | TypeLit | "(" Type ")" .
-TypeName = QualifiedIdent.
-TypeLit =
-	ArrayType | StructType | PointerType | FunctionType | InterfaceType |
-	SliceType | MapType | ChannelType .
+Type      = TypeName | TypeLit | "(" Type ")" .
+TypeName  = QualifiedIdent.
+TypeLit   = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
+	    SliceType | MapType | ChannelType .
 

@@ -667,37 +659,11 @@ A sequence of string literals is concatenated into a single string. StringLit = string_lit { string_lit } . -

Array types

- -

-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. -

- -
-ArrayType   = "[" ArrayLength "]" ElementType .
-ArrayLength = Expression .
-ElementType = CompleteType .
-
- -

-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 a can be discovered -using the built-in function len(a), which is a -compile-time constant. The elements can be indexed by integer -indices 0 through the len(a)-1 (§Indexes). -

-
-[32]byte
-[2*N] struct { x, y int32 }
-[1000]*float64
+"Alea iacta est."
+"Alea " /* The die */ `iacta est` /* is cast */ "."
 
-

Struct types

@@ -782,12 +748,42 @@ struct { } +

Array types

+ +

+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. +

+ +
+ArrayType   = "[" ArrayLength "]" ElementType .
+ArrayLength = Expression .
+ElementType = CompleteType .
+
+ +

+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 a can be discovered +using the built-in function len(a), which is a +compile-time constant. The elements can be indexed by integer +indices 0 through the len(a)-1 (§Indexes). +

+ +
+[32]byte
+[2*N] struct { x, y int32 }
+[1000]*float64
+

Pointer types

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 nil. +type, called the ``base type'' of the pointer. +A pointer value may be nil.

@@ -797,38 +793,43 @@ BaseType = Type .
 
 
 *int
-map[string] chan
+*map[string] *chan int
 
-

-The pointer base type may be an incomplete type (§Types). -

-

Function types

-

TODO: stopped fine-grained editing here

+

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 nil. +

-FunctionType = "func" Signature .
-Signature = "(" [ ParameterList ] ")" [ Result ] .
-ParameterList = ParameterDecl { "," ParameterDecl } .
-ParameterDecl = [ IdentifierList ] ( Type | "..." ) .
-Result = Type | "(" ParameterList ")" .
+FunctionType   = "func" Signature .
+Signature      = Parameters [ Result ] .
+Result         = Parameters | CompleteType .
+Parameters     = "(" [ ParameterList ] ")" .
+ParameterList  = ParameterDecl { "," ParameterDecl } .
+ParameterDecl  = [ IdentifierList ] ( CompleteType | "..." ) .
 
-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.

-For the last incoming parameter only, instead of a parameter type one -may write "...". The ellipsis indicates that the last parameter stands -for an arbitrary number of additional arguments of any type (including -no additional arguments). If the parameters are named, the identifier -list immediately preceding "..." must contain only one identifier (the -name of the last parameter). +Within a list of parameters or results, the names (IdentifierList) +must either all be present or all be absent. If present, each name +stands for one item (parameter or result) of the specified type; if absent, each +type stands for one item of that type. Parameter and result +lists are always parenthesized except that if there is exactly +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?) +

+

+For the last parameter only, instead of a type one may write +... 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 ... parameter. +

 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, opt ...) (success bool)
 func (int, int, float) (float, *[]int)
-
- -If the result type of a function is itself a function type, the result type -must be parenthesized to resolve a parsing ambiguity: - -
 func (n int) (func (p* T))
 

Interface types

-Type interfaces may be specified explicitly by interface types. -An interface type denotes the set of all types that implement at least -the set of methods specified by the interface type, and the value "nil". +

+An interface type specifies an unordered set of methods. A variable +of interface type can store, dynamically, any value that implements +at least that set of methods. +An interface value may be nil. +

-InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] .
-MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] .
-MethodSpec = IdentifierList Signature | TypeName .
+InterfaceType      = "interface" [ "{" [ MethodSpecList ] "}" ] .
+MethodSpecList     = MethodSpec { ";" MethodSpec } [ ";" ] .
+MethodSpec         = IdentifierList Signature | InterfaceTypeName .
+InterfaceTypeName  = TypeName .
 
-// An interface specifying a basic File type.
+// A simple File interface
 interface {
 	Read, Write	(b Buffer) bool;
 	Close		();
 }
 
-Any type (including interface types) whose interface has, possibly as a -subset, the complete set of methods of an interface I is said to implement -interface I. For instance, if two types S1 and S2 have the methods +

+Any type (including interface types) whose interface includes, +possibly as a subset, the complete set of methods of an interface I +is said to implement interface I. +For instance, if two types S1 and S2 +have the methods +

 func (p T) Read(b Buffer) bool { return ... }
@@ -879,18 +882,28 @@ func (p T) Write(b Buffer) bool { return ... }
 func (p T) Close() { ... }
 
-(where T stands for either S1 or S2) then the File interface is -implemented by both S1 and S2, regardless of what other methods -S1 and S2 may have or share. +

+(where T stands for either S1 or S2) +then the File interface is implemented by both S1 and +S2, regardless of what other methods +S1 and S2 may have or share. +

-All types implement the empty interface: +

+A type implements any interface comprising any subset of its methods +and may therefore implement several distinct interfaces. For +instance, all types implement the empty interface: +

-interface {}
+interface { }
 
-In general, a type implements an arbitrary number of interfaces. -For instance, consider the interface +

+Similarly, consider this interface specification, +which appears within a type declaration (§Type declarations) +to define an interface called Lock: +

 type Lock interface {
@@ -898,19 +911,26 @@ type Lock interface {
 }
 
-If S1 and S2 also implement +

+If S1 and S2 also implement +

 func (p T) Lock() { ... }
 func (p T) Unlock() { ... }
 
-they implement the Lock interface as well as the File interface.

-An interface may contain a type name T in place of a method specification. -T must denote another, complete interface type. -Using this notation is equivalent to enumerating the methods of T explicitly -in the interface containing T. +they implement the Lock interface as well +as the File interface. +

+

+An interface may contain an interface type name T +in place of a method specification. +In this notation, T must denote a different, complete interface type +and the effect is equivalent to enumerating the methods of T explicitly +in the interface. +

 type ReadWrite interface {
@@ -924,128 +944,113 @@ type File interface {
 }
 
-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: - -
-type T2 interface
-type T1 interface {
-	foo(T2) int;
-}
-type T2 interface {
-	bar(T1) int;
-}
-
-

Slice types

-A slice type denotes the set of all slices (segments) of arrays -(§Array types) of a given element type, and the value "nil". -The number of elements of a slice is called its length; it is never negative. -The elements of a slice are designated by indices which are -integers from 0 through the length - 1. +

+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 nil. +

 SliceType = "[" "]" ElementType .
 
-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.

-For slices, the actual array underlying the slice may extend past the current -slice length; the maximum length a slice may assume is called its capacity. -The capacity of any slice "a" can be discovered using the built-in function +Like arrays, slices are indexable and have a length. The length of a +slice s can be discovered by the built-in function +len(s); unlike with arrays it may change during +execution. The elements can be addressed by integer indices 0 +through len(s)-1 (§Indexes). The slice index of a +given element may be less than the index of the same element in the +underlying array. +

+

+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. +

+

+The array underlying a slice may extend past the end of the slice. +The capacity 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 a can be discovered using the +built-in function +

-cap(a)
+cap(s)
 
-and the following relationship between "len()" and "cap()" holds: +

+and the relationship between len() and cap() is: +

 0 <= len(a) <= cap(a)
 
-The value of an uninitialized slice is "nil", and its length and capacity -are 0. A new, initialized slice value for a given element type T is -made using the built-in function "make", which takes a slice type +

+The value of an uninitialized slice is nil, and its length and capacity +are 0. A new, initialized slice value for a given element type T is +made using the built-in function make, which takes a slice type and parameters specifying the length and optionally the capacity: +

 make([]T, length)
 make([]T, length, capacity)
 
-The "make()" call allocates a new underlying array to which the returned -slice value refers. More precisely, calling "make" +

+The make() call allocates a new, hidden array to which the returned +slice value refers. That is, calling make +

 make([]T, length, capacity)
 
-is effectively the same as allocating an array and slicing it - -
-new([capacity]T)[0 : length]
-
-

-Indexing: Given a (pointer to) a slice variable "a", a slice element is -specified with an index operation: +produces the same slice as allocating an array and slicing it: +

-a[i]
+make([capacity]T)[0 : length]
 
-This denotes the slice element at index "i". "i" must be within bounds, -that is "0 <= i < len(a)". -

-Slicing: Given a a slice variable "a", a sub-slice is created with a slice -operation: - -

-a[i : j]
-
- -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 <= i <= j <= 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. -

Map types

-A map is a composite type consisting of a variable number of entries -called (key, value) pairs. For a given map, the keys and values must -each be of a specific complete type (§Types) called the key and value type, -respectively. The number of entries in a map is called its length; it is never -negative. +

+A map is an unordered group of elements of one type, called the +value type, indexed by a set of unique keys of another type, +called the key type. Both key and value types must be complete. +(§Types). +(TODO: is completeness necessary here?) +A map value may be nil. + +

-MapType = "map" "[" KeyType "]" ValueType .
-KeyType = CompleteType .
-ValueType = CompleteType .
+MapType     = "map" "[" KeyType "]" ValueType .
+KeyType     = CompleteType .
+ValueType   = CompleteType .
 
-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.

-Upon creation, a map is empty and values may be added and removed -during execution. +The comparison operators == and != +(§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. + +

 map [string] int
@@ -1053,42 +1058,47 @@ map [*T] struct { x, y float }
 map [string] interface {}
 
-The length of a map "m" can be discovered using the built-in function - -
-len(m)
-
- -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: - -
-my_map := make(M, 100);
-
-

-The map capacity is an allocation hint for more efficient incremental growth -of the map. +The number of elements is called the length and is never negative. +The length of a map m can be discovered using the +built-in function len(m) and may change during execution. +The value of an uninitialized map is nil

+

+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 make, which takes the map type and an optional +capacity, an allocation hint, as arguments: +

+ +
+make(map[string] int, 100);
+

Channel types

+

A channel provides a mechanism for two concurrently executing functions -to synchronize execution and exchange values of a specified type. This -type must be a complete type (§Types). +to synchronize execution and communicate by passing a value of a +specified element type. The element type must be complete (§Types). +(TODO: is completeness necessary here?) +A channel value may be nil. +

-ChannelType = Channel | SendChannel | RecvChannel .
-Channel = "chan" ValueType .
-SendChannel = "chan" "<-" ValueType .
-RecvChannel = "<-" "chan" ValueType .
+ChannelType   = Channel | SendChannel | RecvChannel .
+Channel       = "chan" ValueType .
+SendChannel   = "chan" "<-" ValueType .
+RecvChannel   = "<-" "chan" ValueType .
 
-Upon creation, a channel can be used both to send and to receive. +

+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 -to receive. This constraint is called a channel's ``direction''; either -bi-directional (unconstrained), send, or receive. +to receive. This constraint is called a channel's direction; either +send, receive, or bi-directional (unconstrained). +

 chan T         // can send and receive values of type T
@@ -1096,108 +1106,88 @@ chan <- float  // can only be used to send floats
 <-chan int     // can only receive ints
 
-The value of an uninitialized channel is "nil". A new, initialized channel -value for a given element type T is made using the built-in function "make", +

+The value of an uninitialized channel is nil. A new, initialized channel +value is made using the built-in function make, which takes the channel type and an optional capacity as arguments: +

-my_chan = make(chan int, 100);
+make(chan int, 100);
 
-The capacity sets the size of the buffer in the communication channel. If the +

+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 -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. +buffer is not full, sends can succeed without blocking. If the capacity is zero +or absent, the communication succeeds only when both a sender and receiver are ready. +

- -

Type equality

+

General properties of types and values

-Types may be ``different'', ``structurally equal'', or ``identical''. -Go is a type-safe language; generally different types cannot be mixed -in binary operations, and values cannot be assigned to variables of different -types. However, values may be assigned to variables of structurally -equal types. Finally, type guards succeed only if the dynamic type -is identical to or implements the type tested against (§Type guards). -

-Structural type equality (equality for short) is defined by these rules: +Types may be different, structurally equal (or just equal), +or identical. +Go is type safe: different types cannot be mixed +in binary operations and values cannot be assigned to variables of different +types. They can be assigned to variables of equal type. +

+ +

Type equality and identity

+

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 -literal structure and corresponding components have equal types. Loosely -speaking, two types are equal if their values have the same layout in memory. -More precisely: +are equal (§Declarations and Scope). +Two type literals specify equal types if they have the same +literal structure and corresponding components have equal types. +In detail:

+

-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''.

-Two type names denote identical types if they originate in the same -type declaration. Two type literals specify identical types if they have the -same literal structure and corresponding components have identical types. -More precisely: +By definition, identical types are also equal types. +Two types are different if they are not equal.

- - -Note that the type denoted by a type name is identical only to the type literal -in the type name's declaration.

-Finally, two types are different if they are not structurally equal. -(By definition, they cannot be identical, either). - -For instance, given the declarations +Given the declarations +

 type (
@@ -1210,17 +1200,22 @@ type (
 )
 
-these are some types that are equal +

+these types are equal +

 T0 and T0
+T0 and T1
 T0 and []string
 T2 and T3
 T4 and T5
 T3 and struct { a int; int }
 
-and these are some types that are identical +

+and these types are identical +

 T0 and T0
@@ -1228,22 +1223,13 @@ T0 and T0
 struct { a, b *T5 } and struct { a, b *T5 }
 
-As an example, "T0" and "T1" are equal but not identical because they have -different declarations. +

+T0 and T1 are equal but not +identical because they have distinct declarations. +

Assignment compatibility

- -

Values of any type may always be assigned to variables 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 nth variable is initialized to the value of the nth expression. Otherwise, each variable is initialized to the zero -of the type (§Program initialization and execution). +of the type (§The zero value). The expressions can be general expressions; they need not be constants.

@@ -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. 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 notation "..." may be used in place of the length expression to denote a 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].

Slices

-Strings, arrays, and slices can be ``sliced'' to construct substrings or descriptors +Strings, arrays, and slices can be sliced to construct substrings or descriptors 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 difference in the index values in the slice. After slicing the array "a" @@ -2129,8 +2115,11 @@ s[0] == 2 s[1] == 3
-The index values in the slice must be in bounds for the original -array (or string) and the slice length must be non-negative. +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.

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 @@ -2173,8 +2162,8 @@ v, ok := x.(T) 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)"; 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 -value for the type of "v" (§Program initialization and execution), and "ok" is +is set to true. If the type guard fails, the value in "v" is set to the zero +value for the type of "v" (§The zero value), and "ok" is set to false. No run-time exception occurs in this case.

@@ -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 memory is initialized as described in the section on initial values -(§Program initialization and execution). +(§The zero value).

 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"
 must be a slice, map, or channel type.
 The memory is initialized as described in the section on initial values
-(§Program initialization and execution).
+(§The zero value).
 
 
 make(T [, optional list of expressions])
@@ -3665,29 +3654,38 @@ func main() {
 
 

Program initialization and execution

+

The zero value

+

When memory is allocated to store a value, either through a declaration -or "new()", and no explicit initialization is provided, the memory is +or new(), and no explicit initialization is provided, the memory 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, -"0.0" for floats, '''' for strings, and "nil" for pointers and interfaces. +set to the zero value for its type: false for booleans, +0 for integers, 0.0 for floats, "" +for strings, and nil for pointers and interfaces. 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. +

These two simple declarations are equivalent: +

 var i int;
 var i int = 0;
 
+

After +

 type T struct { i int; f float; next *T };
 t := new(T);
 
+

the following holds: +

 t.i == 0
@@ -3695,43 +3693,54 @@ t.f == 0.0
 t.next == nil
 
- +

Program execution

+

A package with no imports is initialized by assigning initial values to all its global variables in declaration order and then calling any init() functions defined in its source. Since a package may contain more than one source file, there may be more than one init() function, but only one per source file. +

Initialization code may contain "go" statements, but the functions they invoke do not begin execution until initialization of the entire program is complete. Therefore, all initialization code is run in a single thread of execution. +

Furthermore, an "init()" function cannot be referred to from anywhere in a program. In particular, "init()" cannot be called explicitly, nor can a pointer to "init" be assigned to a function variable). +

If a package has imports, the imported packages are initialized before initializing the package itself. If multiple packages import a package P, P will be initialized only once. +

The importing of packages, by construction, guarantees that there can be no cyclic dependencies in initialization. +

A complete program, possibly created by linking multiple packages, must have one package called main, with a function +

 func main() { ...  }
 
-defined. The function main.main() takes no arguments and returns no +

+defined. The function main.main() takes no arguments and returns no value. +

Program execution begins by initializing the main package and then -invoking main.main(). +invoking main.main(). +

When main.main() returns, the program exits. +