From a9ed30ff377976b9e2fd7fb4a897ffda71649474 Mon Sep 17 00:00:00 2001
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. -
- --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 scope of an identifier depends on the entity declared: -
- -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 - -Constants: - true false iota nil - -Functions: - cap convert len make new panic panicln print println typeof (TODO: typeof??) - -Packages: - sys unsafe (TODO: does sys endure?) -- - -
-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. -
- --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. -
- --ConstDecl = "const" ( ConstSpec | "(" [ ConstSpecList ] ")" ) . -ConstSpecList = ConstSpec { ";" ConstSpec } [ ";" ] . -ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] . - -IdentifierList = identifier { "," identifier } . -ExpressionList = Expression { "," Expression } . - -CompleteType = Type . -- -
-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:
-
-const ( - Sunday = iota; - Monday; - Tuesday; - Wednesday; - Thursday; - Friday; - Partyday; - numberOfDays; // this constant is not exported -) -- - -
-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 -) - -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) -- -
-Within an ExpressionList, the value of each iota
is 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 -) -- -
-This last example exploits the implicit repetition of the -last non-empty expression list. -
- - --A type declaration binds an identifier, the type name, -to a new type. TODO: what exactly is a "new type"? -
- --TypeDecl = "type" ( TypeSpec | "(" [ TypeSpecList ] ")" ) . -TypeSpecList = TypeSpec { ";" TypeSpec } [ ";" ] . -TypeSpec = identifier Type . -- -
-type IntArray [16] int - -type ( - Point struct { x, y float }; - Polar Point -) - -type TreeNode struct { - left, right *TreeNode; - value Point; -} - -type Comparable interface { - cmp(Comparable) int -} -- -
-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 ) . -- -
-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" -) -- -
-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 int
or float
-respectively:
-
-var i = 0 // i has type int -var f = 3.1415 // f has type float -- -
-SimpleVarDecl = IdentifierList ":=" ExpressionList . -- -and is shorthand for the declaration syntax - -
-"var" IdentifierList = ExpressionList . -- -
-i, j := 0, 10; -f := func() int { return 7; } -ch := new(chan int); -- -
-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. -
- --count, error := os.Close(fd); // os.Close() returns two values -- -
-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. -
- --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 ")" . -- -
-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); -} - -func (p *Point) Scale(factor float) { - p.x = p.x * factor; - p.y = p.y * factor; -} -- -
-bind the methods Length
and Scale
-to the base type Point
.
-
-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. -
- --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. -
- --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 List struct // forward declaration of List -type Item struct { - value int; - next *List; -} -type List struct { - head, tail *Item -} --
-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. -
--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) -} -- -
+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. +
+ ++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 scope of an identifier depends on the entity declared: +
+ +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 + +Constants: + true false iota nil + +Functions: + cap convert len make new panic panicln print println typeof (TODO: typeof??) + +Packages: + sys unsafe (TODO: does sys endure?) ++ + +
+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. +
+ ++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. +
+ ++ConstDecl = "const" ( ConstSpec | "(" [ ConstSpecList ] ")" ) . +ConstSpecList = ConstSpec { ";" ConstSpec } [ ";" ] . +ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] . + +IdentifierList = identifier { "," identifier } . +ExpressionList = Expression { "," Expression } . + +CompleteType = Type . ++ +
+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:
+
+const ( + Sunday = iota; + Monday; + Tuesday; + Wednesday; + Thursday; + Friday; + Partyday; + numberOfDays; // this constant is not exported +) ++ + +
+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 +) + +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) ++ +
+Within an ExpressionList, the value of each iota
is 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 +) ++ +
+This last example exploits the implicit repetition of the +last non-empty expression list. +
+ + ++A type declaration binds an identifier, the type name, +to a new type. TODO: what exactly is a "new type"? +
+ ++TypeDecl = "type" ( TypeSpec | "(" [ TypeSpecList ] ")" ) . +TypeSpecList = TypeSpec { ";" TypeSpec } [ ";" ] . +TypeSpec = identifier Type . ++ +
+type IntArray [16] int + +type ( + Point struct { x, y float }; + Polar Point +) + +type TreeNode struct { + left, right *TreeNode; + value Point; +} + +type Comparable interface { + cmp(Comparable) int +} ++ +
+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 ) . ++ +
+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" +) ++ +
+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 int
or float
+respectively:
+
+var i = 0 // i has type int +var f = 3.1415 // f has type float ++ +
+SimpleVarDecl = IdentifierList ":=" ExpressionList . ++ +and is shorthand for the declaration syntax + +
+"var" IdentifierList = ExpressionList . ++ +
+i, j := 0, 10; +f := func() int { return 7; } +ch := new(chan int); ++ +
+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. +
+ ++count, error := os.Close(fd); // os.Close() returns two values ++ +
+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. +
+ ++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 ")" . ++ +
+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); +} + +func (p *Point) Scale(factor float) { + p.x = p.x * factor; + p.y = p.y * factor; +} ++ +
+bind the methods Length
and Scale
+to the base type Point
.
+
+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. +
+ ++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. +
+ ++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 List struct // forward declaration of List +type Item struct { + value int; + next *List; +} +type List struct { + head, tail *Item +} ++
+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. +
++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) +} ++ +