mirror of
https://github.com/golang/go
synced 2024-11-22 05:54:40 -07:00
- language to define type equality rigorously
- language for type guards - fixed language for break statements Also: Removed uses of "we" and replaced by impersonal language. Minor cosmetic changes. DELTA=237 (160 added, 34 deleted, 43 changed) OCL=18620 CL=18800
This commit is contained in:
parent
f8d7f5bd81
commit
434c6052d8
274
doc/go_spec.txt
274
doc/go_spec.txt
@ -4,7 +4,7 @@ The Go Programming Language Specification (DRAFT)
|
|||||||
Robert Griesemer, Rob Pike, Ken Thompson
|
Robert Griesemer, Rob Pike, Ken Thompson
|
||||||
|
|
||||||
----
|
----
|
||||||
(November 4, 2008)
|
(November 7, 2008)
|
||||||
|
|
||||||
|
|
||||||
This document is a semi-formal specification of the Go systems
|
This document is a semi-formal specification of the Go systems
|
||||||
@ -157,6 +157,7 @@ Contents
|
|||||||
Channel types
|
Channel types
|
||||||
Function types
|
Function types
|
||||||
Interface types
|
Interface types
|
||||||
|
Type equality
|
||||||
|
|
||||||
Expressions
|
Expressions
|
||||||
Operands
|
Operands
|
||||||
@ -289,15 +290,15 @@ implementation, Go treats these as distinct characters.
|
|||||||
Characters
|
Characters
|
||||||
----
|
----
|
||||||
|
|
||||||
In the grammar we use the notation
|
In the grammar the term
|
||||||
|
|
||||||
utf8_char
|
utf8_char
|
||||||
|
|
||||||
to refer to an arbitrary Unicode code point encoded in UTF-8. We use
|
denotes an arbitrary Unicode code point encoded in UTF-8. Similarly,
|
||||||
|
|
||||||
non_ascii
|
non_ascii
|
||||||
|
|
||||||
to refer to the subset of "utf8_char" code points with values >= 128.
|
denotes the subset of "utf8_char" code points with values >= 128.
|
||||||
|
|
||||||
|
|
||||||
Letters and digits
|
Letters and digits
|
||||||
@ -719,6 +720,7 @@ Type declarations
|
|||||||
----
|
----
|
||||||
|
|
||||||
A type declaration specifies a new type and binds an identifier to it.
|
A type declaration specifies a new type and binds an identifier to it.
|
||||||
|
The identifier is called the ``type name''; it denotes the type.
|
||||||
|
|
||||||
TypeDecl = "type" Decl<TypeSpec> .
|
TypeDecl = "type" Decl<TypeSpec> .
|
||||||
TypeSpec = identifier Type .
|
TypeSpec = identifier Type .
|
||||||
@ -834,17 +836,23 @@ TODO: export as a mechanism for public and private struct fields?
|
|||||||
Types
|
Types
|
||||||
----
|
----
|
||||||
|
|
||||||
A type specifies the set of values that variables of that type may
|
A type specifies the set of values that variables of that type may assume
|
||||||
assume, and the operators that are applicable.
|
and the operators that are applicable.
|
||||||
|
|
||||||
There are basic types and composite types. Basic types are predeclared.
|
A type may be specified by a type name (§Type declarations)
|
||||||
Composite types are arrays, maps, channels, structures, functions, pointers,
|
or a type literal.
|
||||||
and interfaces. They are constructed from other (basic or composite) types.
|
|
||||||
|
|
||||||
Type =
|
Type = TypeName | TypeLit .
|
||||||
TypeName | ArrayType | ChannelType | InterfaceType |
|
|
||||||
FunctionType | MapType | StructType | PointerType .
|
|
||||||
TypeName = QualifiedIdent.
|
TypeName = QualifiedIdent.
|
||||||
|
TypeLit =
|
||||||
|
ArrayType | StructType | PointerType | FunctionType |
|
||||||
|
ChannelType | MapType | InterfaceType .
|
||||||
|
|
||||||
|
There are basic types and composite types. Basic types are predeclared and
|
||||||
|
denoted by their type names.
|
||||||
|
Composite types are arrays, maps, channels, structures, functions, pointers,
|
||||||
|
and interfaces. They are constructed from other (basic or composite) types
|
||||||
|
and denoted by their type names or by type literals.
|
||||||
|
|
||||||
Types may be ``complete'' or ''incomplete''. Basic, pointer, function and
|
Types may be ``complete'' or ''incomplete''. Basic, pointer, function and
|
||||||
interface types are always complete (although their components, such
|
interface types are always complete (although their components, such
|
||||||
@ -868,7 +876,7 @@ 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 run-time. Except for variables of
|
||||||
interface type, the dynamic type of a variable is always its static type.
|
interface type, the dynamic type of a variable is always its static type.
|
||||||
|
|
||||||
Variables of interface type may hold values with different dynamic types
|
Variables of interface type may hold values with different dynamic types
|
||||||
@ -978,10 +986,6 @@ If the length is present in the declaration, the array is called
|
|||||||
ArrayLength = Expression .
|
ArrayLength = Expression .
|
||||||
ElementType = CompleteType .
|
ElementType = CompleteType .
|
||||||
|
|
||||||
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
|
|
||||||
are open arrays.
|
|
||||||
|
|
||||||
The length of an array "a" can be discovered using the built-in function
|
The length of an array "a" can be discovered using the built-in function
|
||||||
|
|
||||||
len(a)
|
len(a)
|
||||||
@ -1169,11 +1173,6 @@ This allows the construction of mutually recursive types such as:
|
|||||||
type S1 struct { s2 *S2 }
|
type S1 struct { s2 *S2 }
|
||||||
type S2 struct { s1 *S1 }
|
type S2 struct { s1 *S1 }
|
||||||
|
|
||||||
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
|
|
||||||
anonymous, and the corresponding field types are equal. Specifically,
|
|
||||||
field names don't have to match.
|
|
||||||
|
|
||||||
Assignment compatibility: Structs are assignment compatible to variables of
|
Assignment compatibility: Structs are assignment compatible to variables of
|
||||||
equal type only.
|
equal type only.
|
||||||
|
|
||||||
@ -1201,9 +1200,6 @@ such as:
|
|||||||
type S1 struct { s2 *S2 }
|
type S1 struct { s2 *S2 }
|
||||||
type S2 struct { s1 *S1 }
|
type S2 struct { s1 *S1 }
|
||||||
|
|
||||||
Type equality: Two pointer types are equal only if both have equal
|
|
||||||
base types.
|
|
||||||
|
|
||||||
Assignment compatibility: A pointer is assignment compatible to a variable
|
Assignment compatibility: A pointer is assignment compatible to a variable
|
||||||
of pointer type, only if both types are equal.
|
of pointer type, only if both types are equal.
|
||||||
|
|
||||||
@ -1235,9 +1231,6 @@ Allocation: A map may only be used as a base type of a pointer type.
|
|||||||
There are no variables, parameters, array, struct, or map fields of
|
There are no variables, parameters, array, struct, or map fields of
|
||||||
map type, only of pointers to maps.
|
map type, only of pointers to maps.
|
||||||
|
|
||||||
Type equivalence: Two map types are equal only if both have equal
|
|
||||||
key and value types.
|
|
||||||
|
|
||||||
Assignment compatibility: A pointer to a map type is assignment
|
Assignment compatibility: A pointer to a map type is assignment
|
||||||
compatible to a variable of pointer to map type only if both types
|
compatible to a variable of pointer to map type only if both types
|
||||||
are equal.
|
are equal.
|
||||||
@ -1251,17 +1244,18 @@ to synchronize execution and exchange values of a specified type. This
|
|||||||
type must be a complete type (§Types).
|
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 channel may be constrained only to send or
|
||||||
to receive. Such a restricted channel is called a 'send channel' or a 'receive channel'.
|
to receive. This constraint is called a channel's ``direction''; either
|
||||||
|
bi-directional (unconstrained), send, or receive.
|
||||||
|
|
||||||
ChannelType = FullChannel | SendChannel | RecvChannel .
|
ChannelType = Channel | SendChannel | RecvChannel .
|
||||||
FullChannel = "chan" ValueType .
|
Channel = "chan" ValueType .
|
||||||
SendChannel = "chan" "<-" ValueType .
|
SendChannel = "chan" "<-" ValueType .
|
||||||
RecvChannel = "<-" "chan" ValueType .
|
RecvChannel = "<-" "chan" ValueType .
|
||||||
|
|
||||||
chan T // a channel that can exchange values of type T
|
chan T // can send and receive values of type T
|
||||||
chan <- float // a channel that can only be used to send floats
|
chan <- float // can only be used to send floats
|
||||||
<-chan int // a channel that can receive only ints
|
<-chan int // can receive only ints
|
||||||
|
|
||||||
Channel variables always have type pointer to channel.
|
Channel variables always have type pointer to channel.
|
||||||
It is an error to attempt to use a channel value and in
|
It is an error to attempt to use a channel value and in
|
||||||
@ -1311,11 +1305,6 @@ In particular, v := func() {} creates a variable of type *(). To call the
|
|||||||
function referenced by v, one writes v(). It is illegal to dereference a
|
function referenced by v, one writes v(). It is illegal to dereference a
|
||||||
function pointer.
|
function pointer.
|
||||||
|
|
||||||
Type equality: Two function types are equal if both have the same number
|
|
||||||
of parameters and result values and if corresponding parameter and result
|
|
||||||
types are equal. In particular, the parameter and result names are ignored
|
|
||||||
for the purpose of type equivalence.
|
|
||||||
|
|
||||||
Assignment compatibility: A function pointer can be assigned to a function
|
Assignment compatibility: A function pointer can be assigned to a function
|
||||||
(pointer) variable only if both function types are equal.
|
(pointer) variable only if both function types are equal.
|
||||||
|
|
||||||
@ -1337,9 +1326,9 @@ the set of methods specified by the interface type, and the value "nil".
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Any type whose interface has, possibly as a subset, the complete
|
Any type (including interface types) whose interface has, possibly as a
|
||||||
set of methods of an interface I is said to implement interface I.
|
subset, the complete set of methods of an interface I is said to implement
|
||||||
For instance, if two types S1 and S2 have the methods
|
interface I. For instance, if two types S1 and S2 have the methods
|
||||||
|
|
||||||
func (p T) Read(b Buffer) bool { return ... }
|
func (p T) Read(b Buffer) bool { return ... }
|
||||||
func (p T) Write(b Buffer) bool { return ... }
|
func (p T) Write(b Buffer) bool { return ... }
|
||||||
@ -1354,14 +1343,14 @@ All types implement the empty interface:
|
|||||||
interface {}
|
interface {}
|
||||||
|
|
||||||
In general, a type implements an arbitrary number of interfaces.
|
In general, a type implements an arbitrary number of interfaces.
|
||||||
For instance, if we have
|
For instance, consider the interface
|
||||||
|
|
||||||
type Lock interface {
|
type Lock interface {
|
||||||
lock();
|
lock();
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
and S1 and S2 also implement
|
If S1 and S2 also implement
|
||||||
|
|
||||||
func (p T) lock() { ... }
|
func (p T) lock() { ... }
|
||||||
func (p T) unlock() { ... }
|
func (p T) unlock() { ... }
|
||||||
@ -1381,14 +1370,120 @@ This allows the construction of mutually recursive types such as:
|
|||||||
bar(T1) int;
|
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
|
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".
|
if the static type of the value implements the interface or if the value is "nil".
|
||||||
|
|
||||||
|
|
||||||
|
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 structually
|
||||||
|
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:
|
||||||
|
|
||||||
|
- Two array types are equal if they have equal element types and if they
|
||||||
|
are either fixed arrays with the same array length, or they are open
|
||||||
|
arrays.
|
||||||
|
|
||||||
|
- Two struct types are equal if they have the same number of fields in the
|
||||||
|
same order, corresponding fields are either both named or both anonymous,
|
||||||
|
and corresponding field types are equal. Note that field names
|
||||||
|
do not have to match.
|
||||||
|
|
||||||
|
- Two pointer types are equal if they have equal base types.
|
||||||
|
|
||||||
|
- Two function types are equal if they have the same number of parameters
|
||||||
|
and result values and if corresponding parameter and result types are
|
||||||
|
equal (a "..." parameter is equal to another "..." parameter).
|
||||||
|
Note that parameter and result names do not have to match.
|
||||||
|
|
||||||
|
- Two channel types are equal if they have equal value types and
|
||||||
|
the same direction.
|
||||||
|
|
||||||
|
- Two map types are equal if they have equal key and value types.
|
||||||
|
|
||||||
|
- Two interface types are equal if they have the same set of methods
|
||||||
|
with the same names and equal function types. Note that the order
|
||||||
|
of the methods in the respective type declarations is irrelevant.
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
- Two array types are identical if they have identical element types and if
|
||||||
|
they are either fixed arrays with the same array length, or they are open
|
||||||
|
arrays.
|
||||||
|
|
||||||
|
- Two struct types are identical if they have the same number of fields in
|
||||||
|
the same order, corresponding fields either have both the same name or
|
||||||
|
are both anonymous, and corresponding field types are identical.
|
||||||
|
|
||||||
|
- Two pointer types are identical if they have identical base types.
|
||||||
|
|
||||||
|
- Two function types are identical if they have the same number of
|
||||||
|
parameters and result values both with the same (or absent) names, and
|
||||||
|
if corresponding parameter and result types are identical (a "..."
|
||||||
|
parameter is identical to another "..." parameter with the same name).
|
||||||
|
|
||||||
|
- Two channel types are identical if they have identical value types and
|
||||||
|
the same direction.
|
||||||
|
|
||||||
|
- Two map types are identical if they have identical key and value types.
|
||||||
|
|
||||||
|
- Two interface types are identical if they have the same set of methods
|
||||||
|
with the same names and identical function types. Note that the order
|
||||||
|
of the methods in the respective type declarations is irrelevant.
|
||||||
|
|
||||||
|
Note that the type denoted by a type name is identical only to the type literal
|
||||||
|
in the type name's declaration.
|
||||||
|
|
||||||
|
Finally, two types are different if they are not structurally equal.
|
||||||
|
(By definition, they cannot be identical, either).
|
||||||
|
|
||||||
|
For instance, given the declarations
|
||||||
|
|
||||||
|
type (
|
||||||
|
T0 []string;
|
||||||
|
T1 []string
|
||||||
|
T2 struct { a, b int };
|
||||||
|
T3 struct { a, c int };
|
||||||
|
T4 *(int, float) *T0
|
||||||
|
T5 *(x int, y float) *[]string
|
||||||
|
)
|
||||||
|
|
||||||
|
these are some types that are equal
|
||||||
|
|
||||||
|
T0 and T0
|
||||||
|
T0 and []string
|
||||||
|
T2 and T3
|
||||||
|
T4 and T5
|
||||||
|
T3 and struct { a int; int }
|
||||||
|
|
||||||
|
and these are some types that are identical
|
||||||
|
|
||||||
|
T0 and T0
|
||||||
|
[]int and []int
|
||||||
|
struct { a, b *T5 } and struct { a, b *T5 }
|
||||||
|
|
||||||
|
As an example, "T0" and "T1" are equal but not identical because they have
|
||||||
|
different declarations.
|
||||||
|
|
||||||
|
|
||||||
Expressions
|
Expressions
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -1511,7 +1606,7 @@ Given
|
|||||||
type Rat struct { num, den int };
|
type Rat struct { num, den int };
|
||||||
type Num struct { r Rat; f float; s string };
|
type Num struct { r Rat; f float; s string };
|
||||||
|
|
||||||
we can write
|
one can write
|
||||||
|
|
||||||
pi := Num{Rat{22, 7}, 3.14159, "pi"};
|
pi := Num{Rat{22, 7}, 3.14159, "pi"};
|
||||||
|
|
||||||
@ -1576,7 +1671,7 @@ Primary expressions
|
|||||||
Selector = "." identifier .
|
Selector = "." identifier .
|
||||||
Index = "[" Expression "]" .
|
Index = "[" Expression "]" .
|
||||||
Slice = "[" Expression ":" Expression "]" .
|
Slice = "[" Expression ":" Expression "]" .
|
||||||
TypeGuard = "." "(" QualifiedIdent ")" .
|
TypeGuard = "." "(" Type ")" .
|
||||||
Call = "(" [ ExpressionList ] ")" .
|
Call = "(" [ ExpressionList ] ")" .
|
||||||
|
|
||||||
|
|
||||||
@ -1660,7 +1755,7 @@ declarations:
|
|||||||
|
|
||||||
var p *T2; // with p != nil and p.T1 != nil
|
var p *T2; // with p != nil and p.T1 != nil
|
||||||
|
|
||||||
we can write:
|
one can write:
|
||||||
|
|
||||||
p.z // (*p).z
|
p.z // (*p).z
|
||||||
p.y // ((*p).T1).y
|
p.y // ((*p).T1).y
|
||||||
@ -1734,7 +1829,41 @@ would have no effect on ``a''.
|
|||||||
Type guards
|
Type guards
|
||||||
----
|
----
|
||||||
|
|
||||||
TODO: write this section
|
For an expression "x" and a type "T", the primary expression
|
||||||
|
|
||||||
|
x.(T)
|
||||||
|
|
||||||
|
asserts that the value stored in "x" is an element of type "T" (§Types).
|
||||||
|
The notation ".(T)" is called a ``type guard'', and "x.(T)" is called
|
||||||
|
a ``guarded expression''. The type of "x" must be an interface type.
|
||||||
|
|
||||||
|
More precisely, if "T" is not an interface type, the expression asserts
|
||||||
|
that the dynamic type of "x" is identical to the type "T" (§Types).
|
||||||
|
If "T" is an interface type, the expression asserts that the dynamic type
|
||||||
|
of T implements the interface "T" (§Interface types). Because it can be
|
||||||
|
verified statically, a type guard in which the static type of "x" implements
|
||||||
|
the interface "T" is illegal. The type guard is said to succeed if the
|
||||||
|
assertion holds.
|
||||||
|
|
||||||
|
If the type guard succeeds, the value of the guarded expression is the value
|
||||||
|
stored in "x" and its type is "T". If the type guard fails, a run-time
|
||||||
|
exception occurs. In other words, even though the dynamic type of "x"
|
||||||
|
is only known at run-time, the type of the guarded expression "x.(T)" is
|
||||||
|
known to be "T" in a correct program.
|
||||||
|
|
||||||
|
As a special form, if a guarded expression is used in an assignment
|
||||||
|
|
||||||
|
v, ok = x.(T)
|
||||||
|
v, ok := x.(T)
|
||||||
|
|
||||||
|
the result of the guarded expression is a pair of values with types "(T, bool)".
|
||||||
|
If the type guard succeeds, the expression returns the pair "(x.(T), true)";
|
||||||
|
that is, the value stored in "x" (of type "T") is assigned to "v", and "ok"
|
||||||
|
is set to true. If the type guard fails, the value in "v" is set to the initial
|
||||||
|
value for the type of "v" (§Program initialization and execution), and "ok" is
|
||||||
|
set to false. No run-time exception occurs in this case.
|
||||||
|
|
||||||
|
TODO add examples
|
||||||
|
|
||||||
|
|
||||||
Calls
|
Calls
|
||||||
@ -1773,7 +1902,7 @@ TODO expand this section (right now only "..." parameters are covered).
|
|||||||
|
|
||||||
Inside a function, the type of the "..." parameter is the empty interface
|
Inside a function, the type of the "..." parameter is the empty interface
|
||||||
"interface {}". The dynamic type of the parameter - that is, the type of
|
"interface {}". The dynamic type of the parameter - that is, the type of
|
||||||
the actual value stored in the parameter - is of the form (in pseudo-
|
the value stored in the parameter - is of the form (in pseudo-
|
||||||
notation)
|
notation)
|
||||||
|
|
||||||
*struct {
|
*struct {
|
||||||
@ -1791,7 +1920,7 @@ Thus, arguments provided in place of a "..." parameter are wrapped into
|
|||||||
a corresponding struct, and a pointer to the struct is passed to the
|
a corresponding struct, and a pointer to the struct is passed to the
|
||||||
function instead of the actual arguments.
|
function instead of the actual arguments.
|
||||||
|
|
||||||
For instance, given the function
|
For instance, consider the function
|
||||||
|
|
||||||
func f(x int, s string, f_extra ...)
|
func f(x int, s string, f_extra ...)
|
||||||
|
|
||||||
@ -1802,7 +1931,7 @@ and the call
|
|||||||
Upon invocation, the parameters "3.14", "true", and "*[3]int{1, 2, 3}"
|
Upon invocation, the parameters "3.14", "true", and "*[3]int{1, 2, 3}"
|
||||||
are wrapped into a struct and the pointer to the struct is passed to f.
|
are wrapped into a struct and the pointer to the struct is passed to f.
|
||||||
In f the type of parameter "f_extra" is "interface{}".
|
In f the type of parameter "f_extra" is "interface{}".
|
||||||
The dynamic type of "f_extra" is the type of the actual value assigned
|
The dynamic type of "f_extra" is the type of the value assigned
|
||||||
to it upon invocation (the field names "arg0", "arg1", "arg2" are made
|
to it upon invocation (the field names "arg0", "arg1", "arg2" are made
|
||||||
up for illustration only, they are not accessible via reflection):
|
up for illustration only, they are not accessible via reflection):
|
||||||
|
|
||||||
@ -1826,7 +1955,7 @@ as
|
|||||||
|
|
||||||
g(x, f_extra);
|
g(x, f_extra);
|
||||||
|
|
||||||
Inside g, the actual value stored in g_extra is the same as the value stored
|
Inside g, the value stored in g_extra is the same as the value stored
|
||||||
in f_extra.
|
in f_extra.
|
||||||
|
|
||||||
|
|
||||||
@ -2028,7 +2157,7 @@ pointer to function. Consider the type T with method M:
|
|||||||
func (tp *T) M(a int) int;
|
func (tp *T) M(a int) int;
|
||||||
var t *T;
|
var t *T;
|
||||||
|
|
||||||
To construct the address of method M, we write
|
To construct the address of method M, one writes
|
||||||
|
|
||||||
&t.M
|
&t.M
|
||||||
|
|
||||||
@ -2187,12 +2316,6 @@ In all other cases a semicolon is required to separate two statements. Since the
|
|||||||
is an empty statement, a statement list can always be ``terminated'' with a semicolon.
|
is an empty statement, a statement list can always be ``terminated'' with a semicolon.
|
||||||
|
|
||||||
|
|
||||||
Label declarations
|
|
||||||
----
|
|
||||||
|
|
||||||
TODO write this section
|
|
||||||
|
|
||||||
|
|
||||||
Empty statements
|
Empty statements
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -2584,14 +2707,14 @@ values:
|
|||||||
Break statements
|
Break statements
|
||||||
----
|
----
|
||||||
|
|
||||||
Within a for or switch statement, a break statement terminates execution of
|
Within a for, switch, or select statement, a break statement terminates
|
||||||
the innermost for or switch statement.
|
execution of the innermost such statement.
|
||||||
|
|
||||||
BreakStat = "break" [ identifier ].
|
BreakStat = "break" [ identifier ].
|
||||||
|
|
||||||
If there is an identifier, it must be the label name of an enclosing
|
If there is an identifier, it must be a label marking an enclosing
|
||||||
for or switch
|
for, switch, or select statement, and that is the one whose execution
|
||||||
statement, and that is the one whose execution terminates.
|
terminates.
|
||||||
|
|
||||||
L: for i < n {
|
L: for i < n {
|
||||||
switch i {
|
switch i {
|
||||||
@ -2611,13 +2734,15 @@ loop at the post statement.
|
|||||||
The optional identifier is analogous to that of a break statement.
|
The optional identifier is analogous to that of a break statement.
|
||||||
|
|
||||||
|
|
||||||
Label declaration
|
Label declarations
|
||||||
----
|
----
|
||||||
|
|
||||||
A label declaration serves as the target of a goto, break or continue statement.
|
A label declaration serves as the target of a goto, break or continue statement.
|
||||||
|
|
||||||
LabelDecl = identifier ":" .
|
LabelDecl = identifier ":" .
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
|
|
||||||
|
|
||||||
@ -2771,7 +2896,7 @@ yields a valid value; there is no signal for overflow.
|
|||||||
|
|
||||||
2) Between integer and floating point types, or between floating point
|
2) Between integer and floating point types, or between floating point
|
||||||
types. To avoid overdefining the properties of the conversion, for
|
types. To avoid overdefining the properties of the conversion, for
|
||||||
now we define it as a ``best effort'' conversion. The conversion
|
now it is defined as a ``best effort'' conversion. The conversion
|
||||||
always succeeds but the value may be a NaN or other problematic
|
always succeeds but the value may be a NaN or other problematic
|
||||||
result. TODO: clarify?
|
result. TODO: clarify?
|
||||||
|
|
||||||
@ -2801,7 +2926,8 @@ Allocation
|
|||||||
The built-in function "new()" takes a type "T", optionally followed by a
|
The built-in function "new()" takes a type "T", optionally followed by a
|
||||||
type-specific list of expressions. It allocates memory for a variable
|
type-specific list of expressions. It allocates memory for a variable
|
||||||
of type "T" and returns a pointer of type "*T" to that variable. The
|
of type "T" and returns a pointer of type "*T" to that variable. The
|
||||||
memory is initialized as described in the section on initial values.
|
memory is initialized as described in the section on initial values
|
||||||
|
(§Program initialization and execution).
|
||||||
|
|
||||||
new(type [, optional list of expressions])
|
new(type [, optional list of expressions])
|
||||||
|
|
||||||
@ -3095,7 +3221,7 @@ If a type defines all methods of an interface, it
|
|||||||
implements that interface and thus can be used where that interface is
|
implements that interface and thus can be used where that interface is
|
||||||
required. Unless used through a variable of interface type, methods
|
required. Unless used through a variable of interface type, methods
|
||||||
can always be statically bound (they are not ``virtual''), and incur no
|
can always be statically bound (they are not ``virtual''), and incur no
|
||||||
runtime overhead compared to an ordinary function.
|
run-time overhead compared to an ordinary function.
|
||||||
|
|
||||||
[OLD
|
[OLD
|
||||||
Interface types, building on structures with methods, provide
|
Interface types, building on structures with methods, provide
|
||||||
@ -3112,7 +3238,7 @@ structures. If a structure implements all methods of an interface, it
|
|||||||
implements that interface and thus can be used where that interface is
|
implements that interface and thus can be used where that interface is
|
||||||
required. Unless used through a variable of interface type, methods
|
required. Unless used through a variable of interface type, methods
|
||||||
can always be statically bound (they are not ``virtual''), and incur no
|
can always be statically bound (they are not ``virtual''), and incur no
|
||||||
runtime overhead compared to an ordinary function.
|
run-time overhead compared to an ordinary function.
|
||||||
END]
|
END]
|
||||||
|
|
||||||
Go has no explicit notion of classes, sub-classes, or inheritance.
|
Go has no explicit notion of classes, sub-classes, or inheritance.
|
||||||
|
Loading…
Reference in New Issue
Block a user