202 lines
9.1 KiB
Plaintext
Generated
202 lines
9.1 KiB
Plaintext
Generated
<!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">"fmt"</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 := <-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"><-</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">"received job"</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">"received all jobs"</span><span class="p">)</span>
|
||
<span class="nx">done</span> <span class="o"><-</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"><=</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="nx">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>
|
||
<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">"sent all jobs"</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"><-</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>
|