gobyexample/public/closing-channels
2019-10-14 23:20:44 +03:00

202 lines
9.1 KiB
Plaintext
Generated
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Go в примерах: Закрытие каналов (Closing Channels)</title>
<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';
}
}
</script>
<body>
<div class="example" id="closing-channels">
<h2><a href="./">Go в примерах</a>: Закрытие каналов (Closing Channels)</h2>
<table>
<tr>
<td class="docs">
<p><em>Закрытие</em> канала означает, что по нему больше не
будет отправлено никаких значений. Это может быть
полезно для сообщения получателям о завершении.</p>
</td>
<td class="code empty leading">
</td>
</tr>
<tr>
<td class="docs">
</td>
<td class="code leading">
<a href="http://play.golang.org/p/V8RCD4w9KY-" target="_blank"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
<div class="highlight"><pre><span class="kn">package</span> <span class="nx">main</span>
</pre></div>
</td>
</tr>
<tr>
<td class="docs">
</td>
<td class="code leading">
<div class="highlight"><pre><span class="kn">import</span> <span class="s">&quot;fmt&quot;</span>
</pre></div>
</td>
</tr>
<tr>
<td class="docs">
<p>В этом примере мы будем использовать канал <code>jobs</code> для
передачи задания, которое должна быть выполнена из
<code>main()</code> в горутине. Когда у нас больше не будет
заданий для воркера, мы <code>закроем</code> канал <code>jobs</code>.</p>
</td>
<td class="code leading">
<div class="highlight"><pre><span class="kd">func</span> <span class="nx">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>
</pre></div>
</td>
</tr>
<tr>
<td class="docs">
<p>Вот наш воркер. Он многократно получает из канала
<code>jobs</code> значения <code>j, more := &lt;-jobs</code>. В этой специальной
форме получения с двумя значениями <code>more</code> значение
будет <code>ложным</code>, если <code>jobs</code> были <code>закрыты</code>, а все
значения в канале уже получены. Мы используем
это, чтобы уведомить о <code>выполнении</code>, когда мы
проработали все наши работы.</p>
</td>
<td class="code leading">
<div class="highlight"><pre> <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">&lt;-</span><span class="nx">jobs</span>
<span class="k">if</span> <span class="nx">more</span> <span class="p">{</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;received job&quot;</span><span class="p">,</span> <span class="nx">j</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;received all jobs&quot;</span><span class="p">)</span>
<span class="nx">done</span> <span class="o">&lt;-</span> <span class="kc">true</span>
<span class="k">return</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}()</span>
</pre></div>
</td>
</tr>
<tr>
<td class="docs">
<p>Отправляем 3 сообщения в канал <code>jobs</code>, и закрываем
его.</p>
</td>
<td class="code leading">
<div class="highlight"><pre> <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">&lt;=</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">&lt;-</span> <span class="nx">j</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;sent job&quot;</span><span class="p">,</span> <span class="nx">j</span><span class="p">)</span>
<span class="p">}</span>
<span class="nb">close</span><span class="p">(</span><span class="nx">jobs</span><span class="p">)</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="s">&quot;sent all jobs&quot;</span><span class="p">)</span>
</pre></div>
</td>
</tr>
<tr>
<td class="docs">
<p>Мы ожидаем выполнения всех каналов используя
<a href="channel-synchronization">синхронизацию</a>, рассмотренную
нами ранее.</p>
</td>
<td class="code">
<div class="highlight"><pre> <span class="o">&lt;-</span><span class="nx">done</span>
<span class="p">}</span>
</pre></div>
</td>
</tr>
</table>
<table>
<tr>
<td class="docs">
</td>
<td class="code leading">
<div class="highlight"><pre><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 all jobs</span>
</pre></div>
</td>
</tr>
<tr>
<td class="docs">
<p>Идея закрытых каналов естественно приводит нас к
следующему примеру: <code>range</code> по каналам.</p>
</td>
<td class="code empty">
</td>
</tr>
</table>
<p class="next">
Следующий пример: <a href="range-over-channels">Перебор значений из каналов (Range over Channels)</a>.
</p>
<p class="footer">
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> | <a href="https://github.com/mmcgrana/gobyexample/blob/master/examples/closing-channels">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 := make(chan int, 5)\u000A done := make(chan bool)\u000A');codeLines.push(' go func() {\u000A for {\u000A j, more := \x3C-jobs\u000A if more {\u000A fmt.Println(\"received job\", j)\u000A } else {\u000A fmt.Println(\"received all jobs\")\u000A done \x3C- true\u000A return\u000A }\u000A }\u000A }()\u000A');codeLines.push(' for j := 1; j \x3C= 3; j++ {\u000A jobs \x3C- j\u000A fmt.Println(\"sent job\", j)\u000A }\u000A close(jobs)\u000A fmt.Println(\"sent all jobs\")\u000A');codeLines.push(' \x3C-done\u000A}\u000A');codeLines.push('');codeLines.push('');
</script>
<script src="site.js" async></script>
</body>
</html>