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: