From 01cadde59761f2aade7ae45f41a145893b59cc71 Mon Sep 17 00:00:00 2001
From: Rob Pike
-TODO: This text needs to be cleaned up and go elsewhere, there are no address
-operators involved.
-
+The term channel means "value of channel type".
-Methods are a form of function and a method ``value'' has a function type.
-Consider the type T with method M:
+The send operation uses the binary operator "<-", which operates on
+a channel and a value (expression):
-To construct the value of method M, one writes
+The send operation sends the value on the channel. Both the channel
+and the expression are evaluated before communication begins.
+Communication blocks until the send can proceed, at which point the
+value is transmitted on the channel.
+A send on an unbuffered channel can proceed if a receiver is ready.
+A send on a buffered channel can proceed if there is room in the buffer.
+
+If the send operation appears in an expression context, the value
+of the expression is a boolean and the operation is non-blocking.
+The value of the boolean reports true if the communication succeeded,
+false if it did not. (The channel and
+the expression to be sent are evaluated regardless.)
+These two examples are equivalent:
-using the variable t (not the type T).
-TODO: It makes perfect sense to be able to say T.M (in fact, it makes more
-sense then t.M, since only the type T is needed to find the method M, i.e.,
-its address). TBD.
-
+In other words, if the program tests the value of a send operation,
+the send is non-blocking and the value of the expression is the
+success of the operation. If the program does not test the value,
+the operation blocks until it succeeds.
-The expression t.M is a function value with type
+The receive operation uses the prefix unary operator "<-".
+The value of the expression is the value received, whose type
+is the element type of the channel.
-and may be invoked only as a function, not as a method:
+The expression blocks until a value is available, which then can
+be assigned to a variable or used like any other expression.
+If the receive expression does not save the value, the value is
+discarded.
-Note that one does not write t.f(7); taking the value of a method demotes
-it to a function.
-
-In general, given type T with method M and variable t of type T,
-the method invocation
+If a receive expression is used in an assignment or initialization of the form
-is equivalent to the function call
+the receive operation becomes non-blocking.
+If the operation can proceed, the boolean variable
+
-
-TODO: should probably describe the effect of (t.m) under §Expressions if t.m
-denotes a method: Effect is as described above, converts into function.
-
+TODO: Probably in a separate section, communication semantics
+need to be presented regarding send, receive, select, and goroutines.
-If T is an interface type, the expression t.M does not determine which
-underlying type's M is called until the point of the call itself. Thus given
-T1 and T2, both implementing interface I with method M, the sequence
+If
-will invoke t2.M() even though m was constructed with an expression involving
-t1. Effectively, the value of m is a function literal
+Consider a struct type
-that is automatically created.
-
-
-TODO: Document implementation restriction: It is illegal to take the address
-of a result parameter (e.g.: func f() (x int, p *int) { return 2, &x }).
-(TBD: is it an implementation restriction or fact?)
-
+The expression
-The term channel means "value of channel type".
-
-The send operation uses the binary operator "<-", which operates on
-a channel and a value (expression):
+yields a function equivalent to
-The send operation sends the value on the channel. Both the channel
-and the expression are evaluated before communication begins.
-Communication blocks until the send can proceed, at which point the
-value is transmitted on the channel.
-A send on an unbuffered channel can proceed if a receiver is ready.
-A send on a buffered channel can proceed if there is room in the buffer.
-
-If the send operation appears in an expression context, the value
-of the expression is a boolean and the operation is non-blocking.
-The value of the boolean reports true if the communication succeeded,
-false if it did not. (The channel and
-the expression to be sent are evaluated regardless.)
-These two examples are equivalent:
+That function may be called normally with an explicit receiver, so
+these three invocations are equivalent:
-In other words, if the program tests the value of a send operation,
-the send is non-blocking and the value of the expression is the
-success of the operation. If the program does not test the value,
-the operation blocks until it succeeds.
+Similarly, the expression
-The receive operation uses the prefix unary operator "<-".
-The value of the expression is the value received, whose type
-is the element type of the channel.
+yields a function value representing
-The expression blocks until a value is available, which then can
-be assigned to a variable or used like any other expression.
-If the receive expression does not save the value, the value is
-discarded.
+For a method with a value receiver, one can derive a function
+with an explicit pointer receiver, so
-If a receive expression is used in an assignment or initialization of the form
+yields a function value representing
-the receive operation becomes non-blocking.
-If the operation can proceed, the boolean variable
-
-TODO: Probably in a separate section, communication semantices
-need to be presented regarding send, receive, select, and goroutines.
+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
+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.
-Operand = Literal | QualifiedIdent | "(" Expression ")" .
+Operand = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | char_lit | StringLit .
@@ -2710,213 +2710,215 @@ to by the operand.
*pf(x)
+Communication operators
+
-type T struct {
- a int;
-}
-func (tp *T) M(a int) int;
-var t *T;
+ch <- 3
-t.M
+ok := ch <- 3;
+if ok { print("sent") } else { print("not sent") }
+
+if ch <- 3 { print("sent") } else { print("not sent") }
-func (t *T, a int) int
+<-ch
-var f func (t *T, a int) int;
-f = t.M;
-x := f(t, 7);
+v1 := <-ch
+v2 = <-ch
+f(<-ch)
+<-strobe // wait until clock pulse
-t.M(args)
+x, ok = <-ch
+x, ok := <-ch
+var x, ok = <-ch
ok
will be set to true
+and the value stored in x
; otherwise
+ok
is set
+to false
and x
is set to the
+zero value for its type (§The zero value).
-(t.M)(t, args)
-
-
Method expressions
+
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.
-var t1 *T1;
-var t2 *T2;
-var i I = t1;
-m := i.M;
-m(t2, 7);
+
+MethodExpr = ReceiverType "." MethodName .
+ReceiverType = TypeName | "(" "*" TypeName ")" .
+MethodName = identifier .
T
with two methods,
+Mv
, whose receiver is of type T
, and
+Mp
, whose receiver is of type *T
.
-func (recv I, a int) {
- recv.M(a);
+type T struct {
+ a int;
}
+func (tv T) Mv(a int) int { return 0 } // value receiver
+func (tp *T) Mp(f float) float { return 1 } // pointer receiver
+var t T;
Communication operators
+
+T.Mv
+
Mv
but
+with an explicit receiver as its first argument; it has signature
-ch <- 3
+func (tv T, a int) int
-ok := ch <- 3;
-if ok { print("sent") } else { print("not sent") }
-
-if ch <- 3 { print("sent") } else { print("not sent") }
+t.Mv(7)
+T.Mv(t, 7)
+f := T.Mv; f(t, 7)
+(*T).Mp
+
+
Mp
with signature
-<-ch
+func (tp *T, f float) float
-v1 := <-ch
-v2 = <-ch
-f(<-ch)
-<-strobe // wait until clock pulse
+(*T).Mv
Mv
with signature
-x, ok = <-ch
-x, ok := <-ch
-var x, ok = <-ch
+func (tv *T, f int) int
ok
will be set to true
-and the value stored in x
; otherwise
-ok
is set
-to false
and x
is set to the
-zero value for its type (§The zero value).
+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.
f := T.Mv
, f
is invoked
+as f(t, 7)
not t.f(7)
.
+To construct a function that binds the receiver, use a
+closure.
+Constant expressions
@@ -4309,8 +4311,8 @@ mentions B
, or mentions a function that
mentions B
, recursively.
If two items are not interdependent, they will be initialized
in the order they appear in the source.
-Since the dependency analysis is done per package, it can be
-defeated if A
's initializer calls a function defined
+Since the dependency analysis is done per package, it can produce
+unspecified results if A
's initializer calls a function defined
in another package that refers to B
.
-- 2.48.1