From f154da9e12608589e8d5f0508f908a0c3e88a1bb Mon Sep 17 00:00:00 2001
From: Tianon Gravi ""
. The text between the quotes,
which may not contain newlines, forms the
value of the literal, with backslash escapes interpreted as they
-are in rune literals (except that \'
is illegal and
+are in rune literals (except that \'
is illegal and
\"
is legal), with the same restrictions.
The three-digit octal (\
nnn)
and two-digit hexadecimal (\x
nn) escapes represent individual
@@ -577,7 +577,7 @@ Numeric constants represent values of arbitrary precision and do not overflow.
-Constants may be typed or untyped.
+Constants may be typed or untyped.
Literal constants, true
, false
, iota
,
and certain constant expressions
containing only untyped constant operands are untyped.
@@ -597,6 +597,17 @@ can be given the types float32
, float64
, or uint
not
int32
or string
.
+An untyped constant has a default type which is the type to which the
+constant is implicitly converted in contexts where a typed value is required,
+for instance, in a short variable declaration
+such as i := 0
where there is no explicit type.
+The default type of an untyped constant is bool
, rune
,
+int
, float64
, complex128
or string
+respectively, depending on whether it is a boolean, rune, integer, floating-point,
+complex, or string constant.
+
There are no constants denoting the IEEE-754 infinity and not-a-number values,
but the math
package's
@@ -636,6 +647,65 @@ of evaluating constant
expressions.
+A variable is a storage location for holding a value. +The set of permissible values is determined by the +variable's type. +
+ +
+A variable declaration
+or, for function parameters and results, the signature
+of a function declaration
+or function literal reserves
+storage for a named variable.
+
+Calling the built-in function new
+or taking the address of a composite literal
+allocates storage for a variable at run time.
+Such an anonymous variable is referred to via a (possibly implicit)
+pointer indirection.
+
+Structured variables of array, slice, +and struct types have elements and fields that may +be addressed individually. Each such element +acts like a variable. +
+ +
+The static type (or just type) of a variable is the
+type given in its declaration, the type provided in the
+new
call or composite literal, or the type of
+an element of a structured variable.
+Variables of interface type also have a distinct dynamic type,
+which is the concrete type of the value assigned to the variable at run time
+(unless the value is the predeclared identifier nil
,
+which has no type).
+The dynamic type may vary during execution but values stored in interface
+variables are always assignable
+to the static type of the variable.
+
+var x interface{} // x is nil and has static type interface{} +var v *T // v has value nil, static type *T +x = 42 // x has value 42 and dynamic type int +x = v // x has value (*T)(nil) and dynamic type *T ++ +
+A variable's value is retrieved by referring to the variable in an +expression; it is the most recent value +assigned to the variable. +If a variable has not yet been assigned a value, its value is the +zero value for its type. +
+ +@@ -661,17 +731,6 @@ interface, slice, map, and channel types—may be constructed using type literals.
--The static type (or just type) of a variable is the -type defined by its declaration. Variables of interface type -also have a distinct dynamic type, which -is the actual type of the value stored in the variable at run time. -The dynamic type may vary during execution but is always -assignable -to the static type of the interface variable. For non-interface -types, the dynamic type is always the static type. -
-
Each type T
has an underlying type: If T
is one of the predeclared boolean, numeric, or string types, or a type literal,
@@ -1027,14 +1086,14 @@ struct {
-A pointer type denotes the set of all pointers to variables of a given
+A pointer type denotes the set of all pointers to variables of a given
type, called the base type of the pointer.
The value of an uninitialized pointer is nil
.
PointerType = "*" BaseType . -BaseType = Type . +BaseType = Type .
@@ -1154,11 +1213,11 @@ interface{}Similarly, consider this interface specification, which appears within a type declaration -to define an interface called
Lock
: +to define an interface calledLocker
:-type Lock interface { +type Locker interface { Lock() Unlock() } @@ -1174,28 +1233,35 @@ func (p T) Unlock() { … }-they implement the
+Lock
interface as well +they implement theLocker
interface as well as theFile
interface.-An interface may use an interface type name
T
-in place of a method specification. -The effect, called embedding an interface, -is equivalent to enumerating the methods ofT
explicitly -in the interface. +An interfaceT
may use a (possibly qualified) interface type +nameE
in place of a method specification. This is called +embedding interfaceE
inT
; it adds +all (exported and non-exported) methods ofE
to the interface +T
.-type ReadWrite interface { +type ReadWriter interface { Read(b Buffer) bool Write(b Buffer) bool } type File interface { - ReadWrite // same as enumerating the methods in ReadWrite - Lock // same as enumerating the methods in Lock + ReadWriter // same as adding the methods of ReadWriter + Locker // same as adding the methods of Locker Close() } + +type LockedFile interface { + Locker + File // illegal: Lock, Unlock not unique + Lock() // illegal: Lock not unique +}@@ -1443,7 +1509,7 @@ is different from
[]string
.Assignability
-A value
@@ -1875,9 +1941,10 @@ func (tz TimeZone) String() string {x
is assignable to a variable of typeT
+A valuex
is assignable to a variable of typeT
("x
is assignable toT
") in any of these cases:Variable declarations
-A variable declaration creates a variable, binds an identifier to it and -gives it a type and optionally an initial value. +A variable declaration creates one or more variables, binds corresponding +identifiers to them, and gives each a type and an initial value.
+VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) . VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) . @@ -1898,22 +1965,27 @@ var _, found = entries[name] // map lookup; only interested in "found"If a list of expressions is given, the variables are initialized -by assigning the expressions to the variables -in order; all expressions must be consumed and all variables initialized from them. +with the expressions following the rules for assignments. Otherwise, each variable is initialized to its zero value.
-If the type is present, each variable is given that type. -Otherwise, the types are deduced from the assignment -of the expression list. +If a type is present, each variable is given that type. +Otherwise, each variable is given the type of the corresponding +initialization value in the assignment. +If that value is an untyped constant, it is first +converted to its default type; +if it is an untyped boolean value, it is first converted to type
-bool
. +The predeclared valuenil
cannot be used to initialize a variable +with no explicit type.-If the type is absent and the corresponding expression evaluates to an -untyped constant, the type of the declared variable -is as described in §Assignments. -
++var d = math.Sin(0.5) // d is int64 +var i = 42 // i is int +var t, ok = x.(T) // t is T, ok is bool +var n = nil // illegal +Implementation restriction: A compiler may make it illegal to declare a variable @@ -2029,13 +2101,14 @@ and associates the method with the receiver's base type.
MethodDecl = "func" Receiver MethodName ( Function | Signature ) . -Receiver = "(" [ identifier ] [ "*" ] BaseTypeName ")" . -BaseTypeName = identifier . +Receiver = Parameters .-The receiver type must be of the form
T
or*T
where -T
is a type name. The type denoted byT
is called +The receiver is specified via an extra parameter section preceeding the method +name. That parameter section must declare a single parameter, the receiver. +Its type must be of the formT
or*T
(possibly using +parentheses) whereT
is a type name. The type denoted byT
is called the receiver base type; it must not be a pointer or interface type and it must be declared in the same package as the method. The method is said to be bound to the base type and the method name @@ -2117,9 +2190,9 @@ operand only on the left-hand side of an assignment.-Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . -Literal = BasicLit | CompositeLit | FunctionLit . -BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit . +Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . +Literal = BasicLit | CompositeLit | FunctionLit . +BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit . OperandName = identifier | QualifiedIdent.@@ -2241,7 +2314,8 @@ For array and slice literals the following rules apply:Taking the address of a composite literal -generates a pointer to a unique instance of the literal's value. +generates a pointer to a unique variable initialized +with the literal's value.
var pointer *Point3D = &Point3D{y: 1000} @@ -2375,12 +2449,11 @@ Primary expressions are the operands for unary and binary expressions. PrimaryExpr = Operand | Conversion | - BuiltinCall | PrimaryExpr Selector | PrimaryExpr Index | PrimaryExpr Slice | PrimaryExpr TypeAssertion | - PrimaryExpr Call . + PrimaryExpr Arguments . Selector = "." identifier . Index = "[" Expression "]" . @@ -2388,8 +2461,7 @@ Slice = "[" ( [ Expression ] ":" [ Expression ] ) | ( [ Expression ] ":" Expression ":" Expression ) "]" . TypeAssertion = "." "(" Type ")" . -Call = "(" [ ArgumentList [ "," ] ] ")" . -ArgumentList = ExpressionList [ "..." ] . +Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .@@ -2449,30 +2521,40 @@ The following rules apply to selectors:-
- For a value
+x
of typeT
or*T
-whereT
is not an interface type, +whereT
is not a pointer or interface type,x.f
denotes the field or method at the shallowest depth inT
where there is such anf
. If there is not exactly onef
with shallowest depth, the selector expression is illegal.- -For a variable
+ +x
of typeI
whereI
+For a valuex
of typeI
whereI
is an interface type,x.f
denotes the actual method with name -f
of the value assigned tox
. +f
of the dynamic value ofx
. If there is no method with namef
in the method set ofI
, the selector expression is illegal.- +As an exception, if the type of
+x
is a named pointer type +and(*x).f
is a valid selector expression denoting a field +(but not a method),x.f
is shorthand for(*x).f
. +- In all other cases,
+x.f
is illegal.- If
+x
is of pointer type and has the valuenil
andx.f
denotes a struct field, assigning to or evaluatingx.f
causes a run-time panic.- If
x
is of interface type and has the valuenil
, calling or @@ -2481,18 +2563,6 @@ causes a run-time panic.-Selectors automatically dereference -pointers to structs. -If
-x
is a pointer to a struct,x.y
-is shorthand for(*x).y
; if the fieldy
-is also a pointer to a struct,x.y.z
is shorthand -for(*(*x).y).z
, and so on. -Ifx
contains an anonymous field of type*A
, -whereA
is also a struct type, -x.f
is shorthand for(*x.A).f
. -For example, given the declarations:
@@ -2502,13 +2572,13 @@ type T0 struct { x int } -func (recv *T0) M0() +func (*T0) M0() type T1 struct { y int } -func (recv T1) M1() +func (T1) M1() type T2 struct { z int @@ -2516,9 +2586,13 @@ type T2 struct { *T0 } -func (recv *T2) M2() +func (*T2) M2() -var p *T2 // with p != nil and p.T0 != nil +type Q *T2 + +var t T2 // with t.T0 != nil +var p *T2 // with p != nil and (*p).T0 != nil +var q Q = p@@ -2526,13 +2600,254 @@ one may write:
-p.z // (*p).z -p.y // ((*p).T1).y -p.x // (*(*p).T0).x +t.z // t.z +t.y // t.T1.y +t.x // (*t.TO).x + +p.z // (*p).z +p.y // (*p).T1.y +p.x // (*(*p).T0).x + +q.x // (*(*q).T0).x (*q).x is a valid field selector + +p.M2() // p.M2() M2 expects *T2 receiver +p.M1() // ((*p).T1).M1() M1 expects T1 receiver +p.M0() // ((&(*p).T0)).M0() M0 expects *T0 receiver, see section on Calls ++ ++but the following is invalid: +
+ ++q.M0() // (*q).M0 is valid but not a field selector ++ + +Method expressions
+ ++If
+ +M
is in the method set of typeT
, +T.M
is a function that is callable as a regular function +with the same arguments asM
prefixed by an additional +argument that is the receiver of the method. ++MethodExpr = ReceiverType "." MethodName . +ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" . ++ ++Consider a struct type
+ +T
with two methods, +Mv
, whose receiver is of typeT
, and +Mp
, whose receiver is of type*T
. ++type T struct { + a int +} +func (tv T) Mv(a int) int { return 0 } // value receiver +func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver + +var t T ++ ++The expression +
+ ++T.Mv ++ ++yields a function equivalent to
+ +Mv
but +with an explicit receiver as its first argument; it has signature ++func(tv T, a int) int ++ ++That function may be called normally with an explicit receiver, so +these five invocations are equivalent: +
+ ++t.Mv(7) +T.Mv(t, 7) +(T).Mv(t, 7) +f1 := T.Mv; f1(t, 7) +f2 := (T).Mv; f2(t, 7) ++ ++Similarly, the expression +
+ ++(*T).Mp ++ ++yields a function value representing
+ +Mp
with signature ++func(tp *T, f float32) float32 ++ ++For a method with a value receiver, one can derive a function +with an explicit pointer receiver, so +
+ ++(*T).Mv ++ ++yields a function value representing
+ +Mv
with signature ++func(tv *T, a int) int ++ ++Such a function indirects through the receiver to create a value +to pass as the receiver to the underlying method; +the method does not overwrite the value whose address is passed in +the function call. +
+ ++The final case, a value-receiver function for a pointer-receiver method, +is illegal because pointer-receiver methods are not in the method set +of the value type. +
+ ++Function values derived from methods are called with function call syntax; +the receiver is provided as the first argument to the call. +That is, given
+ +f := T.Mv
,f
is invoked +asf(t, 7)
nott.f(7)
. +To construct a function that binds the receiver, use a +function literal or +method value. ++It is legal to derive a function value from a method of an interface type. +The resulting function takes an explicit receiver of that interface type. +
+ +Method values
+ ++If the expression
+ +x
has static typeT
and +M
is in the method set of typeT
, +x.M
is called a method value. +The method valuex.M
is a function value that is callable +with the same arguments as a method call ofx.M
. +The expressionx
is evaluated and saved during the evaluation of the +method value; the saved copy is then used as the receiver in any calls, +which may be executed later. ++The type
+ +T
may be an interface or non-interface type. ++As in the discussion of method expressions above, +consider a struct type
+ +T
with two methods, +Mv
, whose receiver is of typeT
, and +Mp
, whose receiver is of type*T
. ++type T struct { + a int +} +func (tv T) Mv(a int) int { return 0 } // value receiver +func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver + +var t T +var pt *T +func makeT() T ++ ++The expression +
+ ++t.Mv ++ ++yields a function value of type +
+ ++func(int) int ++ ++These two invocations are equivalent: +
+ ++t.Mv(7) +f := t.Mv; f(7) ++ ++Similarly, the expression +
+ ++pt.Mp ++ ++yields a function value of type +
+ ++func(float32) float32 +-p.M2() // (*p).M2() -p.M1() // ((*p).T1).M1() -p.M0() // ((*p).T0).M0() ++As with selectors, a reference to a non-interface method with a value receiver +using a pointer will automatically dereference that pointer:
+ +pt.Mv
is equivalent to(*pt).Mv
. ++As with method calls, a reference to a non-interface method with a pointer receiver +using an addressable value will automatically take the address of that value:
+ +t.Mp
is equivalent to(&t).Mp
. ++f := t.Mv; f(7) // like t.Mv(7) +f := pt.Mp; f(7) // like pt.Mp(7) +f := pt.Mv; f(7) // like (*pt).Mv(7) +f := t.Mp; f(7) // like (&t).Mp(7) +f := makeT().Mp // invalid: result of makeT() is not addressable ++ ++Although the examples above use non-interface types, it is also legal to create a method value +from a value of interface type. +
+ ++var i interface { M(int) } = myVal +f := i.M; f(7) // like i.M(7)@@ -2625,7 +2940,7 @@ Otherwisea[x]
is illegal.An index expression on a map
a
of typemap[K]V
-may be used in an assignment or initialization of the special form +used in an assignment or initialization of the special form@@ -2635,11 +2950,9 @@ var v, ok = a[x]-where the result of the index expression is a pair of values with types -
(V, bool)
. In this form, the value ofok
is +yields an additional untyped boolean value. The value ofok
istrue
if the keyx
is present in the map, and -false
otherwise. The value ofv
is the value -a[x]
as in the single-result form. +false
otherwise.@@ -2824,7 +3137,7 @@ r := y.(io.Reader) // r has type io.Reader and y must implement both I and i
-If a type assertion is used in an assignment or initialization of the form +A type assertion used in an assignment or initialization of the special form
@@ -2834,13 +3147,10 @@ var v, ok = x.(T)
-the result of the assertion is a pair of values with types (T, bool)
.
-If the assertion holds, the expression returns the pair (x.(T), true)
;
-otherwise, the expression returns (Z, false)
where Z
-is the zero value for type T
.
+yields an additional untyped boolean value. The value of ok
is true
+if the assertion holds. Otherwise it is false
and the value of v
is
+the zero value for type T
.
No run-time panic occurs in this case.
-The type assertion in this construct thus acts like a function call
-returning a value and a boolean indicating success.
math.Atan2(x, y) // function call var pt *Point -pt.Scale(3.5) // method call with receiver pt +pt.Scale(3.5) // method call with receiver pt
@@ -3375,13 +3685,13 @@ or an array indexing operation of an addressable array.
As an exception to the addressability requirement, x
may also be a
(possibly parenthesized)
composite literal.
-If the evaluation of x
would cause a run-time panic,
+If the evaluation of x
would cause a run-time panic,
then the evaluation of &x
does too.
For an operand x
of pointer type *T
, the pointer
-indirection *x
denotes the value of type T
pointed
+indirection *x
denotes the variable of type T
pointed
to by x
.
If x
is nil
, an attempt to evaluate *x
will cause a run-time panic.
@@ -3422,7 +3732,7 @@ f(<-ch)
-A receive expression used in an assignment or initialization of the form +A receive expression used in an assignment or initialization of the special form
@@ -3432,7 +3742,7 @@ var x, ok = <-ch
-yields an additional result of type bool
reporting whether the
+yields an additional untyped boolean result reporting whether the
communication succeeded. The value of ok
is true
if the value received was delivered by a successful send operation to the
channel, or false
if it is a zero value generated because the
@@ -3440,232 +3750,6 @@ channel is closed and empty.
-If M
is in the method set of type T
,
-T.M
is a function that is callable as a regular function
-with the same arguments as M
prefixed by an additional
-argument that is the receiver of the method.
-
-MethodExpr = ReceiverType "." MethodName . -ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" . -- -
-Consider a struct type T
with two methods,
-Mv
, whose receiver is of type T
, and
-Mp
, whose receiver is of type *T
.
-
-type T struct { - a int -} -func (tv T) Mv(a int) int { return 0 } // value receiver -func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver - -var t T -- -
-The expression -
- --T.Mv -- -
-yields a function equivalent to Mv
but
-with an explicit receiver as its first argument; it has signature
-
-func(tv T, a int) int -- -
-That function may be called normally with an explicit receiver, so -these five invocations are equivalent: -
- --t.Mv(7) -T.Mv(t, 7) -(T).Mv(t, 7) -f1 := T.Mv; f1(t, 7) -f2 := (T).Mv; f2(t, 7) -- -
-Similarly, the expression -
- --(*T).Mp -- -
-yields a function value representing Mp
with signature
-
-func(tp *T, f float32) float32 -- -
-For a method with a value receiver, one can derive a function -with an explicit pointer receiver, so -
- --(*T).Mv -- -
-yields a function value representing Mv
with signature
-
-func(tv *T, a int) int -- -
-Such a function indirects through the receiver to create a value -to pass as the receiver to the underlying method; -the method does not overwrite the value whose address is passed in -the function call. -
- --The final case, a value-receiver function for a pointer-receiver method, -is illegal because pointer-receiver methods are not in the method set -of the value type. -
- -
-Function values derived from methods are called with function call syntax;
-the receiver is provided as the first argument to the call.
-That is, given f := T.Mv
, f
is invoked
-as f(t, 7)
not t.f(7)
.
-To construct a function that binds the receiver, use a
-function literal or
-method value.
-
-It is legal to derive a function value from a method of an interface type. -The resulting function takes an explicit receiver of that interface type. -
- -
-If the expression x
has static type T
and
-M
is in the method set of type T
,
-x.M
is called a method value.
-The method value x.M
is a function value that is callable
-with the same arguments as a method call of x.M
.
-The expression x
is evaluated and saved during the evaluation of the
-method value; the saved copy is then used as the receiver in any calls,
-which may be executed later.
-
-The type T
may be an interface or non-interface type.
-
-As in the discussion of method expressions above,
-consider a struct type T
with two methods,
-Mv
, whose receiver is of type T
, and
-Mp
, whose receiver is of type *T
.
-
-type T struct { - a int -} -func (tv T) Mv(a int) int { return 0 } // value receiver -func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver - -var t T -var pt *T -func makeT() T -- -
-The expression -
- --t.Mv -- -
-yields a function value of type -
- --func(int) int -- -
-These two invocations are equivalent: -
- --t.Mv(7) -f := t.Mv; f(7) -- -
-Similarly, the expression -
- --pt.Mp -- -
-yields a function value of type -
- --func(float32) float32 -- -
-As with selectors, a reference to a non-interface method with a value receiver
-using a pointer will automatically dereference that pointer: pt.Mv
is equivalent to (*pt).Mv
.
-
-As with method calls, a reference to a non-interface method with a pointer receiver
-using an addressable value will automatically take the address of that value: t.Mp
is equivalent to (&t).Mp
.
-
-f := t.Mv; f(7) // like t.Mv(7) -f := pt.Mp; f(7) // like pt.Mp(7) -f := pt.Mv; f(7) // like (*pt).Mv(7) -f := t.Mp; f(7) // like (&t).Mp(7) -f := makeT().Mp // invalid: result of makeT() is not addressable -- -
-Although the examples above use non-interface types, it is also legal to create a method value -from a value of interface type. -
- --var i interface { M(int) } = myVal -f := i.M; f(7) // like i.M(7) --
@@ -4055,7 +4139,7 @@ n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}: evaluation order bet
At package level, initialization dependencies override the left-to-right rule for individual initialization expressions, but not for operands within each -expression: +expression:
@@ -4314,7 +4398,7 @@ a[i] = 23An assignment operation
x
op=
-y
where op is a binary arithmetic operation equivalent +y
where op is a binary arithmetic operation is equivalent tox
=
x
opy
but evaluatesx
only once. The op=
construct is a single token. @@ -4332,8 +4416,8 @@ i &^= 1<<n A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right hand operand is a single multi-valued expression -such as a function evaluation or channel or -map operation or a type assertion. +such as a function call, a channel or +map operation, or a type assertion. The number of operands on the left hand side must match the number of values. For instance, iff
is a function returning two values, @@ -4407,23 +4491,21 @@ to the type of the operand to which it is assigned, with the following special c-
- If an untyped constant +
- + Any typed value may be assigned to the blank identifier. +
+ +- + If an untyped constant is assigned to a variable of interface type or the blank identifier, - the constant is first converted to type -
- -bool
,rune
,int
,float64
, -complex128
orstring
respectively, depending on - whether the value is a boolean, rune, integer, floating-point, complex, or - string constant. -- + the constant is first converted to its + default type. + + +
- - If a left-hand side is the blank identifier, any typed or non-constant - value except for the predeclared identifier -
nil
- may be assigned to it. -- + If an untyped boolean value is assigned to a variable of interface type or + the blank identifier, it is first converted to type
bool
. +If statements
@@ -4678,6 +4760,7 @@ additionally it may specify an init and a post statement, such as an assignment, an increment or decrement statement. The init statement may be a short variable declaration, but the post statement must not. +Variables declared by the init statement are re-used in each iteration.@@ -4713,41 +4796,42 @@ for { S() } is the same as for true { S() } A "for" statement with a "range" clause iterates through all entries of an array, slice, string or map, or values received on a channel. For each entry it assigns iteration values -to corresponding iteration variables and then executes the block. +to corresponding iteration variables if present and then executes the block.-RangeClause = ( ExpressionList "=" | IdentifierList ":=" ) "range" Expression . +RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .The expression on the right in the "range" clause is called the range expression, which may be an array, pointer to an array, slice, string, map, or channel permitting receive operations. -As with an assignment, the operands on the left must be +As with an assignment, if present the operands on the left must be addressable or map index expressions; they -denote the iteration variables. If the range expression is a channel, only -one iteration variable is permitted, otherwise there may be one or two. In the latter case, -if the second iteration variable is the blank identifier, -the range clause is equivalent to the same clause with only the first variable present. +denote the iteration variables. If the range expression is a channel, at most +one iteration variable is permitted, otherwise there may be up to two. +If the last iteration variable is the blank identifier, +the range clause is equivalent to the same clause without that identifier.
The range expression is evaluated once before beginning the loop, -with one exception. If the range expression is an array or a pointer to an array -and only the first iteration value is present, only the range expression's -length is evaluated; if that length is constant -by definition, +with one exception: if the range expression is an array or a pointer to an array +and at most one iteration variable is present, only the range expression's +length is evaluated; if that length is constant, +by definition the range expression itself will not be evaluated.
Function calls on the left are evaluated once per iteration. -For each iteration, iteration values are produced as follows: +For each iteration, iteration values are produced as follows +if the respective iteration variables are present:
-Range expression 1st value 2nd value (if 2nd variable is present) +Range expression 1st value 2nd value array or slice a [n]E, *[n]E, or []E index i int a[i] E string s string type index i int see below rune @@ -4759,7 +4843,7 @@ channel c chan E, <-chan E element e E
a
, the index iteration
values are produced in increasing order, starting at element index 0.
-If only the first iteration variable is present, the range loop produces
+If at most one iteration variable is present, the range loop produces
iteration values from 0 up to len(a)-1
and does not index into the array
or slice itself. For a nil
slice, the number of iterations is 0.
:=
).
In this case their types are set to the types of the respective iteration values
-and their scope ends at the end of the "for"
+and their scope is the block of the "for"
statement; they are re-used in each iteration.
If the iteration variables are declared outside the "for" statement,
after execution their values will be those of the last iteration.
@@ -4840,6 +4924,9 @@ var ch chan Work = producer()
for w := range ch {
doWork(w)
}
+
+// empty a channel
+for range ch {}
@@ -5242,13 +5329,16 @@ Calls of built-in functions are restricted as for
-Each time the "defer" statement
+Each time a "defer" statement
executes, the function value and parameters to the call are
evaluated as usual
-and saved anew but the actual function body is not executed.
-Instead, deferred functions are executed immediately before
+and saved anew but the actual function is not invoked.
+Instead, deferred functions are invoked immediately before
the surrounding function returns, in the reverse order
they were deferred.
+If a deferred function value evaluates
+to nil
, execution panics
+when the function is invoked, not when the "defer" statement is executed.
@@ -5295,11 +5385,6 @@ so they can only appear in call expressions; they cannot be used as function values.
--BuiltinCall = identifier "(" [ BuiltinArgs [ "," ] ] ")" . -BuiltinArgs = Type [ "," ArgumentList ] | ArgumentList . --
@@ -5378,9 +5463,11 @@ var z complex128
-The built-in function new
takes a type T
and
-returns a value of type *T
.
-The memory is initialized as described in the section on
+The built-in function new
takes a type T
,
+allocates storage for a variable of that type
+at run time, and returns a value of type *T
+pointing to it.
+The variable is initialized as described in the section on
initial values.
-dynamically allocates memory for a variable of type S
,
+allocates storage for a variable of type S
,
initializes it (a=0
, b=0.0
),
and returns a value of type *S
containing the address
-of the memory.
+of the location.
-When memory is allocated to store a value, either through a declaration
-or a call of make
or new
,
-and no explicit initialization is provided, the memory is
-given a default initialization. Each element of such a value is
+When storage is allocated for a variable,
+either through a declaration or a call of new
, or when
+a new value is created, either through a composite literal or a call
+of make
,
+and no explicit initialization is provided, the variable or value is
+given a default value. Each element of such a variable or value is
set to the zero value for its type: false
for booleans,
0
for integers, 0.0
for floats, ""
for strings, and nil
for pointers, functions, interfaces, slices, channels, and maps.
@@ -5915,20 +6004,42 @@ var t T
-Within a package, package-level variables are initialized according
-to their dependencies: if a variable x
depends on
-a variable y
, x
will be initialized after
-y
.
+Within a package, package-level variables are initialized in
+declaration order but after any of the variables
+they depend on.
+
+More precisely, a package-level variable is considered ready for +initialization if it is not yet initialized and either has +no initialization expression or +its initialization expression has no dependencies on uninitialized variables. +Initialization proceeds by repeatedly initializing the next package-level +variable that is earliest in declaration order and ready for initialization, +until there are no variables ready for initialization. +
+ ++If any variables are still uninitialized when this +process ends, those variables are part of one or more initialization cycles, +and the program is not valid. +
+ ++The declaration order of variables declared in multiple files is determined +by the order in which the files are presented to the compiler: Variables +declared in the first file are declared before any of the variables declared +in the second file, and so on.
Dependency analysis does not rely on the actual values of the
variables, only on lexical references to them in the source,
-analyzed transitively. For instance, a variable x
's
-initialization expression
-may refer to a function whose body refers to variable y
;
-if so, x
depends on y
.
+analyzed transitively. For instance, if a variable x
's
+initialization expression refers to a function whose body refers to
+variable y
then x
depends on y
.
Specifically:
m
is a
method value or
-method expression of the form
+method expression of the form
t.m
, where the (static) type of t
is
not an interface type, and the method m
is in the
method set of t
.
@@ -5950,7 +6061,7 @@ It is immaterial whether the resulting function value
x
depends on a variable
+A variable, function, or method x
depends on a variable
y
if x
's initialization expression or body
(for functions and methods) contains a reference to y
or to a function or method that depends on y
.
@@ -5961,11 +6072,6 @@ or to a function or method that depends on y
.
Dependency analysis is performed per package; only references referring
to variables, functions, and methods declared in the current package
are considered.
-It is an error if variable dependencies form a cycle
-(but dependency cycles containing no variables are permitted).
-If two variables are independent of each other,
-they are initialized in the order they are declared
-in the source, possibly in multiple files, as presented to the compiler.
@@ -5988,8 +6094,6 @@ func f() int {
the initialization order is d
, b
, c
, a
.
-Since b
and c
are independent of each other, they are
-initialized in declaration order (b
before c
).
@@ -6002,7 +6106,7 @@ func init() { … }
-Multiple such functions may be defined, even within a single
+Multiple such functions may be defined, even within a single
source file. The init
identifier is not
declared and thus
init
functions cannot be referred to from anywhere
@@ -6032,6 +6136,12 @@ the init
functions: it will not invoke the next one
until the previous one has returned.
+To ensure reproducible initialization behavior, build systems are encouraged +to present multiple files belonging to the same package in lexical file name +order to a compiler. +
+
@@ -6106,8 +6216,8 @@ type Error interface {
The built-in package unsafe
, known to the compiler,
provides facilities for low-level programming including operations
that violate the type system. A package using unsafe
-must be vetted manually for type safety. The package provides the
-following interface:
+must be vetted manually for type safety and may not be portable.
+The package provides the following interface:
@@ -6122,10 +6232,11 @@ func Sizeof(variable ArbitraryType) uintptr
-Any pointer or value of underlying type uintptr
can be converted to
-a Pointer
type and vice versa.
A Pointer
is a pointer type but a Pointer
value may not be dereferenced.
+Any pointer or value of underlying type uintptr
can be converted to
+a Pointer
type and vice versa.
+The effect of converting between Pointer
and uintptr
is implementation-defined.
-- cgit v1.2.3