1
0
mirror of https://github.com/golang/go synced 2024-11-25 11:17:56 -07:00

- precise scope rules

- forward decls for interface and struct types
- complete & incomplete types
- optional semicolons

R=r
DELTA=216  (95 added, 15 deleted, 106 changed)
OCL=16465
CL=16687
This commit is contained in:
Robert Griesemer 2008-10-07 17:14:30 -07:00
parent 02d184b303
commit 7abfcd981f

View File

@ -4,7 +4,7 @@ The Go Programming Language Specification (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson Robert Griesemer, Rob Pike, Ken Thompson
---- ----
(October 3 2008) (October 7, 2008)
This document is a semi-formal specification of the Go systems This document is a semi-formal specification of the Go systems
@ -33,7 +33,6 @@ Open issues according to gri:
(should only use new(arraytype, n) - this will allow later (should only use new(arraytype, n) - this will allow later
extension to multi-dim arrays w/o breaking the language) extension to multi-dim arrays w/o breaking the language)
[ ] comparison operators: can we compare interfaces? [ ] comparison operators: can we compare interfaces?
[ ] optional semicolons: too complicated and unclear
[ ] like to have assert() in the language, w/ option to disable code gen for it [ ] like to have assert() in the language, w/ option to disable code gen for it
[ ] composite types should uniformly create an instance instead of a pointer [ ] composite types should uniformly create an instance instead of a pointer
[ ] clarify slice rules [ ] clarify slice rules
@ -55,13 +54,18 @@ Open issues according to gri:
[ ] provide composite literal notation to address array indices: []int{ 0: x1, 1: x2, ... } [ ] provide composite literal notation to address array indices: []int{ 0: x1, 1: x2, ... }
and struct field names (both seem easy to do). and struct field names (both seem easy to do).
[ ] reopening & and func issue: Seems inconsistent as both &func(){} and func(){} are [ ] reopening & and func issue: Seems inconsistent as both &func(){} and func(){} are
permitted. permitted. Suggestion: func literals are pointers. We need to use & for all other
functions. This would be in consistency with the declaration of function pointer
variables and the use of '&' to convert methods into function pointers.
[ ] Conversions: can we say: "type T int; T(3.0)" ?
[ ] Is . import implemented?
Decisions in need of integration into the doc: Decisions in need of integration into the doc:
[ ] pair assignment is required to get map, and receive ok. [ ] pair assignment is required to get map, and receive ok.
Closed issues: Closed issues:
[x] optional semicolons: too complicated and unclear
[x] anonymous types are written using a type name, which can be a qualified identifier. [x] anonymous types are written using a type name, which can be a qualified identifier.
this might be a problem when referring to such a field using the type name. this might be a problem when referring to such a field using the type name.
[x] nil and interfaces - can we test for nil, what does it mean, etc. [x] nil and interfaces - can we test for nil, what does it mean, etc.
@ -93,6 +97,7 @@ Contents
Character and string literals Character and string literals
Operators and delimitors Operators and delimitors
Reserved words Reserved words
Optional semicolons
Declarations and scope rules Declarations and scope rules
Const declarations Const declarations
@ -197,6 +202,9 @@ Lower-case production names are used to identify productions that cannot
be broken by white space or comments; they are usually tokens. Other be broken by white space or comments; they are usually tokens. Other
productions are in CamelCase. productions are in CamelCase.
Productions with names ending in List never produces the empty phrase.
For instance, an ExpressionList always contains at least one expression.
Source code representation Source code representation
---- ----
@ -461,49 +469,73 @@ The following words are reserved and must not be used as identifiers:
continue for import return var continue for import return var
Optional semicolons
----
Semicolons are used to terminate all declarations and statements.
The following rules apply:
1) Semicolons can be omitted after declarations at the top
(package) level.
2) Semicolons can be omitted before and after a closing
parentheses ")" or brace "}" on a list of declarations
or statements.
Semicolons that are subject to these rules are represented using
the OptSemicolon production:
OptSemicolon = [ ";" ] .
Declarations and scope rules Declarations and scope rules
---- ----
A declaration ``binds'' an identifier with a language entity (such as A declaration ``binds'' an identifier to a language entity (such as
a package, constant, type, struct field, variable, parameter, result, a package, constant, type, struct field, variable, parameter, result,
function, method) and specifies properties of that entity such as its type. function, method) and specifies properties of that entity such as its type.
Declaration = [ "export" ] ( ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl ) . Declaration =
[ "export" ]
( ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl )
OptSemicolon .
Every identifier in a program must be declared; some identifiers, such as "int" Every identifier in a program must be declared; some identifiers, such as "int"
and "true", are predeclared. and "true", are predeclared.
The ``scope'' of an identifier is the extent of source text within which the The ``scope'' of an identifier is the extent of source text within which the
identifier can be used to refer to the bound entity. No identifier may be declared identifier denotes the bound entity. No identifier may be declared twice in a
twice in a single scope. Go is lexically scoped: An identifier refers to the entity single scope. Go is lexically scoped: An identifier denotes the entity it is
it is bound to only within the scope of the identifier. bound to only within the scope of the identifier.
For instance, for variable "x", the scope of identifier "x" is the extent of For instance, for a variable named "x", the scope of identifier "x" is the
source text within which "x" refers to that particular variable. It is illegal extent of source text within which "x" denotes that particular variable.
to declare another identifier "x" within the same scope. It is illegal to declare another identifier "x" within the same scope.
The scope of an identifier depends on the entity declared. The scope of an identifier depends on the entity declared. The scope for
an identifier always excludes scopes redeclaring the identifier in nested
blocks. An identifier declared in a nested block is said to ``shadow'' the
same identifier declared in an outer block.
1. The scope of predeclared identifiers is the entire source file, excluding 1. The scope of predeclared identifiers is the entire source file.
any scopes in nested blocks that redeclare the identifier.
2. The scope of an identifier referring to a constant, type, variable, 2. The scope of an identifier denoting a type, function or package
function, method or package extends textually from the point of the extends textually from the point of the identifier in the declaration
identifier in the declaration to the end of the innermost surrounding to the end of the innermost surrounding block.
block. It excludes any scopes in nested blocks that redeclare the
identifier.
3. The scope of a parameter or result identifier is the body of the 3. The scope of a constant or variable extends textually from
corresponding function or method. It excludes any scopes in nested after the declaration to the end of the innermost surrounding
blocks that redeclare the identifier. block.
4. The scope of a field or method identifier is selectors for the 4. The scope of a parameter or result identifier is the body of the
corresponding function.
5. The scope of a field or method identifier is selectors for the
corresponding type containing the field or method (§Selectors). corresponding type containing the field or method (§Selectors).
5. Implicit forward declaration: An identifier "T" may be used textually 6. The scope of a label is the body of the innermost surrounding
before the beginning of the scope of "T", but only to denote a pointer function and does not intersect with any non-label scope. Thus,
type of the form "*T". The full declaration of "T" must follow within each function has its own private label scope.
the same block containing the forward declaration.
An entity is said to be ``local'' to its scope. Declarations in the package An entity is said to be ``local'' to its scope. Declarations in the package
scope are ``global'' declarations. scope are ``global'' declarations.
@ -521,11 +553,6 @@ all structure fields and all structure and interface methods are exported also.
export const pi float = 3.14159265 export const pi float = 3.14159265
export func Parse(source string); export func Parse(source string);
The scope of a label 'x' is the entire block of the surrounding function excluding
any nested function. Thus, each function has its own private label scope, and
identifiers for labels never conflict with any non-label identifier. Within a
function a label 'x' may only be declared once (§Label declarations).
Note that at the moment the old-style export via ExportDecl is still supported. Note that at the moment the old-style export via ExportDecl is still supported.
TODO: Eventually we need to be able to restrict visibility of fields and methods. TODO: Eventually we need to be able to restrict visibility of fields and methods.
@ -568,12 +595,12 @@ are unknown in general).
Const declarations Const declarations
---- ----
A constant declaration gives a name to the value of a constant expression A constant declaration binds an identifier to the value of a constant
(§Constant expressions). expression (§Constant expressions).
ConstDecl = "const" ( ConstSpec | "(" ConstSpecList [ ";" ] ")" ). ConstDecl = "const" ( ConstSpec | "(" ConstSpecList ")" ).
ConstSpec = identifier [ Type ] "=" Expression . ConstSpec = identifier [ CompleteType ] "=" Expression .
ConstSpecList = ConstSpec { ";" ConstSpecOptExpr }. ConstSpecList = ConstSpec OptSemicolon { ConstSpecOptExpr OptSemicolon }.
ConstSpecOptExpr = identifier [ Type ] [ "=" Expression ] . ConstSpecOptExpr = identifier [ Type ] [ "=" Expression ] .
const pi float = 3.14159265 const pi float = 3.14159265
@ -587,7 +614,7 @@ The constant expression may be omitted, in which case the expression is
the last expression used after the reserved word "const". If no such expression the last expression used after the reserved word "const". If no such expression
exists, the constant expression cannot be omitted. exists, the constant expression cannot be omitted.
Together with the "iota" constant generator (described later), Together with the "iota" constant generator (§Iota),
implicit repetition permits light-weight declaration of enumerated implicit repetition permits light-weight declaration of enumerated
values: values:
@ -647,16 +674,16 @@ underflow.
Type declarations Type declarations
---- ----
A type declaration introduces a name for a type. A type declaration specifies a new type and binds an identifier to it.
TypeDecl = "type" ( TypeSpec | "(" TypeSpecList [ ";" ] ")" ). TypeDecl = "type" ( TypeSpec | "(" TypeSpecList ")" ).
TypeSpec = identifier Type . TypeSpec = identifier Type .
TypeSpecList = TypeSpec { ";" TypeSpec }. TypeSpecList = TypeSpec OptSemicolon { TypeSpec OptSemicolon }.
The name refers to an incomplete type until the type specification is complete. A struct or interface type may be forward-declared (§Struct types,
Incomplete types can be referred to only by pointer types. Consequently, in a §Interface types). A forward-declared type is incomplete (§Types)
type declaration a type may not refer to itself unless it does so with a pointer until it is fully declared. The full declaration must must follow
type. within the same block containing the forward declaration.
type IntArray [16] int type IntArray [16] int
@ -670,17 +697,23 @@ type.
value Point; value Point;
} }
type Comparable interface {
cmp(Comparable) int
}
Variable declarations Variable declarations
---- ----
A variable declaration creates a variable and gives it a type and a name. A variable declaration creates a variable, binds an identifier to it and
It may optionally give the variable an initial value; in some forms of gives it a type. It may optionally give the variable an initial value.
declaration the type of the initial value defines the type of the variable. The variable type must be a complete type (§Types).
In some forms of declaration the type of the initial value defines the type
of the variable.
VarDecl = "var" ( VarSpec | "(" VarSpecList [ ";" ] ")" ) . VarDecl = "var" ( VarSpec | "(" VarSpecList ")" ) .
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) . VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
VarSpecList = VarSpec { ";" VarSpec } . VarSpecList = VarSpec OptSemicolon { VarSpec OptSemicolon } .
IdentifierList = identifier { "," identifier } . IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } . ExpressionList = Expression { "," Expression } .
@ -738,7 +771,8 @@ That is, one can export global functions, types, and so on but not
local variables or structure fields. local variables or structure fields.
Exporting an identifier makes the identifier visible externally to the Exporting an identifier makes the identifier visible externally to the
package. If the identifier represents a type, the type structure is package. If the identifier represents a type, it must be a complete
type (§Types) and the type structure is
exported as well. The exported identifiers may appear later in the exported as well. The exported identifiers may appear later in the
source than the export directive itself, but it is an error to specify source than the export directive itself, but it is an error to specify
an identifier not declared anywhere in the source file containing the an identifier not declared anywhere in the source file containing the
@ -770,12 +804,26 @@ and interfaces. They are constructed from other (basic or composite) types.
FunctionType | MapType | StructType | PointerType . FunctionType | MapType | StructType | PointerType .
TypeName = QualifiedIdent. TypeName = QualifiedIdent.
Types may be ``complete'' or ''incomplete''. Basic, pointer, function and
interface types are always complete (although their components, such
as the base type of a pointer type, may be incomplete). All other types are
complete when they are fully declared. Incomplete types are subject to
usage restrictions; for instance a variable type cannot be an incomplete
type.
CompleteType = Type .
The ``interface'' of a type is the set of methods bound to it The ``interface'' of a type is the set of methods bound to it
(§Method declarations). The interface of a pointer type is the interface (§Method declarations). The interface of a pointer type is the interface
of the pointer base type (§Pointer types). All types have an interface; of the pointer base type (§Pointer types). All types have an interface;
if they have no methods associated with them, their interface is if they have no methods associated with them, their interface is
called the ``empty'' interface. called the ``empty'' interface.
TODO: Since methods are added one at a time, the interface of a type may
be different at different points in the source text. Thus, static checking
may give different results then dynamic checking which is problematic.
Need to resolve.
The ``static type'' (or simply ``type'') of a variable is the type defined by 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 the variable's declaration. The ``dynamic type'' of a variable is the actual
type of the value stored in a variable at runtime. Except for variables of type of the value stored in a variable at runtime. Except for variables of
@ -887,14 +935,14 @@ designated by indices which are integers between 0 and the length - 1.
An array type specifies the array element type and an optional array An array type specifies the array element type and an optional array
length which must be a compile-time constant expression of a (signed or length which must be a compile-time constant expression of a (signed or
unsigned) int type. If present, the array length and its value is part of unsigned) int type. If present, the array length and its value is part of
the array type. the array type. The element type must be a complete type (§Types).
If the length is present in the declaration, the array is called If the length is present in the declaration, the array is called
``fixed array''; if the length is absent, the array is called ``open array''. ``fixed array''; if the length is absent, the array is called ``open array''.
ArrayType = "[" [ ArrayLength ] "]" ElementType . ArrayType = "[" [ ArrayLength ] "]" ElementType .
ArrayLength = Expression . ArrayLength = Expression .
ElementType = Type . ElementType = CompleteType .
Type equality: Two array types are equal only if both have the same element Type equality: Two array types are equal only if both have the same element
type and if both are either fixed arrays with the same array length, or both type and if both are either fixed arrays with the same array length, or both
@ -1016,14 +1064,14 @@ Struct types
---- ----
A struct is a composite type consisting of a fixed number of elements, A struct is a composite type consisting of a fixed number of elements,
called fields, with possibly different types. The struct type declaration called fields, with possibly different types. A struct type declares
specifies the name and type for each field. The scope of each field identifier an identifier and type for each field. Within a struct type no field
extends from the point of the declaration to the end of the struct type, but identifier may be declared twice and all field types must be complete
it is also visible within field selectors (§Primary Expressions). types (§Types).
StructType = "struct" "{" [ FieldList [ ";" ] ] "}" . StructType = "struct" [ "{" [ FieldList [ ";" ] ] "}" ] .
FieldList = FieldDecl { ";" FieldDecl } . FieldList = FieldDecl { ";" FieldDecl } .
FieldDecl = IdentifierList Type | TypeName . FieldDecl = IdentifierList CompleteType | TypeName .
// An empty struct. // An empty struct.
struct {} struct {}
@ -1037,8 +1085,8 @@ it is also visible within field selectors (§Primary Expressions).
} }
A struct may contain ``anonymous fields'', which are declared with A struct may contain ``anonymous fields'', which are declared with
a type name but no explicit field name. Instead, the unqualified type a type name but no explicit field identifier. Instead, the unqualified type
name acts as the field name. Anonymous fields must not be interface types. name acts as the field identifier. Anonymous fields must not be interface types.
// A struct with two anonymous fields of type T1 and P.T2 // A struct with two anonymous fields of type T1 and P.T2
struct { struct {
@ -1047,15 +1095,23 @@ name acts as the field name. Anonymous fields must not be interface types.
x, y int; x, y int;
} }
As with all scopes, each field name must be unique within a single struct The unqualified type name of an anonymous field must not conflict with the
(§Declarations and scope rules). Consequently, the unqualified type name of field identifier (or unqualified type name for an anonymous field) of any
an anonymous field must not conflict with the field name (or unqualified other field within the struct.
type name for an anonymous field) of any other field within the struct.
Fields and methods (§Method declarations) of an anonymous field become directly 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 accessible as fields and methods of the struct without the need to provide the
type name of the respective anonymous field (§TODO). type name of the respective anonymous field (§TODO).
Forward declaration:
A struct type consisting of only the reserved word "struct" may be used in
a type declaration; it declares an incomplete struct type (§Type declarations).
This allows the construction of mutually recursive types such as:
type S2 struct // forward declaration of S2
type S1 struct { s2 *S2 }
type S2 struct { s1 *S1 }
Type equality: Two struct types are equal only if both have the same number Type equality: Two struct types are equal only if both have the same number
of fields in the same order, corresponding fields are either both named or of fields in the same order, corresponding fields are either both named or
anonymous, and the corresponding field types are equal. Specifically, anonymous, and the corresponding field types are equal. Specifically,
@ -1077,21 +1133,17 @@ type, called the ``base type'' of the pointer, and the value "nil".
*int *int
*map[string] *chan *map[string] *chan
For pointer types (only), the pointer base type may be an The pointer base type may be denoted by an identifier referring to an
identifier referring to an incomplete (not yet fully defined) or undeclared incomplete type (§Types), possibly declared via a forward declaration.
type. This allows the construction of recursive and mutually recursive types This allows the construction of recursive and mutually recursive types
such as: such as:
type S struct { s *S } type S struct { s *S }
type S2 struct // forward declaration of S2
type S1 struct { s2 *S2 } type S1 struct { s2 *S2 }
type S2 struct { s1 *S1 } type S2 struct { s1 *S1 }
If the base type is an undeclared identifier, the declaration implicitly
forward-declares an (incomplete) type with the respective name. Any such
forward-declared type must be completely declared in the same or an outer
scope.
Type equality: Two pointer types are equal only if both have equal Type equality: Two pointer types are equal only if both have equal
base types. base types.
@ -1106,13 +1158,13 @@ Map types
A map is a composite type consisting of a variable number of entries 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 called (key, value) pairs. For a given map, the keys and values must
each be of a specific type called the key and value type, respectively. each be of a specific complete type (§Types) called the key and value type,
Upon creation, a map is empty and values may be added and removed respectively. Upon creation, a map is empty and values may be added and removed
during execution. The number of entries in a map is called its length. during execution. The number of entries in a map is called its length.
MapType = "map" "[" KeyType "]" ValueType . MapType = "map" "[" KeyType "]" ValueType .
KeyType = Type . KeyType = CompleteType .
ValueType = Type . ValueType = CompleteType .
map [string] int map [string] int
map [struct { pid int; name string }] *chan Buffer map [struct { pid int; name string }] *chan Buffer
@ -1138,7 +1190,8 @@ Channel types
---- ----
A channel provides a mechanism for two concurrently executing functions A channel provides a mechanism for two concurrently executing functions
to synchronize execution and exchange values of a specified type. to synchronize execution and exchange values of a specified type. This
type must be a complete type (§Types).
Upon creation, a channel can be used both to send and to receive. Upon creation, a channel can be used both to send and to receive.
By conversion or assignment, a 'full' channel may be constrained only to send or By conversion or assignment, a 'full' channel may be constrained only to send or
@ -1210,12 +1263,12 @@ Type interfaces may be specified explicitly by interface types.
An interface type denotes the set of all types that implement at least 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". the set of methods specified by the interface type, and the value "nil".
InterfaceType = "interface" "{" [ MethodList [ ";" ] ] "}" . InterfaceType = "interface" [ "{" [ MethodList [ ";" ] ] "}" ] .
MethodList = MethodSpec { ";" MethodSpec } . MethodList = MethodSpec { ";" MethodSpec } .
MethodSpec = identifier FunctionType . MethodSpec = identifier FunctionType .
// A basic file interface. // A basic file interface.
type File interface { interface {
Read(b Buffer) bool; Read(b Buffer) bool;
Write(b Buffer) bool; Write(b Buffer) bool;
Close(); Close();
@ -1252,6 +1305,26 @@ and S1 and S2 also implement
they implement the Lock interface as well as the File interface. they implement the Lock interface as well as the File interface.
Forward declaration:
A interface type consisting of only the reserved word "interface" may be used in
a type declaration; it declares an incomplete interface type (§Type declarations).
This allows the construction of mutually recursive types such as:
type T2 interface
type T1 interface {
foo(T2) int;
}
type T2 interface {
bar(T1) int;
}
Type equivalence: Two interface types are equal only if both declare the same
number of methods with the same names, and corresponding (by name) methods
have the same function types.
Assignment compatibility: A value can be assigned to an interface variable
if the static type of the value implements the interface.
Expressions Expressions
---- ----
@ -1401,10 +1474,12 @@ TODO: Consider adding helper syntax for nested composites
Function Literals Function Literals
---- ----
Function literals represent anonymous functions. A function literal represents an anonymous function. It consists of a
specification of the function type and the function body. The parameter
and result types of the function type must all be complete types (§Types).
FunctionLit = "func" FunctionType Block . FunctionLit = "func" FunctionType Block .
Block = "{" [ StatementList [ ";" ] ] "}" . Block = "{" [ StatementList ] "}" .
The type of a function literal is a pointer to the function type. The type of a function literal is a pointer to the function type.
@ -1452,6 +1527,10 @@ Given a pointer p to a struct, one writes
p.f p.f
to access field f of the struct. to access field f of the struct.
TODO: Complete this section:
- type rules
- conflict resolution rules for anonymous fields
Indexes Indexes
---- ----
@ -1460,6 +1539,8 @@ Given an array or map pointer, one writes
p[i] p[i]
to access an element. to access an element.
TODO: Complete this section:
Slices Slices
---- ----
@ -1847,21 +1928,21 @@ Statements
Statements control execution. Statements control execution.
Statement = Statement =
Declaration | LabelDecl | ( SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat |
SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat | Block | IfStat | SwitchStat | SelectStat | ForStat | RangeStat )
Block | IfStat | SwitchStat | SelectStat | ForStat | RangeStat | OptSemicolon .
SimpleStat = SimpleStat =
ExpressionStat | IncDecStat | Assignment | SimpleVarDecl . ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
Semicolons are used to separate individual statements of a statement list. DeclOrStat =
They are optional immediately before or after a closing curly brace "}", Declaration | LabelDecl | Statement .
immediately after "++" or "--", and immediately before a reserved word.
StatementList = Statement { [ ";" ] Statement } . StatementList = DeclOrStat { DeclOrStat } .
Note that for the purpose of optional semicolons, a label declaration is neither
TODO: This still seems to be more complicated then necessary. a declaration nor a statement. Specifically, no semicolon is allowed immediately
after a label declaration.
Label declarations Label declarations
@ -2005,7 +2086,7 @@ Switch statements
Switches provide multi-way execution. Switches provide multi-way execution.
SwitchStat = "switch" [ [ Simplestat ] ";" ] [ Expression ] "{" { CaseClause } "}" . SwitchStat = "switch" [ [ Simplestat ] ";" ] [ Expression ] "{" { CaseClause } "}" .
CaseClause = Case [ StatementList [ ";" ] ] [ "fallthrough" [ ";" ] ] . CaseClause = Case [ StatementList ] [ "fallthrough" OptSemicolon ] .
Case = ( "case" ExpressionList | "default" ) ":" . Case = ( "case" ExpressionList | "default" ) ":" .
There can be at most one default case in a switch statement. There can be at most one default case in a switch statement.
@ -2145,7 +2226,7 @@ will proceed. It looks similar to a switch statement but with the
cases all referring to communication operations. cases all referring to communication operations.
SelectStat = "select" "{" { CommClause } "}" . SelectStat = "select" "{" { CommClause } "}" .
CommClause = CommCase [ StatementList [ ";" ] ] . CommClause = CommCase [ StatementList ] .
CommCase = ( "default" | ( "case" ( SendExpr | RecvExpr) ) ) ":" . CommCase = ( "default" | ( "case" ( SendExpr | RecvExpr) ) ) ":" .
SendExpr = Expression "<-" Expression . SendExpr = Expression "<-" Expression .
RecvExpr = [ PrimaryExpr ( "=" | ":=" ) ] "<-" Expression . RecvExpr = [ PrimaryExpr ( "=" | ":=" ) ] "<-" Expression .
@ -2236,7 +2317,7 @@ the elements of the return value.
return -7.0, -4.0; return -7.0, -4.0;
} }
The second method to return values A second method to return values
is to use those names within the function as variables is to use those names within the function as variables
to be assigned explicitly; the return statement will then provide no to be assigned explicitly; the return statement will then provide no
values: values:
@ -2311,13 +2392,12 @@ is erroneous because the jump to label L skips the creation of v.
Function declarations Function declarations
---- ----
A function declaration binds an identifier to a function.
Functions contain declarations and statements. They may be Functions contain declarations and statements. They may be
recursive. Functions may be anonymous and appear as recursive. Except for forward declarations (see below), the parameter
literals in expressions. and result types of the function type must all be complete types (§Type declarations).
A function declaration declares an identifier of type function. FunctionDecl = "func" identifier FunctionType [ Block ] .
FunctionDecl = "func" identifier FunctionType ( ";" | Block ) .
func min(x int, y int) int { func min(x int, y int) int {
if x < y { if x < y {
@ -2328,7 +2408,7 @@ A function declaration declares an identifier of type function.
A function declaration without a block serves as a forward declaration: A function declaration without a block serves as a forward declaration:
func MakeNode(left, right *Node) *Node; func MakeNode(left, right *Node) *Node
Implementation restrictions: Functions can only be declared at the global level. Implementation restrictions: Functions can only be declared at the global level.
@ -2344,9 +2424,9 @@ as a type name, or as a pointer to a type name. The type specified by the
type name is called ``receiver base type''. The receiver base type must be a type name is called ``receiver base type''. The receiver base type must be a
type declared in the current file, and it must not be a pointer type. type declared in the current file, and it must not be a pointer type.
The method is said to be ``bound'' to the receiver base type; specifically The method is said to be ``bound'' to the receiver base type; specifically
it is declared within the scope of that type (§Types). it is declared within the scope of that type (§Type declarations).
MethodDecl = "func" Receiver identifier FunctionType ( ";" | Block ) . MethodDecl = "func" Receiver identifier FunctionType [ Block ] .
Receiver = "(" identifier [ "*" ] TypeName ")" . Receiver = "(" identifier [ "*" ] TypeName ")" .
All methods bound to a receiver base type must have the same receiver type: All methods bound to a receiver base type must have the same receiver type:
@ -2484,7 +2564,7 @@ Packages
A package is a package clause, optionally followed by import declarations, A package is a package clause, optionally followed by import declarations,
followed by a series of declarations. followed by a series of declarations.
Package = PackageClause { ImportDecl [ ";" ] } { Declaration [ ";" ] } . Package = PackageClause { ImportDecl OptSemicolon } { Declaration } .
The source text following the package clause acts like a block for scoping The source text following the package clause acts like a block for scoping
purposes ($Declarations and scope rules). purposes ($Declarations and scope rules).
@ -2500,9 +2580,9 @@ The file must begin with a package clause.
A package can gain access to exported items from another package A package can gain access to exported items from another package
through an import declaration: through an import declaration:
ImportDecl = "import" ( ImportSpec | "(" ImportSpecList [ ";" ] ")" ) . ImportDecl = "import" ( ImportSpec | "(" ImportSpecList ")" ) .
ImportSpec = [ "." | PackageName ] PackageFileName . ImportSpec = [ "." | PackageName ] PackageFileName .
ImportSpecList = ImportSpec { ";" ImportSpec } . ImportSpecList = ImportSpec OptSemicolon { ImportSpec OptSemicolon } .
An import statement makes the exported contents of the named An import statement makes the exported contents of the named
package file accessible in this package. package file accessible in this package.