Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
a50ee009
Commit
a50ee009
authored
Nov 10, 2011
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tutorial: describe unidirectional channels
R=golang-dev, adg, gri CC=golang-dev
https://golang.org/cl/5370058
parent
d9897096
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
56 additions
and
8 deletions
+56
-8
doc/go_tutorial.html
doc/go_tutorial.html
+28
-4
doc/go_tutorial.tmpl
doc/go_tutorial.tmpl
+25
-1
doc/progs/server.go
doc/progs/server.go
+2
-2
doc/progs/server1.go
doc/progs/server1.go
+1
-1
No files found.
doc/go_tutorial.html
View file @
a50ee009
...
...
@@ -1377,7 +1377,7 @@ The <code>server</code> routine loops forever, receiving requests and, to avoid
a long-running operation, starting a goroutine to do the actual work.
<p>
<pre>
<!--{{code "progs/server.go" `/func.server/` `/^}/`}}
-->
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.
}
</pre>
<p>
We construct a server in a familiar way, starting it and returning a channel
There's a new feature in the signature of
<code>
server
</code>
: the type of the
<code>
service
</code>
channel specifies the direction of communication.
A channel of plain
<code>
chan
</code>
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 (
<code>
chan
<
-
</code>
) or to
receive (
<code>
<
-chan
</code>
) data.
The arrow points towards or away from the
<code>
chan
</code>
to indicate whether data flows into or out of
the channel.
In the
<code>
server
</code>
function,
<code>
service
<
-chan *request
</code>
is a "receive only" channel
that the function can use only to
<em>
read
</em>
new requests.
<p>
We instantiate a server in a familiar way, starting it and returning a channel
connected to it:
<p>
<pre>
<!--{{code "progs/server.go" `/func.startServer/` `/^}/`}}
-->
func startServer(op binOp) chan *request {
-->
func startServer(op binOp) chan
<
-
*request {
req := make(chan *request)
go server(op, req)
return req
}
</pre>
<p>
The returned channel is send only, even though the channel was created bidirectionally.
The read end is passed to
<code>
server
</code>
, while the send end is returned
to the caller of
<code>
startServer
</code>
, so the two halves of the channel
are distinguished, just as we did in
<code>
startServer
</code>
.
<p>
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
<code>
make
</code>
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.
<p>
Here's a simple test. It starts a server with an addition operator and sends out
<code>
N
</code>
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, <code>quit</code> channel to the server:
It passes the quit channel to the
<code>
server
</code>
function, which uses it like this:
<p>
<pre>
<!--{{code "progs/server1.go" `/func.server/` `/^}/`}}
-->
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:
...
...
doc/go_tutorial.tmpl
View file @
a50ee009
...
...
@@ -968,11 +968,35 @@ a long-running operation, starting a goroutine to do the actual work.
<
p
>
{{
code
"progs/server.go"
`/
func
.
server
/`
`/^}/`}}
<
p
>
We
construct
a
server
in
a
familiar
way
,
starting
it
and
returning
a
channel
There
's a new feature in the signature of <code>server</code>: the type of the
<code>service</code> channel specifies the direction of communication.
A channel of plain <code>chan</code> 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 (<code>chan<-</code>) or to
receive (<code><-chan</code>) data.
The arrow points towards or away from the <code>chan</code> to indicate whether data flows into or out of
the channel.
In the <code>server</code> function, <code>service <-chan *request</code> is a "receive only" channel
that the function can use only to <em>read</em> new requests.
<p>
We instantiate a server in a familiar way, starting it and returning a channel
connected to it:
<p>
{{code "progs/server.go" `/func.startServer/` `/^}/`}}
<p>
The returned channel is send only, even though the channel was created bidirectionally.
The read end is passed to <code>server</code>, while the send end is returned
to the caller of <code>startServer</code>, so the two halves of the channel
are distinguished, just as we did in <code>startServer</code>.
<p>
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
<
code
>
make
</
code
>
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.
<p>
Here'
s
a
simple
test
.
It
starts
a
server
with
an
addition
operator
and
sends
out
<
code
>
N
</
code
>
requests
without
waiting
for
the
replies
.
Only
after
all
the
requests
are
sent
does
it
check
the
results
.
...
...
doc/progs/server.go
View file @
a50ee009
...
...
@@ -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
...
...
doc/progs/server1.go
View file @
a50ee009
...
...
@@ -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
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment