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 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:

{{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 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. 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: