mirror of
https://github.com/golang/go
synced 2024-11-22 00:44:39 -07:00
Move Types before Declarations and Scopes.
This is the only change in this CL: only rearrangement, no content change, so subsequent edits will be easier to understand. R=gri OCL=25353 CL=25353
This commit is contained in:
parent
f27e9f072d
commit
a9ed30ff37
935
doc/go_spec.html
935
doc/go_spec.html
@ -538,473 +538,6 @@ literal.
|
||||
</p>
|
||||
<hr/>
|
||||
|
||||
<h2>Declarations and Scope</h2>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <i>scope</i> 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.
|
||||
</p>
|
||||
<p>
|
||||
There are levels of scoping in effect before each source file is compiled.
|
||||
In order from outermost to innermost:
|
||||
</p>
|
||||
<ol>
|
||||
<li>The <i>universe</i> scope contains all predeclared identifiers.</li>
|
||||
<li>An implicit scope contains only the package name.</li>
|
||||
<li>The <i>package-level</i> 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.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
The scope of an identifier depends on the entity declared:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li> The scope of predeclared identifiers is the universe scope.</li>
|
||||
|
||||
<li> 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.</li>
|
||||
|
||||
<li> 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
|
||||
<i>init</i> statement of an <code>if </code>, <code>for</code>,
|
||||
or <code>switch </code> statement, the
|
||||
innermost surrounding block is the block associated
|
||||
with that statement.</li>
|
||||
|
||||
<li> The scope of a parameter or result is the body of the
|
||||
corresponding function.</li>
|
||||
|
||||
<li> The scope of a field or method is selectors for the
|
||||
corresponding type containing the field or method (§Selectors).</li>
|
||||
|
||||
<li> 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.</li>
|
||||
</ol>
|
||||
|
||||
<h3>Predeclared identifiers</h3>
|
||||
|
||||
<p>
|
||||
The following identifiers are implicitly declared in the outermost scope:
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
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?)
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Exported identifiers</h3>
|
||||
|
||||
<p>
|
||||
By default, identifiers are visible only within the package in which they are declared.
|
||||
Some identifiers are <i>exported</i> and can be referenced using
|
||||
<i>qualified identifiers</i> in other packages (§Qualified identifiers).
|
||||
If an identifier satisfies these two conditions:
|
||||
</p>
|
||||
<ol>
|
||||
<li>the first character of the identifier's name is a Unicode upper case letter;
|
||||
<li>the identifier is declared at the package level or is a field or method of a type
|
||||
declared at the top level;
|
||||
</ol>
|
||||
<p>
|
||||
it will be exported automatically.
|
||||
</p>
|
||||
|
||||
<h3>Const declarations</h3>
|
||||
|
||||
<p>
|
||||
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 n<sup>th</sup> identifier on
|
||||
the left is bound to value of the n<sup>th</sup> expression on the
|
||||
right.
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
ConstDecl = "const" ( ConstSpec | "(" [ ConstSpecList ] ")" ) .
|
||||
ConstSpecList = ConstSpec { ";" ConstSpec } [ ";" ] .
|
||||
ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
|
||||
|
||||
IdentifierList = identifier { "," identifier } .
|
||||
ExpressionList = Expression { "," Expression } .
|
||||
|
||||
CompleteType = Type .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Within a parenthesized <code>const</code> 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 <code>iota</code> constant generator
|
||||
(§Iota) this mechanism permits light-weight declaration of sequential values:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
const (
|
||||
Sunday = iota;
|
||||
Monday;
|
||||
Tuesday;
|
||||
Wednesday;
|
||||
Thursday;
|
||||
Friday;
|
||||
Partyday;
|
||||
numberOfDays; // this constant is not exported
|
||||
)
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Iota</h3>
|
||||
|
||||
<p>
|
||||
Within a constant declaration, the predeclared pseudo-constant
|
||||
<code>iota</code> represents successive integers. It is reset to 0
|
||||
whenever the reserved word <code>const</code> appears in the source
|
||||
and increments with each semicolon. It can be used to construct a
|
||||
set of related constants:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Within an ExpressionList, the value of each <code>iota</code> is the same because
|
||||
it is only incremented at a semicolon:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
const (
|
||||
bit0, mask0 = 1 << iota, 1 << iota - 1; // bit0 == 1, mask0 == 0
|
||||
bit1, mask1; // bit1 == 2, mask1 == 1
|
||||
bit2, mask2; // bit2 == 4, mask2 == 3
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This last example exploits the implicit repetition of the
|
||||
last non-empty expression list.
|
||||
</p>
|
||||
|
||||
|
||||
<h3>Type declarations</h3>
|
||||
|
||||
<p>
|
||||
A type declaration binds an identifier, the <i>type name</i>,
|
||||
to a new type. <font color=red>TODO: what exactly is a "new type"?</font>
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
TypeDecl = "type" ( TypeSpec | "(" [ TypeSpecList ] ")" ) .
|
||||
TypeSpecList = TypeSpec { ";" TypeSpec } [ ";" ] .
|
||||
TypeSpec = identifier Type .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
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
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Variable declarations</h3>
|
||||
|
||||
<p>
|
||||
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).
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
VarDecl = "var" ( VarSpec | "(" [ VarSpecList ] ")" ) .
|
||||
VarSpecList = VarSpec { ";" VarSpec } [ ";" ] .
|
||||
VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
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"
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If there are expressions, their number must be equal
|
||||
to the number of identifiers, and the n<sup>th</sup> variable
|
||||
is initialized to the value of the n<sup>th</sup> expression.
|
||||
Otherwise, each variable is initialized to the <i>zero</i>
|
||||
of the type (§Program initialization and execution).
|
||||
The expressions can be general expressions; they need not be constants.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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 <code>int</code> or <code>float</code>
|
||||
respectively:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var i = 0 // i has type int
|
||||
var f = 3.1415 // f has type float
|
||||
</pre>
|
||||
|
||||
<h3>Short variable declarations</h3>
|
||||
|
||||
A <i>short variable declaration</i> uses the syntax
|
||||
|
||||
<pre class="grammar">
|
||||
SimpleVarDecl = IdentifierList ":=" ExpressionList .
|
||||
</pre>
|
||||
|
||||
and is shorthand for the declaration syntax
|
||||
|
||||
<pre class="grammar">
|
||||
"var" IdentifierList = ExpressionList .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
i, j := 0, 10;
|
||||
f := func() int { return 7; }
|
||||
ch := new(chan int);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
count, error := os.Close(fd); // os.Close() returns two values
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Short variable declarations may appear only inside functions.
|
||||
In some contexts such as the initializers for <code>if</code>,
|
||||
<code>for</code>, or <code>switch</code> statements,
|
||||
they can be used to declare local temporary variables (§Statements).
|
||||
</p>
|
||||
|
||||
<h3>Function declarations</h3>
|
||||
|
||||
<p>
|
||||
A function declaration binds an identifier to a function (§Function types).
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
FunctionDecl = "func" identifier Signature [ Block ] .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
func min(x int, y int) int {
|
||||
if x < y {
|
||||
return x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h3>Method declarations</h3>
|
||||
|
||||
<p>
|
||||
A method declaration binds an identifier to a method,
|
||||
which is a function with a <i>receiver</i>.
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
MethodDecl = "func" Receiver identifier Signature [ Block ] .
|
||||
Receiver = "(" [ identifier ] [ "*" ] TypeName ")" .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The receiver type must be a type name or a pointer to a type name,
|
||||
and that name is called the <i>receiver base type</i> or just <i>base type</i>.
|
||||
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 <i>bound</i> to the base type
|
||||
and is visible only within selectors for that type
|
||||
(§Type declarations, §Selectors).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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 <code>Point</code>, the declarations
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
bind the methods <code>Length</code> and <code>Scale</code>
|
||||
to the base type <code>Point</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h3>Forward declarations</h3>
|
||||
|
||||
<p>
|
||||
Mutually-recursive types struct or interface types require that one be
|
||||
<i>forward declared</i> 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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type List struct // forward declaration of List
|
||||
type Item struct {
|
||||
value int;
|
||||
next *List;
|
||||
}
|
||||
type List struct {
|
||||
head, tail *Item
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Functions and methods may similarly be forward-declared by omitting their body.
|
||||
</p>
|
||||
<pre>
|
||||
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)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h2>Types</h2>
|
||||
|
||||
A type specifies the set of values that variables of that type may assume
|
||||
@ -1803,6 +1336,474 @@ different declarations.
|
||||
|
||||
<hr/>
|
||||
|
||||
|
||||
<h2>Declarations and Scope</h2>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The <i>scope</i> 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.
|
||||
</p>
|
||||
<p>
|
||||
There are levels of scoping in effect before each source file is compiled.
|
||||
In order from outermost to innermost:
|
||||
</p>
|
||||
<ol>
|
||||
<li>The <i>universe</i> scope contains all predeclared identifiers.</li>
|
||||
<li>An implicit scope contains only the package name.</li>
|
||||
<li>The <i>package-level</i> 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.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
The scope of an identifier depends on the entity declared:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li> The scope of predeclared identifiers is the universe scope.</li>
|
||||
|
||||
<li> 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.</li>
|
||||
|
||||
<li> 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
|
||||
<i>init</i> statement of an <code>if </code>, <code>for</code>,
|
||||
or <code>switch </code> statement, the
|
||||
innermost surrounding block is the block associated
|
||||
with that statement.</li>
|
||||
|
||||
<li> The scope of a parameter or result is the body of the
|
||||
corresponding function.</li>
|
||||
|
||||
<li> The scope of a field or method is selectors for the
|
||||
corresponding type containing the field or method (§Selectors).</li>
|
||||
|
||||
<li> 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.</li>
|
||||
</ol>
|
||||
|
||||
<h3>Predeclared identifiers</h3>
|
||||
|
||||
<p>
|
||||
The following identifiers are implicitly declared in the outermost scope:
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
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?)
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Exported identifiers</h3>
|
||||
|
||||
<p>
|
||||
By default, identifiers are visible only within the package in which they are declared.
|
||||
Some identifiers are <i>exported</i> and can be referenced using
|
||||
<i>qualified identifiers</i> in other packages (§Qualified identifiers).
|
||||
If an identifier satisfies these two conditions:
|
||||
</p>
|
||||
<ol>
|
||||
<li>the first character of the identifier's name is a Unicode upper case letter;
|
||||
<li>the identifier is declared at the package level or is a field or method of a type
|
||||
declared at the top level;
|
||||
</ol>
|
||||
<p>
|
||||
it will be exported automatically.
|
||||
</p>
|
||||
|
||||
<h3>Const declarations</h3>
|
||||
|
||||
<p>
|
||||
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 n<sup>th</sup> identifier on
|
||||
the left is bound to value of the n<sup>th</sup> expression on the
|
||||
right.
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
ConstDecl = "const" ( ConstSpec | "(" [ ConstSpecList ] ")" ) .
|
||||
ConstSpecList = ConstSpec { ";" ConstSpec } [ ";" ] .
|
||||
ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
|
||||
|
||||
IdentifierList = identifier { "," identifier } .
|
||||
ExpressionList = Expression { "," Expression } .
|
||||
|
||||
CompleteType = Type .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Within a parenthesized <code>const</code> 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 <code>iota</code> constant generator
|
||||
(§Iota) this mechanism permits light-weight declaration of sequential values:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
const (
|
||||
Sunday = iota;
|
||||
Monday;
|
||||
Tuesday;
|
||||
Wednesday;
|
||||
Thursday;
|
||||
Friday;
|
||||
Partyday;
|
||||
numberOfDays; // this constant is not exported
|
||||
)
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Iota</h3>
|
||||
|
||||
<p>
|
||||
Within a constant declaration, the predeclared pseudo-constant
|
||||
<code>iota</code> represents successive integers. It is reset to 0
|
||||
whenever the reserved word <code>const</code> appears in the source
|
||||
and increments with each semicolon. It can be used to construct a
|
||||
set of related constants:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Within an ExpressionList, the value of each <code>iota</code> is the same because
|
||||
it is only incremented at a semicolon:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
const (
|
||||
bit0, mask0 = 1 << iota, 1 << iota - 1; // bit0 == 1, mask0 == 0
|
||||
bit1, mask1; // bit1 == 2, mask1 == 1
|
||||
bit2, mask2; // bit2 == 4, mask2 == 3
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
This last example exploits the implicit repetition of the
|
||||
last non-empty expression list.
|
||||
</p>
|
||||
|
||||
|
||||
<h3>Type declarations</h3>
|
||||
|
||||
<p>
|
||||
A type declaration binds an identifier, the <i>type name</i>,
|
||||
to a new type. <font color=red>TODO: what exactly is a "new type"?</font>
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
TypeDecl = "type" ( TypeSpec | "(" [ TypeSpecList ] ")" ) .
|
||||
TypeSpecList = TypeSpec { ";" TypeSpec } [ ";" ] .
|
||||
TypeSpec = identifier Type .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
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
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3>Variable declarations</h3>
|
||||
|
||||
<p>
|
||||
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).
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
VarDecl = "var" ( VarSpec | "(" [ VarSpecList ] ")" ) .
|
||||
VarSpecList = VarSpec { ";" VarSpec } [ ";" ] .
|
||||
VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
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"
|
||||
)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If there are expressions, their number must be equal
|
||||
to the number of identifiers, and the n<sup>th</sup> variable
|
||||
is initialized to the value of the n<sup>th</sup> expression.
|
||||
Otherwise, each variable is initialized to the <i>zero</i>
|
||||
of the type (§Program initialization and execution).
|
||||
The expressions can be general expressions; they need not be constants.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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 <code>int</code> or <code>float</code>
|
||||
respectively:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var i = 0 // i has type int
|
||||
var f = 3.1415 // f has type float
|
||||
</pre>
|
||||
|
||||
<h3>Short variable declarations</h3>
|
||||
|
||||
A <i>short variable declaration</i> uses the syntax
|
||||
|
||||
<pre class="grammar">
|
||||
SimpleVarDecl = IdentifierList ":=" ExpressionList .
|
||||
</pre>
|
||||
|
||||
and is shorthand for the declaration syntax
|
||||
|
||||
<pre class="grammar">
|
||||
"var" IdentifierList = ExpressionList .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
i, j := 0, 10;
|
||||
f := func() int { return 7; }
|
||||
ch := new(chan int);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
count, error := os.Close(fd); // os.Close() returns two values
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Short variable declarations may appear only inside functions.
|
||||
In some contexts such as the initializers for <code>if</code>,
|
||||
<code>for</code>, or <code>switch</code> statements,
|
||||
they can be used to declare local temporary variables (§Statements).
|
||||
</p>
|
||||
|
||||
<h3>Function declarations</h3>
|
||||
|
||||
<p>
|
||||
A function declaration binds an identifier to a function (§Function types).
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
FunctionDecl = "func" identifier Signature [ Block ] .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
func min(x int, y int) int {
|
||||
if x < y {
|
||||
return x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h3>Method declarations</h3>
|
||||
|
||||
<p>
|
||||
A method declaration binds an identifier to a method,
|
||||
which is a function with a <i>receiver</i>.
|
||||
</p>
|
||||
<pre class="grammar">
|
||||
MethodDecl = "func" Receiver identifier Signature [ Block ] .
|
||||
Receiver = "(" [ identifier ] [ "*" ] TypeName ")" .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The receiver type must be a type name or a pointer to a type name,
|
||||
and that name is called the <i>receiver base type</i> or just <i>base type</i>.
|
||||
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 <i>bound</i> to the base type
|
||||
and is visible only within selectors for that type
|
||||
(§Type declarations, §Selectors).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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 <code>Point</code>, the declarations
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
bind the methods <code>Length</code> and <code>Scale</code>
|
||||
to the base type <code>Point</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
|
||||
<h3>Forward declarations</h3>
|
||||
|
||||
<p>
|
||||
Mutually-recursive types struct or interface types require that one be
|
||||
<i>forward declared</i> 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.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type List struct // forward declaration of List
|
||||
type Item struct {
|
||||
value int;
|
||||
next *List;
|
||||
}
|
||||
type List struct {
|
||||
head, tail *Item
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Functions and methods may similarly be forward-declared by omitting their body.
|
||||
</p>
|
||||
<pre>
|
||||
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)
|
||||
}
|
||||
</pre>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h2>Expressions</h2>
|
||||
|
||||
An expression specifies the computation of a value via the application of
|
||||
|
Loading…
Reference in New Issue
Block a user