fix: Wrong results on Closing-Channels
This commit is contained in:
parent
668ecb9732
commit
144421ac3c
@ -1,11 +1,11 @@
|
||||
$ go run closing-channels.go
|
||||
sent job 1
|
||||
received job 1
|
||||
sent job 2
|
||||
received job 2
|
||||
sent job 3
|
||||
received job 3
|
||||
sent all jobs
|
||||
received job 1
|
||||
received job 2
|
||||
received job 3
|
||||
received all jobs
|
||||
|
||||
# The idea of closed channels leads naturally to our next
|
||||
|
181
public/closing-channels
generated
181
public/closing-channels
generated
@ -1,76 +1,71 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta charset="utf-8" />
|
||||
<title>Go by Example: Closing Channels</title>
|
||||
<link rel=stylesheet href="site.css">
|
||||
<link rel="stylesheet" href="site.css" />
|
||||
</head>
|
||||
<script>
|
||||
onkeydown = (e) => {
|
||||
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = 'non-blocking-channel-operations';
|
||||
}
|
||||
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = 'range-over-channels';
|
||||
}
|
||||
|
||||
onkeydown = (e) => {
|
||||
if (e.key == "ArrowLeft") {
|
||||
window.location.href = "non-blocking-channel-operations";
|
||||
}
|
||||
|
||||
if (e.key == "ArrowRight") {
|
||||
window.location.href = "range-over-channels";
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<body>
|
||||
<div class="example" id="closing-channels">
|
||||
<h2><a href="./">Go by Example</a>: Closing Channels</h2>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p><em>Closing</em> a channel indicates that no more values
|
||||
will be sent on it. This can be useful to communicate
|
||||
completion to the channel’s receivers.</p>
|
||||
|
||||
<p>
|
||||
<em>Closing</em> a channel indicates that no more values will be
|
||||
sent on it. This can be useful to communicate completion to the
|
||||
channel’s receivers.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code empty leading">
|
||||
|
||||
<td class="code empty leading"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs"></td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/vCvRjcMq7p3"
|
||||
><img title="Run code" src="play.png" class="run" /></a
|
||||
><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<pre
|
||||
class="chroma"
|
||||
><span class="kn">package</span> <span class="nx">main</span>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="docs"></td>
|
||||
<td class="code leading">
|
||||
<a href="http://play.golang.org/p/vCvRjcMq7p3"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
|
||||
<pre class="chroma"><span class="kn">package</span> <span class="nx">main</span>
|
||||
<pre
|
||||
class="chroma"
|
||||
><span class="kn">import</span> <span class="s">"fmt"</span>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
<p>
|
||||
In this example we’ll use a <code>jobs</code> channel to
|
||||
communicate work to be done from the <code>main()</code> goroutine
|
||||
to a worker goroutine. When we have no more jobs for the worker
|
||||
we’ll <code>close</code> the <code>jobs</code> channel.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><span class="kn">import</span> <span class="s">"fmt"</span>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>In this example we’ll use a <code>jobs</code> channel to
|
||||
communicate work to be done from the <code>main()</code> goroutine
|
||||
to a worker goroutine. When we have no more jobs for
|
||||
the worker we’ll <code>close</code> the <code>jobs</code> channel.</p>
|
||||
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma">
|
||||
<pre class="chroma">
|
||||
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">jobs</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
|
||||
<span class="nx">done</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">bool</span><span class="p">)</span>
|
||||
@ -80,18 +75,18 @@ the worker we’ll <code>close</code> the <code>jobs</code> channel.</p>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>Here’s the worker goroutine. It repeatedly receives
|
||||
from <code>jobs</code> with <code>j, more := <-jobs</code>. In this
|
||||
special 2-value form of receive, the <code>more</code> value
|
||||
will be <code>false</code> if <code>jobs</code> has been <code>close</code>d and all
|
||||
values in the channel have already been received.
|
||||
We use this to notify on <code>done</code> when we’ve worked
|
||||
all our jobs.</p>
|
||||
|
||||
<p>
|
||||
Here’s the worker goroutine. It repeatedly receives from
|
||||
<code>jobs</code> with <code>j, more := <-jobs</code>. In this
|
||||
special 2-value form of receive, the <code>more</code> value will
|
||||
be <code>false</code> if <code>jobs</code> has been
|
||||
<code>close</code>d and all values in the channel have already
|
||||
been received. We use this to notify on <code>done</code> when
|
||||
we’ve worked all our jobs.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma">
|
||||
<pre class="chroma">
|
||||
<span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="k">for</span> <span class="p">{</span>
|
||||
<span class="nx">j</span><span class="p">,</span> <span class="nx">more</span> <span class="o">:=</span> <span class="o"><-</span><span class="nx">jobs</span>
|
||||
@ -110,13 +105,13 @@ all our jobs.</p>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>This sends 3 jobs to the worker over the <code>jobs</code>
|
||||
channel, then closes it.</p>
|
||||
|
||||
<p>
|
||||
This sends 3 jobs to the worker over the
|
||||
<code>jobs</code> channel, then closes it.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma">
|
||||
<pre class="chroma">
|
||||
<span class="k">for</span> <span class="nx">j</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><=</span> <span class="mi">3</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span> <span class="p">{</span>
|
||||
<span class="nx">jobs</span> <span class="o"><-</span> <span class="nx">j</span>
|
||||
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"sent job"</span><span class="p">,</span> <span class="nx">j</span><span class="p">)</span>
|
||||
@ -129,70 +124,78 @@ channel, then closes it.</p>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>We await the worker using the
|
||||
<a href="channel-synchronization">synchronization</a> approach
|
||||
we saw earlier.</p>
|
||||
|
||||
<p>
|
||||
We await the worker using the
|
||||
<a href="channel-synchronization">synchronization</a> approach we
|
||||
saw earlier.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code">
|
||||
|
||||
<pre class="chroma">
|
||||
<pre class="chroma">
|
||||
<span class="o"><-</span><span class="nx">done</span>
|
||||
<span class="p">}</span>
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
|
||||
</td>
|
||||
<td class="docs"></td>
|
||||
<td class="code leading">
|
||||
|
||||
<pre class="chroma"><span class="gp">$</span> go run closing-channels.go
|
||||
<pre
|
||||
class="chroma"
|
||||
><span class="gp">$</span> go run closing-channels.go
|
||||
<span class="go">sent job 1
|
||||
</span><span class="go">received job 1
|
||||
</span><span class="go">sent job 2
|
||||
</span><span class="go">received job 2
|
||||
</span><span class="go">sent job 3
|
||||
</span><span class="go">received job 3
|
||||
</span><span class="go">sent all jobs
|
||||
</span><span class="go">received job 1
|
||||
</span><span class="go">received job 2
|
||||
</span><span class="go">received job 3
|
||||
</span><span class="go">received all jobs</span></pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="docs">
|
||||
<p>The idea of closed channels leads naturally to our next
|
||||
example: <code>range</code> over channels.</p>
|
||||
|
||||
</td>
|
||||
<td class="code empty">
|
||||
|
||||
|
||||
<p>
|
||||
The idea of closed channels leads naturally to our next example:
|
||||
<code>range</code> over channels.
|
||||
</p>
|
||||
</td>
|
||||
<td class="code empty"></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<p class="next">
|
||||
Next example: <a href="range-over-channels">Range over Channels</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<p class="footer">
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> and <a href="https://eli.thegreenplace.net">Eli Bendersky</a> | <a href="https://github.com/mmcgrana/gobyexample">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
|
||||
<p class="footer">
|
||||
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> and
|
||||
<a href="https://eli.thegreenplace.net">Eli Bendersky</a> |
|
||||
<a href="https://github.com/mmcgrana/gobyexample">source</a> |
|
||||
<a href="https://github.com/mmcgrana/gobyexample#license">license</a>
|
||||
</p>
|
||||
</div>
|
||||
<script>
|
||||
var codeLines = [];
|
||||
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import \"fmt\"\u000A');codeLines.push('func main() {\u000A jobs :\u003D make(chan int, 5)\u000A done :\u003D make(chan bool)\u000A');codeLines.push(' go func() {\u000A for {\u000A j, more :\u003D \u003C-jobs\u000A if more {\u000A fmt.Println(\"received job\", j)\u000A } else {\u000A fmt.Println(\"received all jobs\")\u000A done \u003C- true\u000A return\u000A }\u000A }\u000A }()\u000A');codeLines.push(' for j :\u003D 1; j \u003C\u003D 3; j++ {\u000A jobs \u003C- j\u000A fmt.Println(\"sent job\", j)\u000A }\u000A close(jobs)\u000A fmt.Println(\"sent all jobs\")\u000A');codeLines.push(' \u003C-done\u000A}\u000A');codeLines.push('');codeLines.push('');
|
||||
codeLines.push("");
|
||||
codeLines.push("package main\u000A");
|
||||
codeLines.push('import "fmt"\u000A');
|
||||
codeLines.push(
|
||||
"func main() {\u000A jobs :\u003D make(chan int, 5)\u000A done :\u003D make(chan bool)\u000A"
|
||||
);
|
||||
codeLines.push(
|
||||
' go func() {\u000A for {\u000A j, more :\u003D \u003C-jobs\u000A if more {\u000A fmt.Println("received job", j)\u000A } else {\u000A fmt.Println("received all jobs")\u000A done \u003C- true\u000A return\u000A }\u000A }\u000A }()\u000A'
|
||||
);
|
||||
codeLines.push(
|
||||
' for j :\u003D 1; j \u003C\u003D 3; j++ {\u000A jobs \u003C- j\u000A fmt.Println("sent job", j)\u000A }\u000A close(jobs)\u000A fmt.Println("sent all jobs")\u000A'
|
||||
);
|
||||
codeLines.push(" \u003C-done\u000A}\u000A");
|
||||
codeLines.push("");
|
||||
codeLines.push("");
|
||||
</script>
|
||||
<script src="site.js" async></script>
|
||||
</body>
|
||||
|
Loading…
x
Reference in New Issue
Block a user