forked from gobyexample-cn/gobyexample-cn.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
closing-channels.html
191 lines (149 loc) · 8.46 KB
/
closing-channels.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Go by Example 中文版: 通道的关闭</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 by Example 中文版</a>: 通道的关闭</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="https://play.studygolang.com/p/abQFh1JyeUl"><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="code leading">
<pre class="chroma"><span class="kn">import</span> <span class="s">"fmt"</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>在这个例子中,我们将使用一个 <code>jobs</code> 通道,将工作内容,
从 <code>main()</code> 协程传递到一个工作协程中。
当我们没有更多的任务传递给工作协程时,我们将 <code>close</code> 这个 <code>jobs</code> 通道。</p>
</td>
<td class="code leading">
<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>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>这是工作协程。使用 <code>j, more := <- jobs</code> 循环的从 <code>jobs</code> 接收数据。
根据接收的第二个值,如果 <code>jobs</code> 已经关闭了,
并且通道中所有的值都已经接收完毕,那么 <code>more</code> 的值将是 <code>false</code>。
当我们完成所有的任务时,会使用这个特性通过 <code>done</code> 通道通知 main 协程。</p>
</td>
<td class="code leading">
<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>
<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="nf">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="nf">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>
</td>
</tr>
<tr>
<td class="docs">
<p>使用 <code>jobs</code> 发送 3 个任务到工作协程中,然后关闭 <code>jobs</code>。</p>
</td>
<td class="code leading">
<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>
<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="nf">Println</span><span class="p">(</span><span class="s">"sent all jobs"</span><span class="p">)</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>使用前面学到的<a href="channel-synchronization">通道同步</a>方法等待任务结束。</p>
</td>
<td class="code">
<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="code leading">
<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 all jobs</span></pre>
</td>
</tr>
<tr>
<td class="docs">
<p>根据 <code>关闭通道</code> 的思想,可以引出我们的下一个示例:遍历通道。</p>
</td>
<td class="code empty">
</td>
</tr>
</table>
<p class="next">
下一个例子: <a href="range-over-channels.html">通道遍历</a>
</p>
<p class="footer">
<a href="https://twitter.com/mmcgrana">@mmcgrana</a> 和<a href="https://eli.thegreenplace.net">Eli Bendersky</a>编写 | <a href="https://github.com/gobyexample-cn">gobyexample-cn</a> 翻译 | <a href="https://github.com/gobyexample-cn/gobyexample/issues">反馈</a> | <a href="https://github.com/gobyexample-cn/gobyexample">源码</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a> </p>
</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('');
</script>
<script src="site.js" async></script>
</body>
</html>