-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
318 lines (154 loc) · 59.1 KB
/
atom.xml
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Hexo</title>
<link href="http://example.com/atom.xml" rel="self"/>
<link href="http://example.com/"/>
<updated>2024-05-09T13:04:14.160Z</updated>
<id>http://example.com/</id>
<author>
<name>shenyaoguan</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>gin学习笔记:分组与中间件的组合</title>
<link href="http://example.com/2024/05/07/It's%20mygo!!!!!/gin%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%88%86%E7%BB%84%E4%B8%8E%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E7%BB%84%E5%90%88/"/>
<id>http://example.com/2024/05/07/It's%20mygo!!!!!/gin%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%88%86%E7%BB%84%E4%B8%8E%E4%B8%AD%E9%97%B4%E4%BB%B6%E7%9A%84%E7%BB%84%E5%90%88/</id>
<published>2024-05-07T10:44:17.883Z</published>
<updated>2024-05-09T13:04:14.160Z</updated>
<content type="html"><![CDATA[<p>今天听了一下gin的分组的功能,挺有趣的,记一下</p><h3 id="gin的路由分组功能"><a href="#gin的路由分组功能" class="headerlink" title="gin的路由分组功能"></a>gin的路由分组功能</h3><p>gin中可以对路由进行分组,以便进行一些处理</p><p>比如下面这样</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">r := gin.Default() </span><br><span class="line">v1 := r.Group(<span class="string">"v1"</span>)</span><br></pre></td></tr></table></figure><p>这里就分了一个叫做<code>v1</code>的分组</p><p>这样的分组就有利于我们在使用中间件的时候使用</p><p>这里的分组像一种范畴,这个便于我们对一系列有相似特性的路由进行统一处理。某种意义上也算代码重用的一环</p><h3 id="中间件的使用"><a href="#中间件的使用" class="headerlink" title="中间件的使用"></a>中间件的使用</h3><p>中间件的使用遵循洋葱模型</p><p><img src="https://pic2.zhimg.com/80/v2-c714203a7695b9136a48ab50b217423d_720w.webp" alt="洋葱模型"></p><p>举个例子,比如以下使用中间件</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">middel</span><span class="params">()</span></span> gin.HandlerFunc { </span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">func</span><span class="params">(c *gin.Context)</span></span> { </span><br><span class="line"> fmt.Println(<span class="string">"before"</span>) </span><br><span class="line"> c.Next() </span><br><span class="line"> fmt.Println(<span class="string">"after"</span>) </span><br><span class="line"> } </span><br><span class="line">} </span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">middeltwo</span><span class="params">()</span></span> gin.HandlerFunc { </span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">func</span><span class="params">(c *gin.Context)</span></span> { </span><br><span class="line"> fmt.Println(<span class="string">"before,2"</span>) </span><br><span class="line"> c.Next() </span><br><span class="line"> fmt.Println(<span class="string">"after,2"</span>) </span><br><span class="line"> } </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span>{</span><br><span class="line"><span class="comment">//……</span></span><br><span class="line">v1 := r.Group(<span class="string">"v1"</span>).Use(middel(), middeltwo())</span><br><span class="line">v1.GET(<span class="string">"test"</span>, <span class="function"><span class="keyword">func</span><span class="params">(c *gin.Context)</span></span> { </span><br><span class="line"> fmt.Println(<span class="string">"分了个组"</span>) </span><br><span class="line"> c.JSON(<span class="number">200</span>, gin.H{ </span><br><span class="line"> <span class="string">"message"</span>: <span class="string">"test"</span>, </span><br><span class="line"> <span class="string">"success"</span>: <span class="string">"true"</span>, </span><br><span class="line"> }) </span><br><span class="line">})</span><br><span class="line"><span class="comment">//……</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>如此使用中间件,得到的结果是</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">before</span><br><span class="line">before,2</span><br><span class="line">分了个组</span><br><span class="line">after,2</span><br><span class="line">after</span><br></pre></td></tr></table></figure><p>就像一个洋葱一样,后进先出。</p><p>因此,这里的实现很有可能就是利用了语言自身的函数<strong>堆栈模型</strong></p>]]></content>
<summary type="html"><p>今天听了一下gin的分组的功能,挺有趣的,记一下</p>
<h3 id="gin的路由分组功能"><a href="#gin的路由分组功能" class="headerlink" title="gin的路由分组功能"></a>gin的路由分组功能</h3><p>gin中可以</summary>
<category term="golang" scheme="http://example.com/tags/golang/"/>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
<category term="gin" scheme="http://example.com/tags/gin/"/>
</entry>
<entry>
<title>go 面向对象编程的实现</title>
<link href="http://example.com/2024/05/07/It's%20mygo!!!!!/go%E7%9A%84%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%AE%9E%E7%8E%B0%E5%BD%A2%E5%BC%8F/"/>
<id>http://example.com/2024/05/07/It's%20mygo!!!!!/go%E7%9A%84%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%AE%9E%E7%8E%B0%E5%BD%A2%E5%BC%8F/</id>
<published>2024-05-07T07:41:20.062Z</published>
<updated>2024-05-07T07:42:47.039Z</updated>
<content type="html"><![CDATA[<h2 id="封装"><a href="#封装" class="headerlink" title="封装"></a>封装</h2><h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><h2 id="多态"><a href="#多态" class="headerlink" title="多态"></a>多态</h2>]]></content>
<summary type="html"><h2 id="封装"><a href="#封装" class="headerlink" title="封装"></a>封装</h2><h2 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h2><h2 id</summary>
<category term="golang" scheme="http://example.com/tags/golang/"/>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>go学习笔记:方法</title>
<link href="http://example.com/2024/05/07/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E6%96%B9%E6%B3%95/"/>
<id>http://example.com/2024/05/07/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E6%96%B9%E6%B3%95/</id>
<published>2024-05-07T06:30:01.994Z</published>
<updated>2024-05-07T08:28:08.690Z</updated>
<content type="html"><![CDATA[<h3 id="方法和函数"><a href="#方法和函数" class="headerlink" title="方法和函数"></a>方法和函数</h3><p>在函数声明时,在其名字前面就是一个方法。相当于为这个参数的类型定义了一个独占的方法。</p><p>比如</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> geometry</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"math"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Point <span class="keyword">struct</span>{ X, Y <span class="type">float64</span> }</span><br><span class="line"></span><br><span class="line"><span class="comment">// traditional function</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Distance</span><span class="params">(p, q Point)</span></span> <span class="type">float64</span> {</span><br><span class="line"> <span class="keyword">return</span> math.Hypot(q.X-p.X, q.Y-p.Y)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// same thing, but as a method of the Point type</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p Point)</span></span> Distance(q Point) <span class="type">float64</span> {</span><br><span class="line"> <span class="keyword">return</span> math.Hypot(q.X-p.X, q.Y-p.Y)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中的p是方法的接收器,就和java里面的类的相似(?)</p><p>在这里实现了 OOP 中的<strong>封装</strong></p><h3 id="基于指针对象的方法"><a href="#基于指针对象的方法" class="headerlink" title="基于指针对象的方法"></a>基于指针对象的方法</h3><p>如果一个函数需要更新一个变量,或者其中一个参数过大时,我们会希望避免该变量被默认的拷贝</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Point)</span></span> ScaleBy(factor <span class="type">float64</span>) {</span><br><span class="line"> p.X *= factor</span><br><span class="line"> p.Y *= factor</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中这个函数的名字为<code>(*Point).ScaleBy</code>.这里的括号是必须的;没有括号的话可能会被理解为<code>*(Point.ScaleBy)</code> </p><p><strong>在现实程序中,一般会约定如果Point类中有一个指针作为接收器的方法,那么所有Point的方法都必须有一个指针接收器,即使有些方法不需要</strong></p><p>但是不用担心像C语言一样的麻烦,不管receiver是指针类型还是非指针类型,也不管你使用的是两者之一,编译器都会帮你搞定的(赞美编译器!)</p><h2 id="通过嵌入结构体来拓展类型-实现继承"><a href="#通过嵌入结构体来拓展类型-实现继承" class="headerlink" title="通过嵌入结构体来拓展类型(实现继承)"></a>通过嵌入结构体来拓展类型(实现继承)</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">"image/color"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Point <span class="keyword">struct</span>{ X, Y <span class="type">float64</span> }</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> ColoredPoint <span class="keyword">struct</span> {</span><br><span class="line"> Point</span><br><span class="line"> Color color.RGBA</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中的<code>Point</code>就实现了继承的功能</p>]]></content>
<summary type="html"><h3 id="方法和函数"><a href="#方法和函数" class="headerlink" title="方法和函数"></a>方法和函数</h3><p>在函数声明时,在其名字前面就是一个方法。相当于为这个参数的类型定义了一个独占的方法。</p>
<p>比如</p>
<</summary>
<category term="golang" scheme="http://example.com/tags/golang/"/>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>人月神话学习笔记:</title>
<link href="http://example.com/2024/04/25/Man-Month%20Mythical/%E4%BA%BA%E6%9C%88%E7%A5%9E%E8%AF%9D%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A1/"/>
<id>http://example.com/2024/04/25/Man-Month%20Mythical/%E4%BA%BA%E6%9C%88%E7%A5%9E%E8%AF%9D%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A1/</id>
<published>2024-04-25T02:35:00.354Z</published>
<updated>2024-04-27T03:18:03.886Z</updated>
<content type="html"><![CDATA[<p>书本写作的起因: OS/360的失败</p><p>对于软件开发的比喻:焦油坑</p><h3 id="编程系统产品"><a href="#编程系统产品" class="headerlink" title="编程系统产品"></a>编程系统产品</h3><p>产业化队伍和两人组合产出的差别</p><table><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>编程</td><td>编程系统<br>(接口,系统集成)</td></tr><tr><td>编程产品<br>(通用化,<br> 测试,<br> 文档,<br> 维护)</td><td>编程系统产品</td></tr></tbody></table><p>上面这个四宫格可以清晰的指出普通的程序和真正被现在的社会所需求的产品的区别</p><ul><li><strong>编程产品</strong>: 对用户来说需要考虑可复制性和兼容性,对维护人员来说需要考虑可理解性。这些需要的不只是程序本身,还需要大量的测试和文档,来保证其实现。<strong>成本比其中的程序至少高出3倍</strong></li><li><strong>编程系统</strong>: 需要将程序变成一个构建单元。其中要具有可拓展性和可实现性。必须考虑预先预定的资源限制。同时要考虑不能与其他一些构建单元所冲突,在高复杂度的情况下任然保持健壮。</li></ul><p>而将上述两者结合起来的<strong>编程系统产品</strong>,才是大多数时候,我们的目标</p><h3 id="作为劳动的乐趣"><a href="#作为劳动的乐趣" class="headerlink" title="作为劳动的乐趣"></a>作为劳动的乐趣</h3><blockquote><p>一种创建实物的乐趣</p></blockquote><ol><li>编程中<strong>劳动</strong>的乐趣</li><li>编程中<strong>为他人服务</strong>的乐趣</li><li>编程中<strong>体系建构</strong>的乐趣</li><li>编程中<strong>持续学习</strong>的乐趣</li><li>编程中<strong>容易实现</strong>的乐趣</li></ol><h3 id="作为职业的烦恼"><a href="#作为职业的烦恼" class="headerlink" title="作为职业的烦恼"></a>作为职业的烦恼</h3><ol><li>追求完美时的苦恼(这个也可以作为一种乐趣吧)</li><li>有他人参与的苦恼</li><li></li></ol>]]></content>
<summary type="html"><p>书本写作的起因: OS&#x2F;360的失败</p>
<p>对于软件开发的比喻:焦油坑</p>
<h3 id="编程系统产品"><a href="#编程系统产品" class="headerlink" title="编程系统产品"></a>编程系统产品</h3><p>产业</summary>
<category term="SE" scheme="http://example.com/tags/SE/"/>
</entry>
<entry>
<title>拉康研讨班阅读笔记:《Freud's Papers on Technique》</title>
<link href="http://example.com/2024/04/24/psychoanalysis/%E7%AC%AC%E4%B8%80%E6%9C%9F/"/>
<id>http://example.com/2024/04/24/psychoanalysis/%E7%AC%AC%E4%B8%80%E6%9C%9F/</id>
<published>2024-04-24T12:44:43.228Z</published>
<updated>2024-04-24T13:10:38.727Z</updated>
<content type="html"><![CDATA[<h3 id="对经典精神分析术语的解析"><a href="#对经典精神分析术语的解析" class="headerlink" title="对经典精神分析术语的解析"></a>对经典精神分析术语的解析</h3><ol><li>超我: 一个失去意义的法则,只能通过语言来维系自身</li><li>自我理想: 自我建立的防御有机体, 目的是延长主体的满足</li><li>本我: 不可还原为主题的驱力。不会以定量的攻击性或爱欲性为结果(不同于心理学)</li></ol><h3 id="重要问题"><a href="#重要问题" class="headerlink" title="重要问题"></a>重要问题</h3><p><strong>当我们做精神分析时,我们在做什么</strong></p><p>我们要研讨精神分析技术的所说、所写和所做</p><p>先在有大量的精神分析师沉溺于对比最极端的<strong>概念的游戏</strong></p><p>曾有人认为精神分析是某种双体心理学(two-body psychology),但是精神分析并不应当只囿于处理两个人之间的关系</p><blockquote><p>主体历史的完全重构是对分析进程的基本、构成性的和结构性的要素</p></blockquote><p>对于案例的分析,有趣之点在与个案的独一性</p>]]></content>
<summary type="html"><h3 id="对经典精神分析术语的解析"><a href="#对经典精神分析术语的解析" class="headerlink" title="对经典精神分析术语的解析"></a>对经典精神分析术语的解析</h3><ol>
<li>超我: 一个失去意义的法则,只能通过语言来维系自</summary>
<category term="精神分析" scheme="http://example.com/tags/%E7%B2%BE%E7%A5%9E%E5%88%86%E6%9E%90/"/>
</entry>
<entry>
<title>拉康研讨班阅读笔记:《The Object Relation》</title>
<link href="http://example.com/2024/04/16/psychoanalysis/%E7%AC%AC%E5%9B%9B%E6%9C%9F%E7%A0%94%E8%AE%A8%E7%8F%AD/"/>
<id>http://example.com/2024/04/16/psychoanalysis/%E7%AC%AC%E5%9B%9B%E6%9C%9F%E7%A0%94%E8%AE%A8%E7%8F%AD/</id>
<published>2024-04-16T14:23:16.733Z</published>
<updated>2024-04-16T14:26:42.223Z</updated>
<category term="精神分析" scheme="http://example.com/tags/%E7%B2%BE%E7%A5%9E%E5%88%86%E6%9E%90/"/>
</entry>
<entry>
<title>go学习笔记:Recover捕获异常</title>
<link href="http://example.com/2024/04/16/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%20Recover%E6%8D%95%E8%8E%B7%E5%BC%82%E5%B8%B8/"/>
<id>http://example.com/2024/04/16/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%20Recover%E6%8D%95%E8%8E%B7%E5%BC%82%E5%B8%B8/</id>
<published>2024-04-16T08:44:50.398Z</published>
<updated>2024-04-17T07:17:20.957Z</updated>
<content type="html"><![CDATA[<h5 id="与Panic的关系"><a href="#与Panic的关系" class="headerlink" title="与Panic的关系"></a>与Panic的关系</h5><p>通常来说,不应当处理Panic异常,但是有时候,我们需要在异常中恢复,或者在崩溃前做一些必要的操作。比如,当web服务器遇到未被预料的问题时,在崩溃前应当将所有连接关闭;如果不做任何处理,会使客户端一直处于等待状态,如果web服务器属于开发状态,我们甚至可以将异常信息反馈到客户端,帮助调试。</p><p>如果在deferred函数中调用了内置函数recover,并且定义该defer语句的函数发生了panic异常,recover会使程序从panic中<strong>恢复</strong>,并返回<strong>panic value</strong>。这将导致panic异常的函数不会继续运行,但是能正常返回</p><p>我们以下面这段代码为例子:</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Parse</span><span class="params">(input <span class="type">string</span>)</span></span> (s *Syntax, err <span class="type">error</span>) {</span><br><span class="line"> <span class="keyword">defer</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">if</span> p := <span class="built_in">recover</span>(); p != <span class="literal">nil</span> {</span><br><span class="line"> err = fmt.Errorf(<span class="string">"internal error: %v"</span>, p)</span><br><span class="line"> }</span><br><span class="line"> }()</span><br><span class="line"> <span class="comment">// ...parser...</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中的recover()帮助Parse从Panic中恢复。我们使用err变量接收错误信息,返回给调用者</p><p><strong>注意:</strong> 不要随意recover别人的panic,也不应该试图恢复其他包引起的panic,否则很可能遗留漏洞</p>]]></content>
<summary type="html"><h5 id="与Panic的关系"><a href="#与Panic的关系" class="headerlink" title="与Panic的关系"></a>与Panic的关系</h5><p>通常来说,不应当处理Panic异常,但是有时候,我们需要在异常中恢复,或者在崩溃前做</summary>
<category term="golang" scheme="http://example.com/tags/golang/"/>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>shell的简单学习</title>
<link href="http://example.com/2024/04/11/os/shell%20%E7%9A%84%E7%AE%80%E5%8D%95%E5%AD%A6%E4%B9%A0/"/>
<id>http://example.com/2024/04/11/os/shell%20%E7%9A%84%E7%AE%80%E5%8D%95%E5%AD%A6%E4%B9%A0/</id>
<published>2024-04-11T08:21:35.843Z</published>
<updated>2024-04-12T07:12:39.677Z</updated>
<content type="html"><![CDATA[<h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">your_name="runoob"</span><br></pre></td></tr></table></figure><p>变量的规则与常见脚本语言相似。</p><p><strong>注意</strong>:‘=’两边不要出现空格,否则容易出bug</p><p>其次,可以用语句隐式赋值</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">for file in 'ls /etc'</span><br><span class="line">或</span><br><span class="line">for file in $(ls /etc)</span><br></pre></td></tr></table></figure><h2 id="使用变量"><a href="#使用变量" class="headerlink" title="使用变量"></a>使用变量</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">your_name="haha"</span><br><span class="line">echo $your_name</span><br><span class="line">echo $(your_name)</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span </summary>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
<category term="shell" scheme="http://example.com/tags/shell/"/>
<category term="os" scheme="http://example.com/tags/os/"/>
</entry>
<entry>
<title>go学习笔记:Panic异常</title>
<link href="http://example.com/2024/04/11/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%20Panic%E5%BC%82%E5%B8%B8/"/>
<id>http://example.com/2024/04/11/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%20Panic%E5%BC%82%E5%B8%B8/</id>
<published>2024-04-11T07:41:03.208Z</published>
<updated>2024-04-16T08:44:43.171Z</updated>
<content type="html"><![CDATA[<h5 id="panic简介"><a href="#panic简介" class="headerlink" title="panic简介"></a>panic简介</h5><p>这里的Panic与前面的错误err不同。这里的Panic常常是在运行中出现的,且常常会导致整个程序崩溃。</p><p>一般而言,panic发生时,程序会中断运行,并立刻执行goroutine中被延迟的函数。</p><p>其中,并不是所有的panic异常都来自运行是,直接调用内置的panic函数也会引发panic异常; panic函数接受任何值作为参数。这里可以作为一个排除一切的选项来阻止不应该出现的场景蔓延。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span> s := suit(drawCard()); s {</span><br><span class="line"><span class="keyword">case</span> <span class="string">"Spades"</span>: <span class="comment">// ...</span></span><br><span class="line"><span class="keyword">case</span> <span class="string">"Hearts"</span>: <span class="comment">// ...</span></span><br><span class="line"><span class="keyword">case</span> <span class="string">"Diamonds"</span>: <span class="comment">// ...</span></span><br><span class="line"><span class="keyword">case</span> <span class="string">"Clubs"</span>: <span class="comment">// ...</span></span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line"> <span class="built_in">panic</span>(fmt.Sprintf(<span class="string">"invalid suit %q"</span>, s)) <span class="comment">// Joker?</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>但是建议调用panic函数时要设置合理的前置条件,否则容易滥用。如下面的代码</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Reset</span><span class="params">(x *Buffer)</span></span> {</span><br><span class="line"> <span class="keyword">if</span> x == <span class="literal">nil</span> {</span><br><span class="line"> <span class="built_in">panic</span>(<span class="string">"x is nil"</span>) <span class="comment">// unnecessary!</span></span><br><span class="line"> }</span><br><span class="line"> x.elements = <span class="literal">nil</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h5><p>regexp.Compile函数的功能是将正则表达式编译成有效的函数,如果正则表达式不合法,那么该函数会返回一个错误。其中检查这个错误是不必要且累赘的,</p><p>这是如果我们希望调用Compile函数时检查输入的合法性,就需要使用regexp.MustCompile函数。下面是该函数的实现</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> regexp</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Compile</span><span class="params">(expr <span class="type">string</span>)</span></span> (*Regexp, <span class="type">error</span>) { <span class="comment">/* ... */</span> }</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">MustCompile</span><span class="params">(expr <span class="type">string</span>)</span></span> *Regexp {</span><br><span class="line"> re, err := Compile(expr)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="built_in">panic</span>(err)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> re</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>显然,MustCompile函数不能接受不合法的输入,其中函数名的Must前缀是一种对这类函数的约定,比如template.Must函数。</p><h5 id="例子-1"><a href="#例子-1" class="headerlink" title="例子"></a>例子</h5><p>让我们看下面一串代码</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> f(<span class="number">3</span>)</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">f</span><span class="params">(x <span class="type">int</span>)</span></span> {</span><br><span class="line"> fmt.Printf(<span class="string">"f(%d)\n"</span>, x+<span class="number">0</span>/x) <span class="comment">// panics if x == 0</span></span><br><span class="line"> <span class="keyword">defer</span> fmt.Printf(<span class="string">"defer %d\n"</span>, x)</span><br><span class="line"> f(x - <span class="number">1</span>)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>输出为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">f(3)</span><br><span class="line">f(2)</span><br><span class="line">f(1)</span><br><span class="line">defer 1</span><br><span class="line">defer 2</span><br><span class="line">defer 3</span><br></pre></td></tr></table></figure><p>当f(0)被调用时,发生了panic异常,之前被defer的fmt.Printf被调用,程序中断执行后,panic信息和堆栈信息被输出。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">goroutine 1 [running]:</span><br><span class="line">main.f(0x4be858?)</span><br><span class="line"> /home/shenyaoguan/Code/gin_study/ch5/test.go:10 +0x118</span><br><span class="line">main.f(0x1)</span><br><span class="line"> /home/shenyaoguan/Code/gin_study/ch5/test.go:12 +0xfe</span><br><span class="line">main.f(0x2)</span><br><span class="line"> /home/shenyaoguan/Code/gin_study/ch5/test.go:12 +0xfe</span><br><span class="line">main.f(0x3)</span><br><span class="line"> /home/shenyaoguan/Code/gin_study/ch5/test.go:12 +0xfe</span><br><span class="line">main.main()</span><br><span class="line"> /home/shenyaoguan/Code/gin_study/ch5/test.go:6 +0x18</span><br></pre></td></tr></table></figure><p>我们在下一节将看到,如何是程序从panic中恢复,阻止程序崩溃</p><h5 id="panic信息返回"><a href="#panic信息返回" class="headerlink" title="panic信息返回"></a>panic信息返回</h5><p>为了方便诊断问题,runtime包允许程序员输出堆栈信息,在下面例子中,我们可以通过runtime函数来调用printStack输出信息</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">defer</span> printStack()</span><br><span class="line"> f(<span class="number">3</span>)</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">printStack</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">var</span> buf [<span class="number">4096</span>]<span class="type">byte</span></span><br><span class="line"> n := runtime.Stack(buf[:], <span class="literal">false</span>)</span><br><span class="line"> os.Stdout.Write(buf[:n])</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>这时候要注意,在调试模式下可以看到,printStack先运行,再运行报错</p><p>若将panic机制类比为其他语言异常机制,则会出现疑问,runtime.Stack为何能输出已经被释放函数的星系?事实上,Go的panic机制中,延迟函数的调用是在释放堆栈信息前的</p>]]></content>
<summary type="html"><h5 id="panic简介"><a href="#panic简介" class="headerlink" title="panic简介"></a>panic简介</h5><p>这里的Panic与前面的错误err不同。这里的Panic常常是在运行中出现的,且常常会导致整个程序崩</summary>
<category term="golang" scheme="http://example.com/tags/golang/"/>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>go学习笔记:Deferred函数</title>
<link href="http://example.com/2024/04/09/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9ADeferred%E5%87%BD%E6%95%B0/"/>
<id>http://example.com/2024/04/09/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9ADeferred%E5%87%BD%E6%95%B0/</id>
<published>2024-04-09T07:53:51.143Z</published>
<updated>2024-04-09T08:32:11.738Z</updated>
<content type="html"><![CDATA[<h3 id="Deferred函数"><a href="#Deferred函数" class="headerlink" title="Deferred函数"></a>Deferred函数</h3><p>在以前的findLinks的例子中,http.Get的输出是作为html.Parse的输入。只有当url的内容是html格式时html.Parse才能正常工作,但是实际中,url指向的内容非常丰富,比如图片,纯文本或者其他。如果他们传入html.Parse,显然会产生不良后果。</p><p>比如下面的例子就会在非html时终止运行,返回错误。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">title</span><span class="params">(url <span class="type">string</span>)</span></span> <span class="type">error</span> {</span><br><span class="line"> resp, err := http.Get(url)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="keyword">return</span> err</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// Check Content-Type is HTML (e.g., "text/html;charset=utf-8").</span></span><br><span class="line"> ct := resp.Header.Get(<span class="string">"Content-Type"</span>)</span><br><span class="line"> <span class="keyword">if</span> ct != <span class="string">"text/html"</span> && !strings.HasPrefix(ct,<span class="string">"text/html;"</span>) {</span><br><span class="line"> resp.Body.Close()</span><br><span class="line"> <span class="keyword">return</span> fmt.Errorf(<span class="string">"%s has type %s, not text/html"</span>,url, ct)</span><br><span class="line"> }</span><br><span class="line"> doc, err := html.Parse(resp.Body)</span><br><span class="line"> resp.Body.Close()</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="keyword">return</span> fmt.Errorf(<span class="string">"parsing %s as HTML: %v"</span>, url,err)</span><br><span class="line"> }</span><br><span class="line"> visitNode := <span class="function"><span class="keyword">func</span><span class="params">(n *html.Node)</span></span> {</span><br><span class="line"> <span class="keyword">if</span> n.Type == html.ElementNode && n.Data == <span class="string">"title"</span>&&n.FirstChild != <span class="literal">nil</span> {</span><br><span class="line"> fmt.Println(n.FirstChild.Data)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> forEachNode(doc, visitNode, <span class="literal">nil</span>)</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>其中resp.Body.close调用了多次,为且表title在所有执行路径下都关闭了网络联机(即使函数运行失败),可以使用defer机制让事情变得简单</p><p>只需要在普通函数或者方法的前面加上关键字defer即可,其中要注意,在多条defer语句中,它们执行的顺序与声明顺序<strong>相反</strong></p><p>defer通常用来处理成对的操作</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">title</span><span class="params">(url <span class="type">string</span>)</span></span> <span class="type">error</span> {</span><br><span class="line"> resp, err := http.Get(url)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="keyword">return</span> err</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"> ct := resp.Header.Get(<span class="string">"Content-Type"</span>)</span><br><span class="line"> <span class="keyword">if</span> ct != <span class="string">"text/html"</span> && !strings.HasPrefix(ct,<span class="string">"text/html;"</span>) {</span><br><span class="line"> <span class="keyword">return</span> fmt.Errorf(<span class="string">"%s has type %s, not text/html"</span>,url, ct)</span><br><span class="line"> }</span><br><span class="line"> doc, err := html.Parse(resp.Body)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="keyword">return</span> fmt.Errorf(<span class="string">"parsing %s as HTML: %v"</span>, url,err)</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// ...print doc's title element…</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>还有一些可以采用defer机制,比如对文件的操作</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> ioutil</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ReadFile</span><span class="params">(filename <span class="type">string</span>)</span></span> ([]<span class="type">byte</span>, <span class="type">error</span>) {</span><br><span class="line"> f, err := os.Open(filename)</span><br><span class="line"> <span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">defer</span> f.Close()</span><br><span class="line"> <span class="keyword">return</span> ReadAll(f)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>或者处理互斥锁</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> mu sync.Mutex</span><br><span class="line"><span class="keyword">var</span> m = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="type">string</span>]<span class="type">int</span>)</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">lookup</span><span class="params">(key <span class="type">string</span>)</span></span> <span class="type">int</span> {</span><br><span class="line"> mu.Lock()</span><br><span class="line"> <span class="keyword">defer</span> mu.Unlock()</span><br><span class="line"> <span class="keyword">return</span> m[key]</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="记录被调用情况"><a href="#记录被调用情况" class="headerlink" title="记录被调用情况"></a>记录被调用情况</h5><p>当调试复杂程序时,defer机制常被用于记录何时进入和退出函数,如下例</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">bigSlowOperation</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">defer</span> trace(<span class="string">"bigSlowOperation"</span>)() <span class="comment">// don't forget the extra parentheses</span></span><br><span class="line"> <span class="comment">// ...lots of work…</span></span><br><span class="line"> time.Sleep(<span class="number">10</span> * time.Second) <span class="comment">// simulate slow operation by sleeping</span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">trace</span><span class="params">(msg <span class="type">string</span>)</span></span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> {</span><br><span class="line"> start := time.Now()</span><br><span class="line"> log.Printf(<span class="string">"enter %s"</span>, msg)</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> { </span><br><span class="line"> log.Printf(<span class="string">"exit %s (%s)"</span>, msg,time.Since(start)) </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>每一次bigSlowOperration被调用,程序都会记录函数进入,退出和持续时间。</p><p>注意:<br>这里利用了defer的<strong>即时求值</strong>的性质</p>]]></content>
<summary type="html"><h3 id="Deferred函数"><a href="#Deferred函数" class="headerlink" title="Deferred函数"></a>Deferred函数</h3><p>在以前的findLinks的例子中,http.Get的输出是作为html.P</summary>
<category term="golang" scheme="http://example.com/tags/golang/"/>
<category term="编程学习" scheme="http://example.com/tags/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>go学习笔记:可变参数</title>
<link href="http://example.com/2024/04/09/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0/"/>
<id>http://example.com/2024/04/09/It's%20mygo!!!!!/go%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0/</id>
<published>2024-04-09T07:25:13.802Z</published>
<updated>2024-04-09T07:54:58.803Z</updated>
<content type="html"><![CDATA[<h3 id="可变参数的函数"><a href="#可变参数的函数" class="headerlink" title="可变参数的函数"></a>可变参数的函数</h3><p>这一节主要是研究参数数量可变的函数,比如fmt.Printf</p><p>在声明可变参数函数时,需要在最后一个参数类型前加上省略号,以表示该函数可以接受任意数量的该类型参数.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">sum</span><span class="params">(vals ...<span class="type">int</span>)</span></span> <span class="type">int</span> {</span><br><span class="line"> total := <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> _, val := <span class="keyword">range</span> vals {</span><br><span class="line"> total += val</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> total</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>sum函数就可以返回任意歌int型参数的和</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">fmt.Println(sum()) <span class="comment">// "0"</span></span><br><span class="line">fmt.Println(sum(<span class="number">3</span>)) <span class="comment">// "3"</span></span><br><span class="line">fmt.Println(sum(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>)) <span class="comment">// "10"</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>上边的代码中,调用者隐式的创建一个数组,再把数组的一个切片,作为参数传给被调用函数。 如果函数已经是切片类型的,我们应该在最后一个参数后加上省略符。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">values := []<span class="type">int</span>{<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>}</span><br><span class="line">fmt.Println(sum(values...)) <span class="comment">// "10"</span></span><br></pre></td></tr></table></figure><p>其中要注意,虽然…int型参数的行为像切片类型,但是其实不同</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">f</span><span class="params">(...<span class="type">int</span>)</span></span> {}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">g</span><span class="params">([]<span class="type">int</span>)</span></span> {}</span><br><span class="line">fmt.Printf(<span class="string">"%T\n"</span>, f) <span class="comment">// "func(...int)"</span></span><br><span class="line">fmt.Printf(<span class="string">"%T\n"</span>, g) <span class="comment">// "func([]int)"</span></span><br></pre></td></tr></table></figure><p>其中,可变阐述经常用于格式化字符串,比如下面的errorf函数</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">errorf</span><span class="params">(linenum <span class="type">int</span>, format <span class="type">string</span>, args ...<span class="keyword">interface</span>{})</span></span> {</span><br><span class="line"> fmt.Fprintf(os.Stderr, <span class="string">"Line %d: "</span>, linenum)</span><br><span class="line"> fmt.Fprintf(os.Stderr, format, args...)</span><br><span class="line"> fmt.Fprintln(os.Stderr)</span><br><span class="line">}</span><br><span class="line">linenum, name := <span class="number">12</span>, <span class="string">"count"</span></span><br><span class="line">errorf(linenum, <span class="string">"undefined: %s"</span>, name) <span class="comment">// "Line 12: undefined: count"</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html"><h3 id="可变参数的函数"><a href="#可变参数的函数" class="headerlink" title="可变参数的函数"></a>可变参数的函数</h3><p>这一节主要是研究参数数量可变的函数,比如fmt.Printf</p>
<p>在声明可变参数函数时,需</summary>
</entry>
<entry>
<title>test</title>
<link href="http://example.com/2024/04/08/test/"/>
<id>http://example.com/2024/04/08/test/</id>
<published>2024-04-08T11:22:15.062Z</published>
<updated>2024-04-08T11:33:48.289Z</updated>
<content type="html"><![CDATA[<p>This is a test article.</p><h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="2"><a href="#2" class="headerlink" title="2"></a>2</h2><h3 id="3"><a href="#3" class="headerlink" title="3"></a>3</h3>]]></content>
<summary type="html"><p>This is a test article.</p>
<h1 id="1"><a href="#1" class="headerlink" title="1"></a>1</h1><h2 id="2"><a href="#2" class="headerlink" tit</summary>
</entry>
<entry>
<title>Hello World</title>
<link href="http://example.com/2024/04/08/hello-world/"/>
<id>http://example.com/2024/04/08/hello-world/</id>
<published>2024-04-08T10:11:49.884Z</published>
<updated>2024-04-08T10:11:49.884Z</updated>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
<summary type="html"><p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for</summary>
</entry>
</feed>