-
Notifications
You must be signed in to change notification settings - Fork 8
/
signals.html
211 lines (163 loc) · 8.25 KB
/
signals.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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
<!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 = 'execing-processes';
}
if (e.key == "ArrowRight") {
window.location.href = 'exit';
}
}
</script>
<body>
<div class="example" id="signals">
<h2><a href="./">Go by Example 中文版</a>: 信号</h2>
<table>
<tr>
<td class="docs">
<p>有时候,我们希望 Go 可以智能的处理 <a href="http://en.wikipedia.org/wiki/Unix_signal">Unix 信号</a>。
例如,我们希望当服务器接收到一个 <code>SIGTERM</code> 信号时,能够优雅退出,
或者一个命令行工具在接收到一个 <code>SIGINT</code> 信号时停止处理输入信息。
我们这里讲的就是在 Go 中如何使用通道来处理信号。</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/O1C4e597EpS"><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="p">(</span>
<span class="s">"fmt"</span>
<span class="s">"os"</span>
<span class="s">"os/signal"</span>
<span class="s">"syscall"</span>
<span class="p">)</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
</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>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>Go 通过向一个通道发送 <code>os.Signal</code> 值来发送信号通知。
我们将创建一个通道来接收这些通知。请注意,这个通道应该被缓存。</p>
</td>
<td class="code leading">
<pre class="chroma">
<span class="nx">sigs</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Signal</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p><code>signal.Notify</code> 注册给定的通道,用于接收特定信号。</p>
</td>
<td class="code leading">
<pre class="chroma">
<span class="nx">signal</span><span class="p">.</span><span class="nf">Notify</span><span class="p">(</span><span class="nx">sigs</span><span class="p">,</span> <span class="nx">syscall</span><span class="p">.</span><span class="nx">SIGINT</span><span class="p">,</span> <span class="nx">syscall</span><span class="p">.</span><span class="nx">SIGTERM</span><span class="p">)</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>我们可以在 main 函数中从 <code>sigs</code> 接收。
但让我们看看如何在单独的 goroutine 中完成此操作,
以演示更实际的正常关闭方案。</p>
</td>
<td class="code leading">
<pre class="chroma">
<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> <span class="mi">1</span><span class="p">)</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>这个协程执行一个阻塞的信号接收操作。
当它接收到一个值时,它将打印这个值,然后通知程序可以退出。</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>
</pre>
</td>
</tr>
<tr>
<td class="docs">
</td>
<td class="code leading">
<pre class="chroma"> <span class="nx">sig</span> <span class="o">:=</span> <span class="o"><-</span><span class="nx">sigs</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</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="nx">sig</span><span class="p">)</span>
<span class="nx">done</span> <span class="o"><-</span> <span class="kc">true</span>
<span class="p">}()</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<pre><code>程序将在这里进行等待,直到它得到了期望的信号
</code></pre>
<p>(也就是上面的协程发送的 <code>done</code> 值),然后退出。</p>
</td>
<td class="code">
<pre class="chroma">
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"awaiting signal"</span><span class="p">)</span>
<span class="o"><-</span><span class="nx">done</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"exiting"</span><span class="p">)</span>
<span class="p">}</span>
</pre>
</td>
</tr>
</table>
<table>
<tr>
<td class="docs">
<p>当我们运行这个程序时,它将一直等待一个信号。
通过 <code>ctrl-C</code>(终端显示为 <code>^C</code>),我们可以发送一个 <code>SIGINT</code> 信号,
这会使程序打印 <code>interrupt</code> 然后退出。</p>
</td>
<td class="code">
<pre class="chroma">
<span class="gp">$</span> go run signals.go
<span class="go">awaiting signal
</span><span class="go">^C
</span><span class="go">interrupt
</span><span class="go">exiting</span></pre>
</td>
</tr>
</table>
<p class="next">
下一个例子: <a href="exit">退出</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 (\u000A \"fmt\"\u000A \"os\"\u000A \"os/signal\"\u000A \"syscall\"\u000A)\u000A');codeLines.push('func main() {\u000A');codeLines.push(' sigs :\u003D make(chan os.Signal, 1)\u000A');codeLines.push(' signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)\u000A');codeLines.push(' done :\u003D make(chan bool, 1)\u000A');codeLines.push(' go func() {\u000A');codeLines.push(' sig :\u003D \u003C-sigs\u000A fmt.Println()\u000A fmt.Println(sig)\u000A done \u003C- true\u000A }()\u000A');codeLines.push(' fmt.Println(\"awaiting signal\")\u000A \u003C-done\u000A fmt.Println(\"exiting\")\u000A}\u000A');codeLines.push('');
</script>
<script src="site.js" async></script>
</body>
</html>