From 5af7de3fe37378cb61060e554b885b1f26a8f8f6 Mon Sep 17 00:00:00 2001
From: Rob Pike
-Adjacent string literals separated only by the empty string, white
-space, or comments are concatenated into a single string literal.
-
-A type may be specified by a type name (§Type declarations) or a type literal.
-A type literal is a syntactic construct that explicitly specifies the
-composition of a new type in terms of other (already declared) types.
+A type determines a 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.
+
-All other types are called ``composite types'; they are composed from other
-(basic or composite) types and denoted by their type names or by type literals.
-There are arrays, structs, pointers, functions, interfaces, slices, maps, and
+Basic types such as
-At a given point in the source code, a type may be ``complete'' or
-''incomplete''. Array and struct types are complete when they are fully declared.
-All other types are always complete (although their components, such as the base
-type of a pointer type, may be incomplete). Incomplete types are subject to usage
-restrictions; for instance the type of a variable must be complete where the
-variable is declared.
+
+TODO: not sure the rest of this section this is needed; it's all covered or should be covered in the sections
+that follow.
+
+At any point in the source code, a type may be complete or
+incomplete. Most types are always complete, although their
+components, such as the base type of a pointer type, may be incomplete.
+Struct and interface types are incomplete when forward declared
+(§Forward declarations) and become complete once they are fully
+declared. (TODO: You had array here - why?)
+The type of a variable must be complete where the variable is declared.
+(TODO: would be better to say what you CAN do with an interface type,
+and then drop all the references to complete types in the sections
+that follow. What can you do? Use one to declare a pointer variable/field/param.
+Anything else?)
+
+The interface of a type is the set of methods bound to it
+(§Method declarations); for pointer types, it is the interface
of the pointer base type (§Pointer types). All types have an interface;
-if they have no methods associated with them, their interface is
-called the ``empty'' interface.
+if they have no methods, it is the empty'' interface.
+
-The ``static type'' (or simply ``type'') of a variable is the type defined by
-the variable's declaration. The ``dynamic type'' of a variable is the actual
-type of the value stored in a variable at run-time. Except for variables of
-interface type, the dynamic type of a variable is always its static type.
-
-Variables of interface type may hold values with different dynamic types
-during execution. However, its dynamic type is always compatible with
-the static type of the interface variable (§Interface types).
-
+The static type (or just type) of a variable is the
+type defined by its declaration. Variables of interface type
+(§Interface types) also have a distinct dynamic type, 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 compatible
+with the static type of the interface variable. For non-interfaces
+types, the dynamic type is always the static type.
+
+Basic types include traditional arithmetic types, booleans, and strings. All are predeclared.
+
+The architecture-independent numeric types are:
+
Integer types are represented in the usual binary format; the value of
an n-bit integer is n bits wide. A negative signed integer is represented
as the two's complement of its absolute value.
+
+There is also a set of architecture-independent basic numeric types
+whose size depends on the architecture:
+
-Except for "byte", which is an alias for "uint8", all numeric types
-are different from each other to avoid portability issues. Conversions
-are required when different numeric types are mixed in an expression or assignment.
-For instance, "int32" and "int" are not the same type even though they may have
-the same size on a particular platform.
+Except for
-The "string" type represents the set of string values (strings).
-Strings behave like arrays of bytes, with the following properties:
+The
+The elements of strings have type
+String literals separated only by the empty string, white
+space, or comments are concatenated into a single string literal.
+
+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.
+
-The number of elements of an array "a" can be discovered using the built-in
-function
-
-
-StringLit = string_lit { string_lit } .
-
"Alea iacta est."
@@ -540,12 +533,12 @@ literal.
Types
-A type specifies the set of values that variables of that type may assume
-and the operators that are applicable.
Type = TypeName | TypeLit | "(" Type ")" .
@@ -555,52 +548,59 @@ TypeLit =
SliceType | MapType | ChannelType .
-Some types are predeclared and denoted by their type names; these are called
-``basic types''. Generally (except for strings) they are not composed of more
-elementary types; instead they model elementary machine data types.
int
are predeclared (§Predeclared identifiers).
+Other types may be constructed from these, recursively,
+including arrays, structs, pointers, functions, interfaces, slices, maps, and
channels.
-Basic types
-Go defines a number of basic types, referred to by their predeclared
-type names. These include traditional arithmetic types, booleans,
-and strings.
-
+Arithmetic types
-The following list enumerates all platform-independent numeric types:
+
-byte same as uint8 (for convenience)
-
uint8 the set of all unsigned 8-bit integers (0 to 255)
uint16 the set of all unsigned 16-bit integers (0 to 65535)
uint32 the set of all unsigned 32-bit integers (0 to 4294967295)
@@ -613,22 +613,20 @@ int64 the set of all signed 64-bit integers (-9223372036854775808 to 92233720
float32 the set of all valid IEEE-754 32-bit floating point numbers
float64 the set of all valid IEEE-754 64-bit floating point numbers
+
+byte familiar alias for uint8
+
uint at least 32 bits, at most the size of the largest uint type
@@ -638,59 +636,54 @@ uintptr smallest uint type large enough to store the uninterpreted
bits of a pointer value
-For instance, int might have the same size as int32 on a 32-bit
-architecture, or int64 on a 64-bit architecture.
byte
, which is an alias for uint8
,
+to avoid portability issues all numeric types are distinct. Conversions
+are required when different numeric types are mixed in an expression
+or assignment. For instance, int32
and int
+are not the same type even though they may have the same size on a
+particular architecture.
Booleans
-The type "bool" comprises the truth values true and false, which are
-available through the two predeclared constants, "true" and "false".
+The type bool
comprises the Boolean truth values
+represented by the predeclared constants true
+and false
.
Strings
string
type represents the set of textual string values.
+Strings behave like arrays of bytes but are immutable: once created,
+it is impossible to change the contents of a string.
+
+byte
and may be
+accessed using the usual indexing operations (§Indexes). It is
+illegal to take the address of such an element, that is, even if
+s[i]
is the i
th byte of a
+string, &s[i]
is invalid. The length of a string
+can be computed by the function len(s1)
.
-
-
-a [3]byte; a[0] = 'a'; a[1] = 'b'; a[2] = 'c'; string(a) == "abc";
+
+StringLit = string_lit { string_lit } .
-Array types
-An array is a composite type consisting of a number of elements all of the
-same type, called the element type. The element type must be a complete type
-(§Types). The number of elements of an array is called its length; it is never
-negative. The elements of an array are designated by indices
-which are integers from 0 through the length - 1.
+
ArrayType = "[" ArrayLength "]" ElementType .
@@ -698,19 +691,14 @@ ArrayLength = Expression .
ElementType = CompleteType .
-The array length and its value are part of the array type. The array length
-must be a constant expression (§Constant expressions) that evaluates to an
-integer value >= 0.
-len(a)
-
-
-The length of arrays is known at compile-time, and the result of a call to
-"len(a)" is a compile-time constant.
+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 @@ -718,19 +706,15 @@ The length of arrays is known at compile-time, and the result of a call to [1000]*float64-Assignment compatibility: Arrays can be assigned to variables of equal type -and to slice variables with equal element type. When assigning to a slice -variable, the array is not copied but a slice comprising the entire array -is created. -
+A struct is a sequence of named +elements, called fields, with various types. A struct type declares +an identifier and type for each field. Within a struct field identifiers +must be unique and field types must be complete (§Types). +
StructType = "struct" [ "{" [ FieldDeclList ] "}" ] . @@ -752,10 +736,13 @@ struct { }-A struct may contain ``anonymous fields'', which are declared with a type -but no explicit field identifier. An anonymous field type must be specified as -a type name "T", or as a pointer to a type name ``*T'', and T itself may not be +
+A field declared with a type but no field identifier is an anonymous field.
+Such a field type must be specified as
+a type name T
or as a pointer to a type name *T
+and T
itself may not be
a pointer or interface type. The unqualified type name acts as the field identifier.
+
// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4 @@ -768,9 +755,11 @@ struct { }+
The unqualified type name of an anonymous field must not conflict with the field identifier (or unqualified type name for an anonymous field) of any other field within the struct. The following declaration is illegal: +
struct { @@ -780,34 +769,35 @@ struct { }-Fields and methods (§Method declarations) of an anonymous field become directly -accessible as fields and methods of the struct without the need to provide the -type name of the respective anonymous field (§Selectors).
-A field declaration may be followed by an optional string literal tag which -becomes an ``attribute'' for all the identifiers in the corresponding -field declaration. The tags are available via the reflection library but -are ignored otherwise. A tag may contain arbitrary application-specific -information. +Fields and methods (§Method declarations) of an anonymous field are +promoted to be ordinary fields and methods of the struct (§Selectors). +
++A field declaration may be followed by an optional string literal tag, which +becomes an attribute for all the identifiers in the corresponding +field declaration. The tags are made +visible through a reflection library (TODO: reference?) +but are otherwise ignored. +
// A struct corresponding to the EventIdMessage protocol buffer. -// The tag strings contain the protocol buffer field tags. +// The tag strings contain the protocol buffer field numbers. struct { - time_usec uint64 "1"; - server_ip uint32 "2"; - process_id uint32 "3"; + time_usec uint64 "field 1"; + server_ip uint32 "field 2"; + process_id uint32 "field 3"; }-Assignment compatibility: Structs are assignment compatible to variables of -equal type only. -
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, and the value nil
.
+
PointerType = "*" BaseType . @@ -819,37 +809,15 @@ BaseType = Type . map[string] chan-The pointer base type may be denoted by an identifier referring to an -incomplete type (§Types), possibly declared via a forward declaration. -This allows the construction of recursive and mutually recursive types -such as: - -
-type S struct { s *S } - -type S2 struct // forward declaration of S2 -type S1 struct { s2 *S2 } -type S2 struct { s1 *S1 } -- -Assignment compatibility: A pointer is assignment compatible to a variable -of pointer type, only if both types are equal.
-Comparisons: A variable of pointer type can be compared against "nil" with the -operators "==" and "!=" (§Comparison operators). The variable is -"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or -if the variable has not been modified since creation (§Program initialization -and execution). -
-Two variables of equal pointer type can be tested for equality with the -operators "==" and "!=" (§Comparison operators). The pointers are equal -if they point to the same location. - -Pointer arithmetic of any kind is not permitted. - +To permit construction of recursive and mutually recursive types, +the pointer base type may be denoted by the type name of a +forward-declared, incomplete type (§Forward declarations). +
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". @@ -891,19 +859,6 @@ must be parenthesized to resolve a parsing ambiguity: func (n int) (func (p* T)) -Assignment compatibility: A function can be assigned to a function -variable only if both function types are equal. --Comparisons: A variable of function type can be compared against "nil" with the -operators "==" and "!=" (§Comparison operators). The variable is -"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or -if the variable has not been modified since creation (§Program initialization -and execution). -
-Two variables of equal function type can be tested for equality with the -operators "==" and "!=" (§Comparison operators). The variables are equal -if they refer to the same function. -
-Comparisons: A variable of interface type can be compared against "nil" with the -operators "==" and "!=" (§Comparison operators). The variable is -"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or -if the variable has not been modified since creation (§Program initialization -and execution). -
-Two variables of interface type can be tested for equality with the -operators "==" and "!=" (§Comparison operators) if both variables have the -same static type. They are equal if both their dynamic types and values are -equal. If the dynamic types are equal but the values do not support comparison, -a run-time error occurs. - -
Indexing: Given a (pointer to) a slice variable "a", a slice element is specified with an index operation: @@ -1095,12 +1032,6 @@ 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. -
-Comparisons: A variable of slice type can be compared against "nil" with the -operators "==" and "!=" (§Comparison operators). The variable is -"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or -if the variable has not been modified since creation (§Program initialization -and execution).
The map capacity is an allocation hint for more efficient incremental growth of the map. -
-Assignment compatibility: A map type is assignment compatible to a variable of -map type only if both types are equal. -
-Comparisons: A variable of map type can be compared against "nil" with the -operators "==" and "!=" (§Comparison operators). The variable is -"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or -if the variable has not been modified since creation (§Program initialization -and execution). - +
-Assignment compatibility: A value of type channel can be assigned to a variable -of type channel only if a) both types are equal (§Type equality), or b) both -have equal channel value types and the value is a bidirectional channel. -
-Comparisons: A variable of channel type can be compared against "nil" with the -operators "==" and "!=" (§Comparison operators). The variable is -"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or -if the variable has not been modified since creation (§Program initialization -and execution). -
-Two variables of channel type can be tested for equality with the -operators "==" and "!=" (§Comparison operators) if both variables have -the same ValueType. They are equal if both values were created by the same -"make" call (§Making slices, maps, and channels).
+Values of any type may always be assigned to variables +of equal static type. Some types and values have conditions under which they may +be assigned to different types: +
+nil
can be assigned to any
+pointer, function, slice, map, channel, or interface variable.
++Values of any type may be compared to other values of equal static +type. Values of numeric and string type may be compared using the +full range of comparison operators as described in §Comparison operators; +booleans may be compared only for equality or inequality. +
+ +
+Values of composite type may be
+compared for equality or inequality using the ==
and
+!=
operators, with the following provisos:
+
nil
+and is equal to nil
if it has been assigned the explicit
+value nil
or if it is a variable (or array element,
+field, etc.) that has not been modified since it was created
+uninitialized.
+nil
if it has
+been assigned the explicit value nil
or if it is a
+variable (or array element, field, etc.) that has not been modified
+since it was created uninitialized.
+nil
,
+two values of the same type are equal if they both equal nil
,
+unequal if one equals nil
and one does not.
+make
+(§Making slices, maps, and channels).
+-Mutually-recursive types struct or interface types require that one be +Mutually-recursive types require that one be forward declared so that it may be named in the other. A forward declaration of a type omits the block containing the fields or methods of the type. @@ -2484,11 +2481,12 @@ not occur. For instance, it may not assume that "x < x + 1" is always true.
Comparison operators yield a boolean result. All comparison operators apply
-to strings and numeric types. The operators "==" and "!=" also apply to
-boolean values, pointer, interface, and channel types. Slice and
-map types only support testing for equality against the predeclared value
-"nil".
+to basic types except bools.
+The operators ==
and !=
apply, at least in some cases,
+to all types except arrays and structs.
+
== equal @@ -2499,15 +2497,19 @@ map types only support testing for equality against the predeclared value >= greater or equal+
+Numeric basic types are compared in the usual way. +
+Strings are compared byte-wise (lexically). +
Booleans are equal if they are either both "true" or both "false". +
-Pointers are equal if they point to the same value. -
-Interface, slice, map, and channel types can be compared for equality according -to the rules specified in the section on §Interface types, §Slice types, §Map types, -and §Channel types, respectively. +The rules for comparison of composite types are described in the +section on §Comparison compatibility. +
uint8s
yields a string whose successive
+bytes are those of the array.
+(Recall byte
is a synonym for uint8
.)
string([]byte('h', 'e', 'l', 'l', 'o')) // "hello"