From: Rob Pike
-A declaration binds an identifier to a language entity such as -a variable or function and specifies properties such as its type. -Every identifier in a program must be declared. -
+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.
-Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl .
+Type = TypeName | TypeLit | "(" Type ")" .
+TypeName = QualifiedIdent.
+TypeLit =
+ ArrayType | StructType | PointerType | FunctionType | InterfaceType |
+ 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.
-The scope of an identifier is the extent of source text within which the -identifier denotes the bound entity. No identifier may be declared twice in a -single scope, but inner blocks can declare a new entity with the same -identifier, in which case the scope created by the outer declaration excludes -that created by the inner. -
+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 +channels.-There are levels of scoping in effect before each source file is compiled. -In order from outermost to innermost: -
--The scope of an identifier depends on the entity declared: -
- -+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). + -
if , for,
- or switch statement, the
- innermost surrounding block is the block associated
- with that statement.-The following identifiers are implicitly declared in the outermost scope: -
-Basic types: - bool byte float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 - -Platform-specific convenience types: - float int uint uintptr +byte same as uint8 (for convenience) -Constants: - true false iota nil +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) +uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615) -Functions: - cap convert len make new panic panicln print println typeof (TODO: typeof??) +int8 the set of all signed 8-bit integers (-128 to 127) +int16 the set of all signed 16-bit integers (-32768 to 32767) +int32 the set of all signed 32-bit integers (-2147483648 to 2147483647) +int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807) -Packages: - sys unsafe (TODO: does sys endure?) +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+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. -
-By default, identifiers are visible only within the package in which they are declared. -Some identifiers are exported and can be referenced using -qualified identifiers in other packages (§Qualified identifiers). -If an identifier satisfies these two conditions: -
--it will be exported automatically. -
+Additionally, Go declares a set of platform-specific numeric types for +convenience: -+uint at least 32 bits, at most the size of the largest uint type +int at least 32 bits, at most the size of the largest int type +float at least 32 bits, at most the size of the largest float type +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.
-A constant declaration binds a list of identifiers (the names of -the constants) to the values of a list of constant expressions -(§Constant expressions). The number of identifiers must be equal -to the number of expressions, and the nth identifier on -the left is bound to value of the nth expression on the -right. -
+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. -
-ConstDecl = "const" ( ConstSpec | "(" [ ConstSpecList ] ")" ) .
-ConstSpecList = ConstSpec { ";" ConstSpec } [ ";" ] .
-ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
-IdentifierList = identifier { "," identifier } .
-ExpressionList = Expression { "," Expression } .
+Booleans
-CompleteType = Type .
-
+The type "bool" comprises the truth values true and false, which are
+available through the two predeclared constants, "true" and "false".
--If the type (CompleteType) is omitted, the constants take the -individual types of the corresponding expressions, which may be -``ideal integer'' or ``ideal float'' (§Ideal number). If the type -is present, all constants take the type specified, and the types -of all the expressions must be assignment-compatible -with that type. -
--const Pi float64 = 3.14159265358979323846 -const E = 2.718281828 -const ( - size int64 = 1024; - eof = -1; -) -const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo" -const u, v float = 0, 3 // u = 0.0, v = 3.0 -+
-Within a parenthesized const declaration list the
-expression list may be omitted from any but the first declaration.
-Such an empty list is equivalent to the textual substitution of the
-first preceding non-empty expression list. Omitting the list of
-expressions is therefore equivalent to repeating the previous list.
-The number of identifiers must be equal to the number of expressions
-in the previous list. Together with the iota constant generator
-(§Iota) this mechanism permits light-weight declaration of sequential values:
+The "string" type represents the set of string values (strings).
+Strings behave like arrays of bytes, with the following properties:
-const ( - Sunday = iota; - Monday; - Tuesday; - Wednesday; - Thursday; - Friday; - Partyday; - numberOfDays; // this constant is not exported -) +a [3]byte; a[0] = 'a'; a[1] = 'b'; a[2] = 'c'; string(a) == "abc";+
-Within a constant declaration, the predeclared pseudo-constant
-iota represents successive integers. It is reset to 0
-whenever the reserved word const appears in the source
-and increments with each semicolon. It can be used to construct a
-set of related constants:
-
-const ( // iota is reset to 0 - c0 = iota; // c0 == 0 - c1 = iota; // c1 == 1 - c2 = iota // c2 == 2 -) - -const ( - a = 1 << iota; // a == 1 (iota has been reset) - b = 1 << iota; // b == 2 - c = 1 << iota; // c == 4 -) ++ArrayType = "[" ArrayLength "]" ElementType . +ArrayLength = Expression . +ElementType = CompleteType . +-const ( - u = iota * 42; // u == 0 (ideal integer) - v float = iota * 42; // v == 42.0 (float) - w = iota * 42; // w == 84 (ideal integer) -) +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. ++The number of elements of an array "a" can be discovered using the built-in +function -const x = iota; // x == 0 (iota has been reset) -const y = iota; // y == 0 (iota has been reset) +
+len(a)--Within an ExpressionList, the value of each
+The length of arrays is known at compile-time, and the result of a call to +"len(a)" is a compile-time constant.iotais the same because -it is only incremented at a semicolon: --const ( - bit0, mask0 = 1 << iota, 1 << iota - 1; // bit0 == 1, mask0 == 0 - bit1, mask1; // bit1 == 2, mask1 == 1 - bit2, mask2; // bit2 == 4, mask2 == 3 -) +[32]byte +[2*N] struct { x, y int32 } +[1000]*float64--This last example exploits the implicit repetition of the -last non-empty expression list. -
+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. -Type declarations
+Struct types
--A type declaration binds an identifier, the type name, -to a new type. TODO: what exactly is a "new type"? -
+A struct is a composite type consisting of a fixed number of elements, +called fields, with possibly different types. A struct type declares +an identifier and type for each field. Within a struct type no field +identifier may be declared twice and all field types must be complete +types (§Types).-TypeDecl = "type" ( TypeSpec | "(" [ TypeSpecList ] ")" ) . -TypeSpecList = TypeSpec { ";" TypeSpec } [ ";" ] . -TypeSpec = identifier Type . +StructType = "struct" [ "{" [ FieldDeclList ] "}" ] . +FieldDeclList = FieldDecl { ";" FieldDecl } [ ";" ] . +FieldDecl = (IdentifierList CompleteType | [ "*" ] TypeName) [ Tag ] . +Tag = StringLit .-type IntArray [16] int - -type ( - Point struct { x, y float }; - Polar Point -) - -type TreeNode struct { - left, right *TreeNode; - value Point; -} +// An empty struct. +struct {} -type Comparable interface { - cmp(Comparable) int +// A struct with 5 fields. +struct { + x, y int; + u float; + A *[]int; + F func(); }-Variable declarations
+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 pointer or interface type. The unqualified type name acts as the field identifier. --A variable declaration creates a variable, binds an identifier to it and -gives it a type and optionally an initial value. -The variable type must be a complete type (§Types). -
--VarDecl = "var" ( VarSpec | "(" [ VarSpecList ] ")" ) . -VarSpecList = VarSpec { ";" VarSpec } [ ";" ] . -VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) . ++// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4 +struct { + T1; // the field name is T1 + *T2; // the field name is T2 + P.T3; // the field name is the unqualified type name T3 + *P.T4; // the field name is the unqualified type name T4 + x, y int; +}+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: +-var i int -var U, V, W float -var k = 0 -var x, y float = -1.0, -2.0 -var ( - i int; - u, v, s = 2.0, 3.0, "bar" -) +struct { + T; // conflicts with anonymous field *T and *P.T + *T; // conflicts with anonymous field T and *P.T + *P.T; // conflicts with anonymous field T and *T +}+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).-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). -The expressions can be general expressions; they need not be constants. -
--Either the type or the expression list must be present. If the -type is present, it sets the type of each variable and the expressions -(if any) must be assignment-compatible to that type. If the type -is absent, the variables take the types of the corresponding -expressions. -
--If the type is absent and the corresponding expression is a constant -expression of ideal integer or ideal float type, the type of the -declared variable is
+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.intorfloat-respectively: --var i = 0 // i has type int -var f = 3.1415 // f has type float +// A struct corresponding to the EventIdMessage protocol buffer. +// The tag strings contain the protocol buffer field tags. +struct { + time_usec uint64 "1"; + server_ip uint32 "2"; + process_id uint32 "3"; +}-Short variable declarations
+Assignment compatibility: Structs are assignment compatible to variables of +equal type only. -A short variable declaration uses the syntax --SimpleVarDecl = IdentifierList ":=" ExpressionList . -+Pointer types
-and is shorthand for the declaration syntax +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".-"var" IdentifierList = ExpressionList . +PointerType = "*" BaseType . +BaseType = Type .-i, j := 0, 10; -f := func() int { return 7; } -ch := new(chan int); +*int +map[string] chan--Unlike regular variable declarations, short variable declarations -can be used, by analogy with tuple assignment (§Assignments), to -receive the individual elements of a multi-valued expression such -as a call to a multi-valued function. In this form, the ExpressionLIst -must be a single such multi-valued expression, the number of -identifiers must equal the number of values, and the declared -variables will be assigned the corresponding values. -
+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:-count, error := os.Close(fd); // os.Close() returns two values +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.-Short variable declarations may appear only inside functions. -In some contexts such as the initializers for
- -if, -for, orswitchstatements, -they can be used to declare local temporary variables (§Statements). -Function declarations
- +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).-A function declaration binds an identifier to a function (§Function types). -
+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. --FunctionDecl = "func" identifier Signature [ Block ] . -+Pointer arithmetic of any kind is not permitted. --func min(x int, y int) int { - if x < y { - return x; - } - return y; -} ---A function must be declared or forward-declared before it can be invoked (§Forward declarations). -Implementation restriction: Functions can only be declared at the package level. -
+Function types
-Method declarations
+A function type denotes the set of all functions with the same parameter +and result types, and the value "nil". --A method declaration binds an identifier to a method, -which is a function with a receiver. -
-MethodDecl = "func" Receiver identifier Signature [ Block ] . -Receiver = "(" [ identifier ] [ "*" ] TypeName ")" . +FunctionType = "func" Signature . +Signature = "(" [ ParameterList ] ")" [ Result ] . +ParameterList = ParameterDecl { "," ParameterDecl } . +ParameterDecl = [ IdentifierList ] ( Type | "..." ) . +Result = Type | "(" ParameterList ")" .+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.-The receiver type must be a type name or a pointer to a type name, -and that name is called the receiver base type or just base type. -The base type must not be a pointer type and must be -declared in the same source file as the method. -The method is said to be bound to the base type -and is visible only within selectors for that type -(§Type declarations, §Selectors). -
- --All methods bound to a base type must have the same receiver type, -either all pointers to the base type or all the base type itself. -Given 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).Point, the declarations --func (p *Point) Length() float { - return Math.sqrt(p.x * p.x + p.y * p.y); -} +func () +func (x int) +func () int +func (string, float, ...) +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) +-func (p *Point) Scale(factor float) { - p.x = p.x * factor; - p.y = p.y * factor; -} +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))+Assignment compatibility: A function can be assigned to a function +variable only if both function types are equal.-bind the methods
- +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).LengthandScale-to the base typePoint. --If the -receiver's value is not referenced inside the the body of the method, -its identifier may be omitted in the declaration. The same applies in -general to parameters of functions and methods. -
+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. --Methods can be declared -only after their base type is declared or forward-declared, and invoked -only after their own declaration or forward-declaration (§Forward declarations). -Implementation restriction: They can only be declared at package level. -
-Forward declarations
+Interface types
--Mutually-recursive types struct or interface 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. -
+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". + ++InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] . +MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] . +MethodSpec = IdentifierList Signature | TypeName . +-type List struct // forward declaration of List -type Item struct { - value int; - next *List; -} -type List struct { - head, tail *Item +// An interface specifying a basic File type. +interface { + Read, Write (b Buffer) bool; + Close (); }--A forward-declared type is incomplete (§Types) -until it is fully declared. The full declaration must follow -before the end of the block containing the forward declaration. -
--Functions and methods may similarly be forward-declared by omitting their body. -
+ +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 +-func F(a int) int // forward declaration of F -func G(a, b int) int { - return F(a) + F(b) -} -func F(a int) int { - if a <= 0 { return 0 } - return G(a-1, b+1) -} +func (p T) Read(b Buffer) bool { return ... } +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. -Types
+All types implement the empty interface: -A type specifies the set of values that variables of that type may assume -and the operators that are applicable. --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. +
+interface {} +--Type = TypeName | TypeLit | "(" Type ")" . -TypeName = QualifiedIdent. -TypeLit = - ArrayType | StructType | PointerType | FunctionType | InterfaceType | - SliceType | MapType | ChannelType . +In general, a type implements an arbitrary number of interfaces. +For instance, consider the interface + ++type Lock interface { + Lock, Unlock (); +}-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. --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 -channels. -
-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. +If S1 and S2 also implement -The ``interface'' of a type is the set of methods bound to it -(§Method declarations). The interface of a pointer type 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. -
-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. +
+func (p T) Lock() { ... } +func (p T) Unlock() { ... } ++ +they implement the Lock interface as well as the File interface.-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). - +An interface may contain a type name T in place of a method specification. +T must denote another, complete (and not forward-declared) interface type. +Using this notation is equivalent to enumerating the methods of T explicitly +in the interface containing T. -
Basic types
++type ReadWrite interface { + Read, Write (b Buffer) bool; +} -Go defines a number of basic types, referred to by their predeclared -type names. These include traditional arithmetic types, booleans, -and strings. +type File interface { + ReadWrite; // same as enumerating the methods in ReadWrite + Lock; // same as enumerating the methods in Lock + Close(); +} ++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: -Arithmetic types
++type T2 interface +type T1 interface { + foo(T2) int; +} +type T2 interface { + bar(T1) int; +} +-The following list enumerates all platform-independent numeric types: +Assignment compatibility: A value can be assigned to an interface variable +if the static type of the value implements the interface or if the value is "nil". ++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. -
-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) -uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615) +Slice types
-int8 the set of all signed 8-bit integers (-128 to 127) -int16 the set of all signed 16-bit integers (-32768 to 32767) -int32 the set of all signed 32-bit integers (-2147483648 to 2147483647) -int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807) +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. -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 ++SliceType = "[" "]" ElementType .-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. +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 - +
+cap(a) +-Additionally, Go declares a set of platform-specific numeric types for -convenience: +and the following relationship between "len()" and "cap()" holds: --uint at least 32 bits, at most the size of the largest uint type -int at least 32 bits, at most the size of the largest int type -float at least 32 bits, at most the size of the largest float type -uintptr smallest uint type large enough to store the uninterpreted - bits of a pointer value ++0 <= len(a) <= cap(a)-For instance, int might have the same size as int32 on a 32-bit -architecture, or int64 on a 64-bit 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. +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" ++make([]T, length, capacity) +-Booleans
+is effectively the same as allocating an array and slicing it -The type "bool" comprises the truth values true and false, which are -available through the two predeclared constants, "true" and "false". ++new([capacity]T)[0 : length] ++Assignment compatibility: Slices are assignment compatible to variables +of the same type. ++Indexing: Given a (pointer to) a slice variable "a", a slice element is +specified with an index operation: -
Strings
++a[i] ++This denotes the slice element at index "i". "i" must be within bounds, +that is "0 <= i < len(a)".-The "string" type represents the set of string values (strings). -Strings behave like arrays of bytes, with the following properties: -
-
-a [3]byte; a[0] = 'a'; a[1] = 'b'; a[2] = 'c'; string(a) == "abc"; +a[i : j]-
+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). -
-ArrayType = "[" ArrayLength "]" ElementType . -ArrayLength = Expression . -ElementType = CompleteType . +MapType = "map" "[" KeyType "]" ValueType . +KeyType = CompleteType . +ValueType = 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. +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.
-The number of elements of an array "a" can be discovered using the built-in -function +Upon creation, a map is empty and values may be added and removed +during execution.
-len(a)
+map [string] int
+map [*T] struct { x, y float }
+map [string] interface {}
-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 of a map "m" can be discovered using the built-in function
-[32]byte
-[2*N] struct { x, y int32 }
-[1000]*float64
+len(m)
-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.
+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); +-
+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). -A struct is a composite type consisting of a fixed number of elements, -called fields, with possibly different types. A struct type declares -an identifier and type for each field. Within a struct type no field -identifier may be declared twice and all field types must be complete -types (§Types). -
-StructType = "struct" [ "{" [ FieldDeclList ] "}" ] .
-FieldDeclList = FieldDecl { ";" FieldDecl } [ ";" ] .
-FieldDecl = (IdentifierList CompleteType | [ "*" ] TypeName) [ Tag ] .
-Tag = StringLit .
-
+
-// An empty struct.
-struct {}
+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). (TODO could it be incomplete?)
-// A struct with 5 fields.
-struct {
- x, y int;
- u float;
- A *[]int;
- F func();
-}
+
+ChannelType = Channel | SendChannel | RecvChannel .
+Channel = "chan" ValueType .
+SendChannel = "chan" "<-" ValueType .
+RecvChannel = "<-" "chan" ValueType .
-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 pointer or interface type. The unqualified type name acts as the field identifier.
+Upon creation, a channel can be used both to send and to receive.
+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.
-// A struct with four anonymous fields of type T1, *T2, P.T3 and *P.T4
-struct {
- T1; // the field name is T1
- *T2; // the field name is T2
- P.T3; // the field name is the unqualified type name T3
- *P.T4; // the field name is the unqualified type name T4
- x, y int;
-}
+chan T // can send and receive values of type T
+chan <- float // can only be used to send floats
+<-chan int // can only receive ints
-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:
+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",
+which takes the channel type and an optional capacity as arguments:
-struct {
- T; // conflicts with anonymous field *T and *P.T
- *T; // conflicts with anonymous field T and *P.T
- *P.T; // conflicts with anonymous field T and *T
-}
+my_chan = make(chan int, 100);
-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).
+The capacity sets the size of the buffer in the communication 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.
-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.
+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).
-
-// A struct corresponding to the EventIdMessage protocol buffer.
-// The tag strings contain the protocol buffer field tags.
-struct {
- time_usec uint64 "1";
- server_ip uint32 "2";
- process_id uint32 "3";
-}
-
-Assignment compatibility: Structs are assignment compatible to variables of
-equal type only.
+Type equality
+
+
+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:
+
+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:
+
+-PointerType = "*" BaseType . -BaseType = Type . -+
-*int -map[string] chan -+
-type S struct { s *S }
+ +Type identity is defined by these rules: +
++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: +
+-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. +
+Finally, two types are different if they are not structurally equal. +(By definition, they cannot be identical, either). -
-FunctionType = "func" Signature .
-Signature = "(" [ ParameterList ] ")" [ Result ] .
-ParameterList = ParameterDecl { "," ParameterDecl } .
-ParameterDecl = [ IdentifierList ] ( Type | "..." ) .
-Result = Type | "(" ParameterList ")" .
+For instance, given the declarations
+
+
+type (
+ T0 []string;
+ T1 []string
+ T2 struct { a, b int };
+ T3 struct { a, c int };
+ T4 func (int, float) *T0
+ T5 func (x int, y float) *[]string
+)
-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).
+these are some types that are equal
-func ()
-func (x int)
-func () int
-func (string, float, ...)
-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)
+T0 and T0
+T0 and []string
+T2 and T3
+T4 and T5
+T3 and struct { a int; int }
-If the result type of a function is itself a function type, the result type
-must be parenthesized to resolve a parsing ambiguity:
+and these are some types that are identical
-func (n int) (func (p* T))
+T0 and T0
+[]int and []int
+struct { a, b *T5 } and struct { a, b *T5 }
-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.
+As an example, "T0" and "T1" are equal but not identical because they have
+different declarations.
+
-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".
+Declarations and Scope
+
+
+A declaration binds an identifier to a language entity such as
+a variable or function and specifies properties such as its type.
+Every identifier in a program must be declared.
+
-InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] .
-MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] .
-MethodSpec = IdentifierList Signature | TypeName .
+Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl .
+
+
+The scope of an identifier is the extent of source text within which the
+identifier denotes the bound entity. No identifier may be declared twice in a
+single scope, but inner blocks can declare a new entity with the same
+identifier, in which case the scope created by the outer declaration excludes
+that created by the inner.
+
+
+There are levels of scoping in effect before each source file is compiled.
+In order from outermost to innermost:
+
+
+ - The universe scope contains all predeclared identifiers.
+ - An implicit scope contains only the package name.
+ - The package-level scope surrounds all declarations at the
+ top level of the file, that is, outside the body of any
+ function or method. That scope is shared across all
+ source files within the package (§Packages), allowing
+ package-level identifiers to be shared between source
+ files.
+
-
-// An interface specifying a basic File type.
-interface {
- Read, Write (b Buffer) bool;
- Close ();
-}
-
+
+The scope of an identifier depends on the entity declared:
+
-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
+
+ - The scope of predeclared identifiers is the universe scope.
-
-func (p T) Read(b Buffer) bool { return ... }
-func (p T) Write(b Buffer) bool { return ... }
-func (p T) Close() { ... }
-
+ - The scope of an (identifier denoting a) type, function or package
+ extends from the point of the identifier in the declaration
+ to the end of the innermost surrounding block.
-(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.
+ - The scope of a constant or variable extends textually from
+ the end of the declaration to the end of the innermost
+ surrounding block. If the variable is declared in the
+ init statement of an
if , for,
+ or switch statement, the
+ innermost surrounding block is the block associated
+ with that statement.
-All types implement the empty interface:
+ - The scope of a parameter or result is the body of the
+ corresponding function.
-
-interface {}
-
+ - The scope of a field or method is selectors for the
+ corresponding type containing the field or method (§Selectors).
-In general, a type implements an arbitrary number of interfaces.
-For instance, consider the interface
+ - The scope of a label is a unique scope emcompassing
+ the body of the innermost surrounding function, excluding
+ nested functions. Labels do not conflict with variables.
+
-
-type Lock interface {
- Lock, Unlock ();
-}
-
+Predeclared identifiers
-If S1 and S2 also implement
+
+The following identifiers are implicitly declared in the outermost scope:
+
+
+Basic types:
+ bool byte float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64
-
-func (p T) Lock() { ... }
-func (p T) Unlock() { ... }
-
+Platform-specific convenience types:
+ float int uint uintptr
-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 (and not forward-declared) interface type.
-Using this notation is equivalent to enumerating the methods of T explicitly
-in the interface containing T.
+Constants:
+ true false iota nil
-
-type ReadWrite interface {
- Read, Write (b Buffer) bool;
-}
+Functions:
+ cap convert len make new panic panicln print println typeof (TODO: typeof??)
-type File interface {
- ReadWrite; // same as enumerating the methods in ReadWrite
- Lock; // same as enumerating the methods in Lock
- Close();
-}
+Packages:
+ sys unsafe (TODO: does sys endure?)
-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;
-}
-
+Exported identifiers
-Assignment compatibility: A value can be assigned to an interface variable
-if the static type of the value implements the interface or if the value is "nil".
-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).
+By default, identifiers are visible only within the package in which they are declared.
+Some identifiers are exported and can be referenced using
+qualified identifiers in other packages (§Qualified identifiers).
+If an identifier satisfies these two conditions:
+
+
+- the first character of the identifier's name is a Unicode upper case letter;
+
- the identifier is declared at the package level or is a field or method of a type
+declared at the top level;
+
-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.
-
+it will be exported automatically.
+
-Slice types
+Const declarations
-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 constant declaration binds a list of identifiers (the names of
+the constants) to the values of a list of constant expressions
+(§Constant expressions). The number of identifiers must be equal
+to the number of expressions, and the nth identifier on
+the left is bound to value of the nth expression on the
+right.
+
-SliceType = "[" "]" ElementType .
-
+ConstDecl = "const" ( ConstSpec | "(" [ ConstSpecList ] ")" ) .
+ConstSpecList = ConstSpec { ";" ConstSpec } [ ";" ] .
+ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
-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
+IdentifierList = identifier { "," identifier } .
+ExpressionList = Expression { "," Expression } .
-
-cap(a)
+CompleteType = Type .
-and the following relationship between "len()" and "cap()" holds:
+
+If the type (CompleteType) is omitted, the constants take the
+individual types of the corresponding expressions, which may be
+``ideal integer'' or ``ideal float'' (§Ideal number). If the type
+is present, all constants take the type specified, and the types
+of all the expressions must be assignment-compatible
+with that type.
+
-0 <= len(a) <= cap(a)
+const Pi float64 = 3.14159265358979323846
+const E = 2.718281828
+const (
+ size int64 = 1024;
+ eof = -1;
+)
+const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo"
+const u, v float = 0, 3 // u = 0.0, v = 3.0
-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"
+
+Within a parenthesized const declaration list the
+expression list may be omitted from any but the first declaration.
+Such an empty list is equivalent to the textual substitution of the
+first preceding non-empty expression list. Omitting the list of
+expressions is therefore equivalent to repeating the previous list.
+The number of identifiers must be equal to the number of expressions
+in the previous list. Together with the iota constant generator
+(§Iota) this mechanism permits light-weight declaration of sequential values:
+
-make([]T, length, capacity)
+const (
+ Sunday = iota;
+ Monday;
+ Tuesday;
+ Wednesday;
+ Thursday;
+ Friday;
+ Partyday;
+ numberOfDays; // this constant is not exported
+)
-is effectively the same as allocating an array and slicing it
-
-new([capacity]T)[0 : length]
-
+Iota
-Assignment compatibility: Slices are assignment compatible to variables
-of the same type.
-Indexing: Given a (pointer to) a slice variable "a", a slice element is
-specified with an index operation:
+Within a constant declaration, the predeclared pseudo-constant
+iota represents successive integers. It is reset to 0
+whenever the reserved word const appears in the source
+and increments with each semicolon. It can be used to construct a
+set of related constants:
+
-a[i]
+const ( // iota is reset to 0
+ c0 = iota; // c0 == 0
+ c1 = iota; // c1 == 1
+ c2 = iota // c2 == 2
+)
+
+const (
+ a = 1 << iota; // a == 1 (iota has been reset)
+ b = 1 << iota; // b == 2
+ c = 1 << iota; // c == 4
+)
+
+const (
+ u = iota * 42; // u == 0 (ideal integer)
+ v float = iota * 42; // v == 42.0 (float)
+ w = iota * 42; // w == 84 (ideal integer)
+)
+
+const x = iota; // x == 0 (iota has been reset)
+const y = iota; // y == 0 (iota has been reset)
-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:
+Within an ExpressionList, the value of each iota is the same because
+it is only incremented at a semicolon:
+
-a[i : j]
+const (
+ bit0, mask0 = 1 << iota, 1 << iota - 1; // bit0 == 1, mask0 == 0
+ bit1, mask1; // bit1 == 2, mask1 == 1
+ bit2, mask2; // bit2 == 4, mask2 == 3
+)
-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.
-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).
+This last example exploits the implicit repetition of the
+last non-empty expression list.
+
-Map types
+Type declarations
-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 type declaration binds an identifier, the type name,
+to a new type. TODO: what exactly is a "new type"?
+
-MapType = "map" "[" KeyType "]" ValueType .
-KeyType = CompleteType .
-ValueType = CompleteType .
+TypeDecl = "type" ( TypeSpec | "(" [ TypeSpecList ] ")" ) .
+TypeSpecList = TypeSpec { ";" TypeSpec } [ ";" ] .
+TypeSpec = identifier Type .
-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.
-
-map [string] int
-map [*T] struct { x, y float }
-map [string] interface {}
-
+type IntArray [16] int
-The length of a map "m" can be discovered using the built-in function
+type (
+ Point struct { x, y float };
+ Polar Point
+)
-
-len(m)
+type TreeNode struct {
+ left, right *TreeNode;
+ value Point;
+}
+
+type Comparable interface {
+ cmp(Comparable) int
+}
-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:
+Variable declarations
+
+
+A variable declaration creates a variable, binds an identifier to it and
+gives it a type and optionally an initial value.
+The variable type must be a complete type (§Types).
+
+
+VarDecl = "var" ( VarSpec | "(" [ VarSpecList ] ")" ) .
+VarSpecList = VarSpec { ";" VarSpec } [ ";" ] .
+VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
+
-my_map := make(M, 100);
+var i int
+var U, V, W float
+var k = 0
+var x, y float = -1.0, -2.0
+var (
+ i int;
+ u, v, s = 2.0, 3.0, "bar"
+)
-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.
+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).
+The expressions can be general expressions; they need not be constants.
+
-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).
+Either the type or the expression list must be present. If the
+type is present, it sets the type of each variable and the expressions
+(if any) must be assignment-compatible to that type. If the type
+is absent, the variables take the types of the corresponding
+expressions.
+
+
+If the type is absent and the corresponding expression is a constant
+expression of ideal integer or ideal float type, the type of the
+declared variable is int or float
+respectively:
+
+
+var i = 0 // i has type int
+var f = 3.1415 // f has type float
+
-Channel types
+Short variable declarations
-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). (TODO could it be incomplete?)
+A short variable declaration uses the syntax
-ChannelType = Channel | SendChannel | RecvChannel .
-Channel = "chan" ValueType .
-SendChannel = "chan" "<-" ValueType .
-RecvChannel = "<-" "chan" ValueType .
+SimpleVarDecl = IdentifierList ":=" ExpressionList .
-Upon creation, a channel can be used both to send and to receive.
-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.
+and is shorthand for the declaration syntax
-
-chan T // can send and receive values of type T
-chan <- float // can only be used to send floats
-<-chan int // can only receive ints
+
+"var" IdentifierList = ExpressionList .
-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",
-which takes the channel type and an optional capacity as arguments:
-
-my_chan = make(chan int, 100);
+i, j := 0, 10;
+f := func() int { return 7; }
+ch := new(chan int);
-The capacity sets the size of the buffer in the communication 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.
-
-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).
-
+Unlike regular variable declarations, short variable declarations
+can be used, by analogy with tuple assignment (§Assignments), to
+receive the individual elements of a multi-valued expression such
+as a call to a multi-valued function. In this form, the ExpressionLIst
+must be a single such multi-valued expression, the number of
+identifiers must equal the number of values, and the declared
+variables will be assigned the corresponding values.
+
-Type equality
+
+count, error := os.Close(fd); // os.Close() returns two 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:
-
-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:
+Short variable declarations may appear only inside functions.
+In some contexts such as the initializers for if,
+for, or switch statements,
+they can be used to declare local temporary variables (§Statements).
-
+A function declaration binds an identifier to a function (§Function types). +
-+FunctionDecl = "func" identifier Signature [ Block ] . +-
+func min(x int, y int) int {
+ if x < y {
+ return x;
+ }
+ return y;
+}
+
- +A function must be declared or forward-declared before it can be invoked (§Forward declarations). +Implementation restriction: Functions can only be declared at the package level. +
--Type identity is defined by these rules: +A method declaration binds an identifier to a method, +which is a function with a receiver.
+
+MethodDecl = "func" Receiver identifier Signature [ Block ] .
+Receiver = "(" [ identifier ] [ "*" ] TypeName ")" .
+
+
-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: +The receiver type must be a type name or a pointer to a type name, +and that name is called the receiver base type or just base type. +The base type must not be a pointer type and must be +declared in the same source file as the method. +The method is said to be bound to the base type +and is visible only within selectors for that type +(§Type declarations, §Selectors).
-
+All methods bound to a base type must have the same receiver type,
+either all pointers to the base type or all the base type itself.
+Given type Point, the declarations
+
+func (p *Point) Length() float {
+ return Math.sqrt(p.x * p.x + p.y * p.y);
+}
-
+bind the methods Length and Scale
+to the base type Point.
+
-Finally, two types are different if they are not structurally equal. -(By definition, they cannot be identical, either). +If the +receiver's value is not referenced inside the the body of the method, +its identifier may be omitted in the declaration. The same applies in +general to parameters of functions and methods. +
-For instance, given the declarations ++Methods can be declared +only after their base type is declared or forward-declared, and invoked +only after their own declaration or forward-declaration (§Forward declarations). +Implementation restriction: They can only be declared at package level. +
-
-type (
- T0 []string;
- T1 []string
- T2 struct { a, b int };
- T3 struct { a, c int };
- T4 func (int, float) *T0
- T5 func (x int, y float) *[]string
-)
-
++Mutually-recursive types struct or interface 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. +
-T0 and T0
-T0 and []string
-T2 and T3
-T4 and T5
-T3 and struct { a int; int }
+type List struct // forward declaration of List
+type Item struct {
+ value int;
+ next *List;
+}
+type List struct {
+ head, tail *Item
+}
-
-and these are some types that are identical
-
++A forward-declared type is incomplete (§Types) +until it is fully declared. The full declaration must follow +before the end of the block containing the forward declaration. +
++Functions and methods may similarly be forward-declared by omitting their body. +
-T0 and T0
-[]int and []int
-struct { a, b *T5 } and struct { a, b *T5 }
+func F(a int) int // forward declaration of F
+func G(a, b int) int {
+ return F(a) + F(b)
+}
+func F(a int) int {
+ if a <= 0 { return 0 }
+ return G(a-1, b+1)
+}
-As an example, "T0" and "T1" are equal but not identical because they have
-different declarations.
-