diff --git a/doc/go_tutorial.html b/doc/go_tutorial.html
index 0127783a746..9713c904159 100644
--- a/doc/go_tutorial.html
+++ b/doc/go_tutorial.html
@@ -1377,7 +1377,7 @@ The server
routine loops forever, receiving requests and, to avoid
a long-running operation, starting a goroutine to do the actual work.
func server(op binOp, service chan *request) { +-->func server(op binOp, service <-chan *request) { for { req := <-service go run(op, req) // don't wait for it @@ -1385,17 +1385,41 @@ a long-running operation, starting a goroutine to do the actual work. }
-We construct a server in a familiar way, starting it and returning a channel
+There's a new feature in the signature of server
: the type of the
+service
channel specifies the direction of communication.
+A channel of plain chan
type can be used both for sending and receiving.
+However, the type used when declaring a channel can be decorated with an arrow to
+indicate that the channel can be used only to send (chan<-
) or to
+receive (<-chan
) data.
+The arrow points towards or away from the chan
to indicate whether data flows into or out of
+the channel.
+In the server
function, service <-chan *request
is a "receive only" channel
+that the function can use only to read new requests.
+
+We instantiate a server in a familiar way, starting it and returning a channel connected to it:
func startServer(op binOp) chan *request { +-->func startServer(op binOp) chan<- *request { req := make(chan *request) go server(op, req) return req }
+The returned channel is send only, even though the channel was created bidirectionally.
+The read end is passed to server
, while the send end is returned
+to the caller of startServer
, so the two halves of the channel
+are distinguished, just as we did in startServer
.
+
+Bidirectional channels can be assigned to unidirectional channels but not the
+other way around, so if you annotate your channel directions when you declare
+them, such as in function signatures, the type system can help you set up and
+use channels correctly.
+Note that it's pointless to make
unidirectional channels, since you can't
+use them to communicate. Their purpose is served by variables assigned from bidirectional channels
+to distinguish the input and output halves.
+
Here's a simple test. It starts a server with an addition operator and sends out
N
requests without waiting for the replies. Only after all the requests are sent
does it check the results.
@@ -1437,7 +1461,7 @@ we can provide a second, quit
channel to the server:
It passes the quit channel to the server
function, which uses it like this:
func server(op binOp, service chan *request, quit chan bool) { +-->func server(op binOp, service <-chan *request, quit <-chan bool) { for { select { case req := <-service: diff --git a/doc/go_tutorial.tmpl b/doc/go_tutorial.tmpl index 21496ddd980..dfd818959c4 100644 --- a/doc/go_tutorial.tmpl +++ b/doc/go_tutorial.tmpl @@ -968,11 +968,35 @@ a long-running operation, starting a goroutine to do the actual work.{{code "progs/server.go" `/func.server/` `/^}/`}}
-We construct a server in a familiar way, starting it and returning a channel +There's a new feature in the signature of
server
: the type of the +service
channel specifies the direction of communication. +A channel of plainchan
type can be used both for sending and receiving. +However, the type used when declaring a channel can be decorated with an arrow to +indicate that the channel can be used only to send (chan<-
) or to +receive (<-chan
) data. +The arrow points towards or away from thechan
to indicate whether data flows into or out of +the channel. +In theserver
function,service <-chan *request
is a "receive only" channel +that the function can use only to read new requests. ++We instantiate a server in a familiar way, starting it and returning a channel connected to it:
{{code "progs/server.go" `/func.startServer/` `/^}/`}}
+The returned channel is send only, even though the channel was created bidirectionally. +The read end is passed to
server
, while the send end is returned +to the caller ofstartServer
, so the two halves of the channel +are distinguished, just as we did instartServer
. ++Bidirectional channels can be assigned to unidirectional channels but not the +other way around, so if you annotate your channel directions when you declare +them, such as in function signatures, the type system can help you set up and +use channels correctly. +Note that it's pointless to
make
unidirectional channels, since you can't +use them to communicate. Their purpose is served by variables assigned from bidirectional channels +to distinguish the input and output halves. +Here's a simple test. It starts a server with an addition operator and sends out
N
requests without waiting for the replies. Only after all the requests are sent does it check the results. diff --git a/doc/progs/server.go b/doc/progs/server.go index b498b53a63c..4d8409b801e 100644 --- a/doc/progs/server.go +++ b/doc/progs/server.go @@ -18,14 +18,14 @@ func run(op binOp, req *request) { req.replyc <- reply } -func server(op binOp, service chan *request) { +func server(op binOp, service <-chan *request) { for { req := <-service go run(op, req) // don't wait for it } } -func startServer(op binOp) chan *request { +func startServer(op binOp) chan<- *request { req := make(chan *request) go server(op, req) return req diff --git a/doc/progs/server1.go b/doc/progs/server1.go index a4093924b8e..39e3dde5da7 100644 --- a/doc/progs/server1.go +++ b/doc/progs/server1.go @@ -18,7 +18,7 @@ func run(op binOp, req *request) { req.replyc <- reply } -func server(op binOp, service chan *request, quit chan bool) { +func server(op binOp, service <-chan *request, quit <-chan bool) { for { select { case req := <-service: