-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
554 lines (285 loc) · 167 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
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Wind13's Blog</title>
<link href="/atom.xml" rel="self"/>
<link href="http://wind13.github.io/"/>
<updated>2019-10-28T23:32:40.000Z</updated>
<id>http://wind13.github.io/</id>
<author>
<name>Simon J S Wind13 Liu</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>如何用写代码的方式谈恋爱</title>
<link href="http://wind13.github.io/2019/10/07/how-to-love-like-code/"/>
<id>http://wind13.github.io/2019/10/07/how-to-love-like-code/</id>
<published>2019-10-07T03:27:59.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<p><img src="/images/shallwetalk.jpg" alt="shall we talk"></p><p><a href="https://mp.weixin.qq.com/s/gS7bRSo3g1QehLFhdeg4aw" target="_blank" rel="noopener">个人同步公众号文章</a> (内含歌曲 QQ 视频)</p><p>我们做编程的男士,都被贴上了“直男”的标签,整天都跟电脑打交道,喜欢看着代码一行一行的,但是面对女孩儿就显得很笨拙了,那有没有一种谈恋爱的方式是象写代码一样呢?这是个有趣的问题。</p><p>一般人只要有小学五年级以上的知识水平就可以开始学习编程了,然而正式谈恋爱通常都是上大学以后了。喜欢编程的男孩子通常谈恋爱更晚些,因为太少关注周边的人了,一脑子都是代码和程序,通常还是女孩儿主动表达好感才后知后觉地“被动”接受的。</p><p>不过话说回来,现在编程小哥还是挺受一些女孩青睐的,这方面编程直男们还是要有自信心的。</p><p>其实跟女孩子相处也没有想象中那么困难,具体当然也要看女孩是什么样的性格,自己是什么样的性格,天下肯定没有任何两段恋爱是相同的,各有各的特点。总得来说呢,我想编程小哥们的优势自然是真诚而专一了,与人相处,与女朋友相处,都是要以这个为基础的。就好像我们都喜欢编程一样,如果有这样的女孩,让你有类似的感觉,那恭喜你找到了,好好珍惜,好好相处。</p><p>同时,要多了解女孩子的心理特征,要读一些相关的书籍或文章,这就好像我们学一项编程技术,总是先看一些书籍或官方文档一样。这方面除了看书和文章之外,主要还是要从两个人的相处和聊天来感觉,不要打字聊天,尽量多见面、视频、音频聊天。要知道男孩儿是用眼睛谈恋爱,而女孩儿是用耳朵谈恋爱的。女孩儿见你的时候会收拾打扮一下,你见女孩儿的时候,要多想一些聊天的话题,适当地还要来点甜言蜜语啦。就象题图上那句歌词所说:若沉默似金,还谈什么恋爱?编程直男们,一定不能太沉默哦!</p><p>可以多约在一起做一些事情,不一定局限在吃饭、看电影,互相帮忙做一些事情或者出去旅游等,不一定要去很远的地方,可以就在城市的周边逛逛,或者去那类有吃、有玩、有购物的大商城逛也不错。需要叮嘱一件事,很多刚开始恋爱的编程小哥有个误区就是特别想给女孩花大钱,这点会造成几方面的问题:</p><ul><li>女孩儿跟你还没到一定的阶段,不好接受太过贵重的礼物,如果接受的话,可能显得自己太过拜金,而不接受的话,你已经购买了,也很为难。</li><li>有时冲动会超出自己的经济承受能力。</li><li>如果后面两个人要分开了,这些都会加重自己的伤害和损失厌恶的感觉。</li></ul><p>其实年轻男女在一起是很美好的,要多了解对方的生活、喜好等,这样也许一些不贵的小礼物,就可以让双方非常开心了,另外,我们都知道自己写的代码不一定是最好的,但却是自己最关心的,所以一些自己用心制作的东西,其实更能感动女孩儿的心。</p><p>大多数人都算是平凡的,你心中的女神其实也是一样,好像我们学习一种语言一样,初次接触会觉得很惊艳,心中会有很多的憧憬,同时也觉得要掌握它很不容易,还有很长的路要走,然而当你逐渐深入学习后,就会理解得更多,也就逐渐感觉并没有那么困难了,同时也就慢慢地产生依赖,离不开它了。女朋友也是这样,最初的接触会觉得非常美好但却有点高不可攀,然而随着相处的时间的更多,你们便会越来越相互了解,越来越归于平淡,同时又会变得互相依赖,彼此无法分离。</p><p>恋爱的最终目标当然是婚姻,然而并不是每一段恋爱都会走到婚姻,年轻人谈几次失败的恋爱也不是什么大问题,然而就象是我们做编程项目一样,失败了要从中总结经验教训,要不断地改善自己才行。每一个成功的软件产品都不是一天、两天就能完成的,都需要成年累月的不懈努力才能做成,恋爱也是一样,不要指望一两次的见面就已经是真正的男女朋友了,感情其实是很脆弱的,两个人还是要多相处一些时候,多经历一些风雨,多了解一些彼此,才能算是初步建立了男女朋友关系,后面还要不断相处,不断互相了解,直到彼此都非常信任了以后,才能彼此确立为男女朋友,再相处一段时间后,双方家庭有了初步的接触,彼此的经济基础都已经准备得差不多了,才可以正式谈婚论嫁。</p><p>文后,附上一个小彩蛋:<a href="https://zhuanlan.zhihu.com/p/58799684" target="_blank" rel="noopener">给你三行代码的恋爱~</a>,这是知乎上的一篇文章,列举了很多用代码表达爱情的小段子。</p>]]></content>
<summary type="html">
<p><img src="/images/shallwetalk.jpg" alt="shall we talk"></p>
<p><a href="https://mp.weixin.qq.com/s/gS7bRSo3g1QehLFhdeg4aw" target="_blank
</summary>
<category term="love" scheme="http://wind13.github.io/tags/love/"/>
<category term="code" scheme="http://wind13.github.io/tags/code/"/>
</entry>
<entry>
<title>Rust Learning</title>
<link href="http://wind13.github.io/2019/10/04/rust-learning/"/>
<id>http://wind13.github.io/2019/10/04/rust-learning/</id>
<published>2019-10-04T01:32:49.000Z</published>
<updated>2019-10-28T23:41:00.000Z</updated>
<content type="html"><![CDATA[<h1 id="Rust-Learning"><a href="#Rust-Learning" class="headerlink" title="Rust Learning"></a>Rust Learning</h1><h2 id="References"><a href="#References" class="headerlink" title="References"></a>References</h2><ul><li><a href="https://zhuanlan.zhihu.com/p/58134018" target="_blank" rel="noopener">Julia、Rust、F#、Go编程语言游览和感想</a></li><li><a href="https://www.bilibili.com/video/av29588248?seid=14346041965114251492" target="_blank" rel="noopener">Rust, Julia, and Go_ Disruptive New Programming Languages Changing the Face of C</a></li><li>新兴的函数式编程语言(如 Elixir 或 Elm)</li><li>从实际应用角度来看,Rust更偏向于底层,旨在替换C语言与C++,Golang旨在替换Java与C#。</li><li>Rust语言本身不依赖于虚拟机与GC,没有运行时,跨平台,主要靠一套所有权、生命周期、类型系统维护着语言的本身,语言高度抽象。</li><li><a href="https://golang.org" target="_blank" rel="noopener">Golang</a> 语言需要依赖于GC,自动垃圾回收,自带协程,快速编译,跨平台。</li><li><a href="https://www.rust-lang.org/" target="_blank" rel="noopener">Rust</a> 是一门入门门槛较高的语言,所有权与生命周期阻碍了不知多少的编程者。而go语言,入门较容易,学过类C语言同学,基本看一下语法就能入手写代码。<ul><li><a href="https://doc.rust-lang.org/book/" target="_blank" rel="noopener">Rust Book</a></li><li><a href="https://doc.rust-lang.org/stable/rust-by-example/" target="_blank" rel="noopener">Rust by Example</a></li><li><a href="https://github.com/rust-lang/rustlings" target="_blank" rel="noopener">Rustlings</a> Small exercises to get you used to reading and writing Rust code!</li><li><a href="https://doc.rust-lang.org/book/title-page.html" target="_blank" rel="noopener">The Rust Programming Language</a></li><li><a href="https://doc.rust-lang.org/cargo/index.html" target="_blank" rel="noopener">The Cargo Book</a></li><li><a href="https://play.rust-lang.org/help" target="_blank" rel="noopener">The Rust Playground</a></li></ul></li><li><a href="https://rust.cc/" target="_blank" rel="noopener">Rust.cc Rust语言中文社区</a></li><li><a href="https://rustforce.net/" target="_blank" rel="noopener">Rust Force CN</a></li><li><a href="https://www.manning.com/livevideo/rust-in-motion" target="_blank" rel="noopener">Rust in Motion</a> Need to buy $39.99</li></ul><h3 id="Web"><a href="#Web" class="headerlink" title="Web"></a>Web</h3><ul><li><a href="https://rocket.rs/" target="_blank" rel="noopener">Rocket</a> is a web framework for Rust with flexibility, usability, or type safety.<ul><li>Ruby and <a href="http://rubyonrails.org/" target="_blank" rel="noopener">Rails</a></li><li><a href="https://haskell-lang.org/" target="_blank" rel="noopener">Haskell</a> and <a href="https://www.yesodweb.com/" target="_blank" rel="noopener">Yesod</a></li><li><a href="https://www.python.org/" target="_blank" rel="noopener">Python</a> and <a href="http://bottlepy.org/docs/dev/index.html" target="_blank" rel="noopener">Bottle</a> or <a href="https://palletsprojects.com/p/flask/" target="_blank" rel="noopener">Flask</a></li></ul></li><li><a href="http://ironframework.io/" target="_blank" rel="noopener">IRON</a> extensible web framework for rust</li></ul><h3 id="GUI"><a href="#GUI" class="headerlink" title="GUI"></a>GUI</h3><ul><li><a href="https://github.com/PistonDevelopers/conrod" target="_blank" rel="noopener">conrod</a> An easy-to-use, 2D GUI library written entirely in Rust.</li><li><a href="https://github.com/xi-editor/druid" target="_blank" rel="noopener">druid</a> Data-oriented Rust UI design toolkit.</li><li><a href="https://github.com/rust-native-ui/libui-rs" target="_blank" rel="noopener">libui-rs</a> Rust bindings to the minimalist, native, cross-platform UI toolkit <code>libui</code></li><li><a href="https://areweguiyet.com/" target="_blank" rel="noopener">Are we GUI Yet?</a></li></ul><h3 id="Other"><a href="#Other" class="headerlink" title="Other"></a>Other</h3><ul><li><a href="https://www.bilibili.com/video/av12818669/" target="_blank" rel="noopener">[oeasy]教您玩转rust编程视频教程</a></li><li><a href="https://zhuanlan.zhihu.com/p/53064186" target="_blank" rel="noopener">使用Rust编写操作系统(一):独立式可执行程序</a><ul><li>不能使用线程、文件、堆内存、网络、随机数、标准输出,或其它任何需要操作系统抽象和特定硬件的特性;</li><li>可以使用迭代器、闭包、模式匹配、Option、Result、字符串格式化,当然还有所有权系统。</li><li>需要创建一个独立于操作系统的可执行程序,被称作独立式可执行程序(freestanding executable)或裸机程序(bare-metal executable)。</li><li>独立式可执行程序并不能访问Rust运行时或crt0库,需要定义自己的入口点,即重写整个crt0库和它定义的入口点。</li></ul></li><li>Rust与go在网上吵的比较大区别是,Rust有泛型,而Go没有。</li><li>做网络服务选Go, 上手比较简单。做系统用Rust, 它就是未来的系统语言。</li><li><a href="http://wiki.jikexueyuan.com/project/rust-primer/ffi/compiling-rust-to-lib.html" target="_blank" rel="noopener">将Rust编译成库</a></li><li><a href="https://www.cnblogs.com/chenxizhang/p/4760674.html" target="_blank" rel="noopener">Rust初步(六):在C#中使用Rust组件</a></li><li><a href="https://www.oschina.net/translate/rust-vs-cpp" target="_blank" rel="noopener">Rust vs. C++:性能大比拼</a></li><li><a href="https://blog.csdn.net/xiangxianghehe/article/details/53471936" target="_blank" rel="noopener">如何利用科大源提速Cargo和Rust</a></li><li><a href="https://os.phil-opp.com/" target="_blank" rel="noopener">Writing an OS in Rust</a></li><li><a href="https://web.stanford.edu/class/cs140e/" target="_blank" rel="noopener">CS140E: Operating Systems Design and Implementation</a></li><li><a href="https://zhuanlan.zhihu.com/c_1078248076300521472" target="_blank" rel="noopener">一个Rust OS的专栏</a></li><li><a href="https://julialang.org/" target="_blank" rel="noopener">Julia</a> 是新晋发布1.0版本的科学计算类语言,号称兼具C++、python、matlab的优点。</li><li><a href="https://antkillerfarm.github.io/language/2019/07/25/kid_program.html" target="_blank" rel="noopener">孩子的编程语言</a></li><li><a href="https://blog.csdn.net/yihuliunian/article/details/93874487" target="_blank" rel="noopener">V 语言强势登顶 GitHub TOP1,难道要取 Go 而代之?</a></li><li><a href="https://vlang.io/" target="_blank" rel="noopener">vlang</a><ul><li><a href="https://vlang.io/compare" target="_blank" rel="noopener">Comparison of V and Other Languages</a></li></ul></li></ul><h2 id="Learn-web"><a href="#Learn-web" class="headerlink" title="Learn web"></a>Learn web</h2><ul><li><a href="https://developer.mozilla.org/zh-CN/" target="_blank" rel="noopener">MDN web docs</a></li></ul><h2 id="Key-points"><a href="#Key-points" class="headerlink" title="Key points"></a>Key points</h2><ul><li>理解所有权:<a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html" target="_blank" rel="noopener">What is Ownership</a><ul><li>Copy</li><li>Move</li><li>Clone</li></ul></li><li>理解引用和借用:<a href="https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html?highlight=borrow#references-and-borrowing" target="_blank" rel="noopener">References and Borrowing</a><ul><li>& 引用</li><li>(&) 借用<ul><li><blockquote><p>We call having references as function parameters <em>borrowing</em></p></blockquote></li><li>我们称“将引用作为函数参数”为“借用”</li></ul></li><li><ul><li>解引用</li></ul></li></ul></li></ul><h3 id="数据竞争"><a href="#数据竞争" class="headerlink" title="数据竞争"></a>数据竞争</h3><blockquote><p>对于所有的类型T和任意的生命周期参数‘a,都能衍生出两种类型:&’a T 和 &mut ‘a T。</p></blockquote><blockquote><p>&’a T 相当于T的读取器,持有T的读锁, &mut ‘a T 相当于T的写入器,持有T的写锁。</p></blockquote><blockquote><p>编译器里有一个工具borrowck,在编译时会自动检查这两种类型的使用情况,如果有非法的使用,就报错,不让你编译通过。同样地,当你手中还持有着对一个值的引用时,编译器不允许将其移动或者销毁。这样,就杜绝了野指针现象和数据竞争问题。</p></blockquote><figure class="highlight rust"><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"><span class="keyword">let</span> rb0 = &b;</span><br><span class="line"><span class="keyword">let</span> rb1 = &<span class="keyword">mut</span> b;</span><br></pre></td></tr></table></figure><h3 id="值传递"><a href="#值传递" class="headerlink" title="值传递"></a>值传递</h3><blockquote><p>Rust 的默认的值的传递是:转移。不管是赋值还是函数调用时的参数和返回值,都是这样。</p></blockquote><h3 id="分类体系-taxonomy"><a href="#分类体系-taxonomy" class="headerlink" title="分类体系(taxonomy)"></a>分类体系(taxonomy)</h3><blockquote><p>开放的分类,使用泛型;封闭的分类,使用枚举(ADT)。</p></blockquote><h4 id="开放的全分类:Type-Trait"><a href="#开放的全分类:Type-Trait" class="headerlink" title="开放的全分类:Type + Trait"></a>开放的全分类:Type + Trait</h4>]]></content>
<summary type="html">
<h1 id="Rust-Learning"><a href="#Rust-Learning" class="headerlink" title="Rust Learning"></a>Rust Learning</h1><h2 id="References"><a href="
</summary>
<category term="rust" scheme="http://wind13.github.io/tags/rust/"/>
<category term="golang" scheme="http://wind13.github.io/tags/golang/"/>
<category term="julia" scheme="http://wind13.github.io/tags/julia/"/>
<category term="vlang" scheme="http://wind13.github.io/tags/vlang/"/>
</entry>
<entry>
<title>编程自立之道</title>
<link href="http://wind13.github.io/2019/10/02/programming-dao/"/>
<id>http://wind13.github.io/2019/10/02/programming-dao/</id>
<published>2019-10-02T04:58:25.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h1 id="编程自立之道"><a href="#编程自立之道" class="headerlink" title="编程自立之道"></a>编程自立之道</h1><p>在开始之前,有耐心的朋友可以先看一下这篇 InfoQ 翻译的文章<a href="https://mp.weixin.qq.com/s/bhuvkIjQ7StX93HidBU-iw" target="_blank" rel="noopener">从第1行代码到百万年薪 ,我是如何在8个月内做到的?</a>,英文原文在此:<a href="http://www.swejobsearch.com/" target="_blank" rel="noopener">How I Went from First Line of Code to $226K Job Offer in 8 Months</a>,没耐心的我可以简要介绍内容如下:</p><p>作者 Jason Zedde 在 2018年6月24日写下了第一行 JavaScript 代码,当时他有一个经济学学位,做过三年管理顾问,但在7月29日面临两个选择:</p><ul><li>进入一家高速增长的广告技术公司,担任 Chief of Staff(类似副总或办公室主任的职位,参考<a href="https://chuansongme.com/n/867574" target="_blank" rel="noopener">这个介绍</a>和<a href="https://zhuanlan.zhihu.com/p/19685349" target="_blank" rel="noopener">这个知乎</a>,即赚钱又稳定)</li><li>参加一家 Hack Reactor 的编程“训练营”</li></ul><p>作者同时接到了广告技术公司的录用通知和训练营入学考试通过的通知,结果作者经过了72小时的反省,考虑过手头有训练结束后还可以承受三个月的房租和食物费用,由于对技术挑战的喜爱,做出了一个不理性的决定,选择了参加那个编程“训练营”。之后作者在几个月的时间里,每天安排好学习和休息时间,高度优化利用大脑和时间,到12月7日完成了 Hack Reactor 的训练和助教工作,然后又进行了科学而技巧地面试(申请44家,41次面试推荐,14次编码邀请或技术电话面试,8次现场面试,7次录用通知)和谈薪资,最终答应了非常满意的 Lyft 的 $22.6万美元的工作。</p><p>文中讲了很多作者的心路历程、时间管理经验、面试谈薪经验等。虽然大多数人不一定能做到象作者那样优秀,但我觉得还是有很多方面都是可以借鉴的,至少是会对当下的自己有所帮助的。同时我也想说明一件事情,就是编程的学习其实是可以在很短时间达到很好的能力水平的,作者就是一个真实的案例,仅用几个月的时间就从第一行代码的小白达到了可以应聘世界顶级软件公司的水平,这中间自然有很多他个人的能力优势,如英语、高学位、高智商、极强的执行力、时间管理和科学学习方法等。不过就普通人来说,也不是不可能的,别人用半年,我们用一年,只要有持续的兴趣和热情,加上方法得当,应该也是可以有所成就的。</p><p>现在我就想做这样一件事情,以我的经验来帮助年轻人掌握学习、工作和生活的智慧,提升自己的编程以及各方面综合能力,不保证能大富大贵,但是能够自立在社会上,做自己感兴趣的、有意义的、有价值的事,对大众有益、对社会有所贡献。</p><p>我是75年生人,已过不惑之年,工作了很多年,前一份工作的职位是架构师,不过自认为也就是高级程序员而已,水平也很有限,深知山外有山、人外有人。</p><p>如今有段闲暇时间,就想记录一下自己这些年的编程学习和生活自立之道,收一些徒弟,希望能对一些年轻人有所帮助。也许你会想我这水平也好意思收徒弟?没关系,水平高的我不敢收,我还要向人家学习呢,我就收一些水平一般的小白就可以了,人总是有一个成长的过程的,谁都当过小白,况且当师父也不一定要水平多高,很多高人当年从师的人也都是平凡人而已。好像《射雕英雄传》里郭靖也是从江南七侠那开始学艺的,《绝代双骄》中的江小鱼也是从恶人谷的四大恶人那儿开始学艺的。所以说师父的水平不一定要最高,主要看徒弟自己的天赋和悟性了,正所谓“师父领进门,学艺在个人”,当然为师者要有一些见识和教育方法。</p><p>我是本科学历,医学院药学专业,可想而知我走上编程这条路绕了多大的弯子。从平面设计到网页设计,到 Java 开发,到前端开发等,中间学习了无数的技术知识,接触了无数的类库框架,这中间又不知浪费了多少无用的功夫,所以想开这个学堂收徒,也是有这样的发心,希望能给年轻人指条明路,少走些弯路,少费些无用功。在这个学堂里,不只是教编程方面的经验,还有很多个人生活、工作、投资等方面的感悟和教训,相信年轻人少走错一些,就少损失一些,就会多积累一些,这样带来的收益,应该远比我设置的这个年费价值大多了。首批学徒一年收¥1300 元,越早的学徒,越优先教导、个性化教导,毕竟初期人员少,更有时间耐心地沟通。后期积累的资料多了,内容丰富了,自然价格也会慢慢提高,所以现在这个可谓之“早鸟价”。零基础也可以教,只是学的时间会相对更长,一年年续费,长期保持师徒关系,终身学习、终身成长。</p><p>我这个学堂并不同于网上的一些标准课程什么的,对于最早的一些学员,还有一个好处是可以依照学员当前的水平和悟性进行教学,可以保证学得又轻松又高效,后期的也许无法保证了,不过到时候看有没有学徒能成长为“大师兄”帮着教了,哈哈……同时,我的教学不保证考试或证书,也不保证面试或应聘,只教会心法和技能,所谓的真本事,而不是那些表面文章。那类的课程,自然有很多的培训班或线上平台在做了,想学的话花点钱报名就是了。</p><p>综上所述,我的世风十三学堂,不保证你能成功、成名,发财致富,但会教你人生大道,心法技能,自立于这个世界,不走太多弯路,不掉太多坑,编程方面掌握不过时的技术和本领,与时俱进,终身成长!</p><p><img src="/images/zsxq.png" alt="知识星球-世风十三学堂"></p>]]></content>
<summary type="html">
<h1 id="编程自立之道"><a href="#编程自立之道" class="headerlink" title="编程自立之道"></a>编程自立之道</h1><p>在开始之前,有耐心的朋友可以先看一下这篇 InfoQ 翻译的文章<a href="https://mp.we
</summary>
<category term="learn" scheme="http://wind13.github.io/tags/learn/"/>
</entry>
<entry>
<title>函数式编程资料收集</title>
<link href="http://wind13.github.io/2019/09/18/functional-programming-ref/"/>
<id>http://wind13.github.io/2019/09/18/functional-programming-ref/</id>
<published>2019-09-18T03:27:21.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><ul><li><a href="http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html" target="_blank" rel="noopener">函数式编程入门教程(阮一峰)</a> 回答了为什么要用函数式编程思维?</li><li><a href="https://www.jdon.com/functional.html" target="_blank" rel="noopener">面向函数范式编程(Functional programming)</a> 说明了对面向对象编程的区别的关系,是可以互补共用的。</li><li><a href="https://www.jianshu.com/p/4bf39816e786" target="_blank" rel="noopener">Kotlin极简教程:第8章 函数式编程</a> 其中 Y组合子(Y - Combinator) ——匿名递归函数,解决匿名函数如何递归的问题。以及很多 Kotlin 的函数式编程语法。</li><li>强烈推荐以下两本书:<ul><li><a href="https://leanpub.com/javascript-allonge" target="_blank" rel="noopener">《JavaScript Allonge》</a> by Reginald Braithwaite</li><li><a href="http://shop.oreilly.com/product/0636920028857.do" target="_blank" rel="noopener">《Functional JavaScript》</a> by Michael Fogus</li></ul></li><li><a href="https://www.infoq.cn/article/b6gkx1crp2umU2*jIPQB" target="_blank" rel="noopener">不要再尝试函数式编程了</a> 一篇反讽的文章,其实在说函数式编程的好处,以及 OOP 的一些问题。</li></ul><h2 id="TypeScript-JavaScript"><a href="#TypeScript-JavaScript" class="headerlink" title="TypeScript/JavaScript"></a>TypeScript/JavaScript</h2><ul><li><a href="http://swannodette.github.io/mori/" target="_blank" rel="noopener">mori</a> A library for using ClojureScript’s persistent data structures and supporting API from the comfort of vanilla JavaScript.</li><li><a href="https://linux.cn/article-7842-1.html" target="_blank" rel="noopener">函数式 TypeScript</a></li><li><a href="https://gcanti.github.io/fp-ts" target="_blank" rel="noopener">fp-ts</a><ul><li><a href="https://gcanti.github.io/fp-ts/recipes/ramda" target="_blank" rel="noopener">Migrate from Ramda</a></li><li><a href="https://gcanti.github.io/fp-ts/type-classes.svg" target="_blank" rel="noopener">fp-ts type classes svg</a></li></ul></li><li><a href="https://rxmarbles.com/" target="_blank" rel="noopener">rxmarbles</a></li><li><a href="http://www.cnblogs.com/android-blogs/p/5586395.html" target="_blank" rel="noopener">响应式编程,是明智的选择</a></li><li><a href="https://juejin.im/entry/5a4313ef5188255de57e0a18" target="_blank" rel="noopener">掘金——响应式编程,是明智的选择</a></li></ul><h2 id="ClojureScript"><a href="#ClojureScript" class="headerlink" title="ClojureScript"></a>ClojureScript</h2><ul><li><a href="https://cursive-ide.com/" target="_blank" rel="noopener">Cursive</a> The Clojure(Script) IDE that understands your code.</li><li><a href="https://github.com/anmonteiro/lumo" target="_blank" rel="noopener">lumo</a> Fast, cross-platform, standalone ClojureScript environment</li><li><a href="http://shadow-cljs.org/" target="_blank" rel="noopener">shadow-cljs</a> ClojureScript compilation made easy!</li><li><a href="http://cljs-book.clj.im/" target="_blank" rel="noopener">ClojureScript 入门指南</a></li><li><a href="https://github.com/omcljs/om" target="_blank" rel="noopener">Om</a> A ClojureScript UI framework and client/server architecture over Facebook’s React.</li></ul><h2 id="Lua"><a href="#Lua" class="headerlink" title="Lua"></a>Lua</h2><h3 id="Using"><a href="#Using" class="headerlink" title="Using"></a>Using</h3><ul><li><a href="https://github.com/moriyalb/lamda" target="_blank" rel="noopener">Lamda</a></li><li><a href="https://github.com/bjornbytes/RxLua" target="_blank" rel="noopener">bjornbytes/RxLua</a><ul><li><a href="https://github.com/bjornbytes/RxLua/blob/master/tests/observable.lua" target="_blank" rel="noopener">example of observable</a></li></ul></li></ul><h3 id="Ref"><a href="#Ref" class="headerlink" title="Ref"></a>Ref</h3><ul><li><a href="http://yonaba.github.io/Moses/" target="_blank" rel="noopener">Moses</a> Utility library for functional programming in Lua. Like Lodash of Lua.</li><li><a href="https://github.com/lxsmnsyc/rxlua" target="_blank" rel="noopener">lxsmnsyc/RxLua</a> Not ready for production.</li><li><a href="https://github.com/mrunderhill89/bacon.lua" target="_blank" rel="noopener">bacon.lua</a></li><li><a href="http://lua-users.org/" target="_blank" rel="noopener">lua-users</a></li></ul><h2 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h2><ul><li><a href="https://github.com/agiledragon/gomonkey" target="_blank" rel="noopener">gomonkey</a> is a library to make monkey patching in unit tests easy. 单元测试打桩框架</li><li><a href="http://www.minetest.net/" target="_blank" rel="noopener">minetest</a> 我的世界开发框架<ul><li><a href="https://github.com/davisonio/bacon" target="_blank" rel="noopener">Bacon</a> mod for Minetest</li></ul></li></ul><h2 id="Java-8"><a href="#Java-8" class="headerlink" title="Java 8"></a>Java 8</h2><p>Java 8 才算是真的提高到函数式编程语言了,见以下这些资料:</p><ul><li><a href="https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/" target="_blank" rel="noopener">Java 8 中的 Streams API 详解</a></li><li><a href="http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/" target="_blank" rel="noopener">Java 8 Stream Tutorial</a></li></ul><h3 id="fn-rx"><a href="#fn-rx" class="headerlink" title="fn + rx"></a>fn + rx</h3><ul><li><a href="https://medium.com/@ome450901/rxjava2-%E4%BA%8C%E4%B8%89%E5%9B%9B%E4%BA%94%E5%85%AD%E8%A8%AA-29b6ab624ab2" target="_blank" rel="noopener">Rxjava2 二三四五六訪</a></li><li><a href="https://www.functionaljava.org/" target="_blank" rel="noopener">Functional Java</a> is an open source library facilitating functional programming in Java.</li><li><a href="https://blog.csdn.net/u011200604/article/details/70208756" target="_blank" rel="noopener">用RxJava实现Rxbus替换EventBus事件总线</a></li></ul><h2 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h2><ul><li><a href="https://www.liaoxuefeng.com/wiki/897692888725344/923030136026784" target="_blank" rel="noopener">Python 2.7 函数式编程(廖雪峰)</a></li></ul><h2 id="Rx-js"><a href="#Rx-js" class="headerlink" title="Rx.js"></a>Rx.js</h2><ul><li><a href="https://medium.com/@jvdheijden/rxjs-throttletime-debouncetime-and-audittime-explained-in-examples-c393178458f3" target="_blank" rel="noopener">RxJS throttleTime, debounceTime and auditTime explained in examples</a></li></ul>]]></content>
<summary type="html">
<h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><ul>
<li><a href="http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html
</summary>
<category term="函数式编程" scheme="http://wind13.github.io/tags/%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/"/>
</entry>
<entry>
<title>当日笔记-20080925</title>
<link href="http://wind13.github.io/2018/09/25/daily-note-20080925/"/>
<id>http://wind13.github.io/2018/09/25/daily-note-20080925/</id>
<published>2018-09-25T08:25:28.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="小程序"><a href="#小程序" class="headerlink" title="小程序"></a>小程序</h2><ul><li><a href="https://github.com/lcxfs1991/blog/issues/28" target="_blank" rel="noopener">小程序的全栈开发新时代</a></li></ul><h2 id="数学"><a href="#数学" class="headerlink" title="数学"></a>数学</h2><ul><li><a href="https://mp.weixin.qq.com/s/rlUUXVEinbeH4aQ0g2SGXA" target="_blank" rel="noopener">读懂世纪难题“黎曼猜想”和其历史</a></li><li><a href="https://mp.weixin.qq.com/s/LKu7wWcpwbzBTU5t72m9Dw" target="_blank" rel="noopener">黎曼猜想仍旧,素数依然孤独</a></li><li><a href="https://zhuanlan.zhihu.com/p/25055731" target="_blank" rel="noopener">黎曼猜想,及其解释(上)</a></li><li><a href="https://zhuanlan.zhihu.com/p/25222934" target="_blank" rel="noopener">黎曼猜想,及其解释(下)</a></li></ul><h3 id="神奇而有趣的素数"><a href="#神奇而有趣的素数" class="headerlink" title="神奇而有趣的素数"></a>神奇而有趣的素数</h3><ul><li><p>素数(质数)就是除了 1 和自身,不能再被其他整数整除的数字。</p></li><li><p>第一个问题:下一个素数的规律是什么?</p></li><li><p>2 的倍数即是所有偶数。</p></li><li><p>3 的倍数,其数字相加能被 3 整除。</p></li><li><p>5 的倍数,结尾不是 5 就是 0,即见到这两个数字结尾的整数就能被 5 整除。</p></li><li><p>7 的倍数是第一个比较没规律的素数集合,而 7 = 2 * 3 + 1,即前两个素数相乘后再加 1 即可。</p></li><li><p>11 = 2 * 5 + 1,13 = 2 * 2 * 3 + 1,欧几里得在公元前 300 年证明了素数有无限个。如果是有限个,那假设它们的乘积为 P ,而 Q = P + 1,那么 Q 应该是一个合数,即可被其中某个素数 p 整除,而 p 又可以整除 P,那么 Q - P 也应该能被 p 整除,但是 Q - P = 1,1 显然不能被 p 整除,只能被 1 整除,所以不存在这样有限个素数的情况。</p></li></ul><h3 id="调和级数"><a href="#调和级数" class="headerlink" title="调和级数"></a>调和级数</h3><p>$$H_r = \sum_{r=1}^\infin \frac{1}{r} = 1 + \frac{1}{2} + \frac{1}{3} + \frac{1}{4} + …$$</p><ul><li>谐波:高于基音基本频率的泛音,该和式被奥雷斯姆证明是不收敛的(即不存在极限,不接近/趋向于任何特定的数字,而是一直增长到无穷大)。</li></ul><h3 id="Zeta-函数"><a href="#Zeta-函数" class="headerlink" title="Zeta 函数"></a>Zeta 函数</h3><p>$$\zeta(n)=\sum_{r=1}^\infin \frac{1}{r^n}=1 + \frac{1}{2^n} + \frac{1}{3^n} + \frac{1}{4^n} + …$$</p><p>若将 n = 1 代入,就会得到调和级数,它是发散的。然而对于 n > 1 的所有值, 该级数是收敛的,这意味着当 r 递增时,其和趋向于某些数,即它不会增长到无穷大。</p><h3 id="欧拉乘积公式"><a href="#欧拉乘积公式" class="headerlink" title="欧拉乘积公式"></a>欧拉乘积公式</h3><p>zeta 函数和素数间的第一个联系是由欧拉发现的,当时他发现了 n 和 p 两个自然数(大于零的整数)之间的关系,其中 p 为素数:</p><p>$$\zeta(n)=\sum_{r=1}^\infin\frac1{r^n}=\prod_p\frac1{1-p^{-s}}=(1-\frac1{1-\frac1{2^s}})\times(1-\frac1{1-\frac1{3^s}})\times(1-\frac1{1-\frac1{5^s}})\times(1-\frac1{1-\frac1{7^s}})\times(1-\frac1{1-\frac1{11^s}})\times…$$</p><p>欧拉乘积公式,其中 n,p 均为大于零的数字且 p 为素数</p><h2 id="简易思考"><a href="#简易思考" class="headerlink" title="简易思考"></a>简易思考</h2><ul><li><input disabled type="checkbox"> 100 以内有多少个素数?<ul><li><a href="https://plus.ooclab.com/note/article/1189" target="_blank" rel="noopener">golang-daisy-chain</a> 利用信道菊花链筛法求某一个整数范围的素数</li></ul></li><li><input disabled type="checkbox"> 100 以后第一个素数是多少?</li></ul><h2 id="数学公式"><a href="#数学公式" class="headerlink" title="数学公式"></a>数学公式</h2><ul><li><a href="https://www.mathjax.org/" target="_blank" rel="noopener">MathJax</a> Beautiful math in all browsers</li><li><a href="https://www.liuguogy.com/archives/markdown-mathjax-grammar.html" target="_blank" rel="noopener">Markdown 中的 MathJax 数学公式语法整理</a></li><li><a href="https://www.jianshu.com/p/a0aa94ef8ab2" target="_blank" rel="noopener">在Markdown中输入数学公式(MathJax)</a></li><li><a href="https://math.meta.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference" target="_blank" rel="noopener">MathJax basic tutorial and quick reference</a></li></ul><h2 id="Hugo-theme"><a href="#Hugo-theme" class="headerlink" title="Hugo theme"></a>Hugo theme</h2><ul><li><a href="https://www.zeolearn.com/magazine/develop-a-theme-for-hugo" target="_blank" rel="noopener">Develop a Theme for Hugo</a></li></ul><h2 id="Golang"><a href="#Golang" class="headerlink" title="Golang"></a>Golang</h2><ul><li><a href="https://godoc.org/github.com/azbshiri/ramda?import-graph" target="_blank" rel="noopener">ramda deps graph</a></li><li><a href="https://go-search.org" target="_blank" rel="noopener">Go Search</a></li><li><a href="http://labix.org/pipe" target="_blank" rel="noopener">Unix-like pipelines for Go</a> <a href="https://gopkg.in/pipe.v2" target="_blank" rel="noopener">Doc</a></li><li><a href="https://github.com/lennon-guan/pipe" target="_blank" rel="noopener">lennon-guan/pipe</a> A golang library that makes operations on slice easilier 局限于 Slice 数据</li><li><a href="https://godoc.org/github.com/choleraehyq/gofunctools/functools" target="_blank" rel="noopener">gofunctools</a> <a href="https://github.com/choleraehyq/gofunctools" target="_blank" rel="noopener">Github</a></li><li><a href="https://github.com/Mparaiso/go-tiger" target="_blank" rel="noopener">Go TIGER</a> Web 微框架,包含一些工具<ul><li><a href="https://godoc.org/github.com/Mparaiso/tiger-go-framework/funcs" target="_blank" rel="noopener">Make funcs</a> Package funcs provides utilities to enable functional programming with Go.</li></ul></li></ul>]]></content>
<summary type="html">
<h2 id="小程序"><a href="#小程序" class="headerlink" title="小程序"></a>小程序</h2><ul>
<li><a href="https://github.com/lcxfs1991/blog/issues/28" target
</summary>
</entry>
<entry>
<title>当日笔记-20080922</title>
<link href="http://wind13.github.io/2018/09/22/daily-note-20080922/"/>
<id>http://wind13.github.io/2018/09/22/daily-note-20080922/</id>
<published>2018-09-22T01:53:04.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="Hugo-研究"><a href="#Hugo-研究" class="headerlink" title="Hugo 研究"></a>Hugo 研究</h2><p>对 Hugo 有点着迷了,看到了 <a href="https://www.youtube.com/watch?list=PLLAZ4kZ9dFpOnyRlyS-liKL5ReHDcj4G3&v=qtIqKaDlqXo" target="_blank" rel="noopener">Youtube 上面的教程</a>,非常详细而直观,同时还可以练习英语听力,看自己感兴趣的英语视频内容应该是学英语最佳的途径之一了。</p><p>然后发现了这个 <a href="https://www.netlify.com" target="_blank" rel="noopener">netlify 网站</a> ,号称:Everything you need to deploy your project. 在静态网站的基础上,扩展很多功能 Auth/Form/Lamda 等,包括部署 CI/CD 等,单人免费,<a href="https://www.netlify.com/pricing/" target="_blank" rel="noopener">多人收费</a>。考虑到结合 Hugo, google AWP, netlify, AWS lamda 和 facebook Fauna 无服务数据库,就可以做很牛的网站和 App 服务了。 未来技术的发展会进一步简化人们提供服务的能力,从人人可以发 Blog,到人人可以提供应用服务,甚至到人人可以搭平台……</p><h2 id="英语学习"><a href="#英语学习" class="headerlink" title="英语学习"></a>英语学习</h2><p>发现了<a href="https://www.youtube.com/watch?v=FrMSSQRYS6I" target="_blank" rel="noopener">这个</a>视频 How to learn any language in six months Chris Lonsdale at TEDxLingnanUniversity,5 个原则和 7 个行动,超级棒的学习心法!而且在电视上看到这人的英语学习视频,准备购买了来学,似乎感觉自己真正找到了学习英语的法门。</p><ul><li><p><a href="https://v.youku.com/v_show/id_XNjkyODIyMDYw.html" target="_blank" rel="noopener">Ted——6个月掌握外语学习方法(英语字幕)</a></p></li><li><p>[<a href="https://v.qq.com/x/page/x0603lw682d.html" target="_blank" rel="noopener">TED经典视频:6个月掌握流利的外语学习方法</a>]</p></li><li><p><a href="https://list.youku.com/star/show/uid_UMzYzMzc0MA==.html" target="_blank" rel="noopener">龙飞虎</a></p></li><li><p><a href="https://v.youku.com/v_show/id_XMTM3NTg1OTk0NA==.html" target="_blank" rel="noopener">英语学习方法 6个月从0学英语 语法是你的朋友</a></p></li><li><p><a href="https://piccdn.igetget.com/img/201708/21/201708211714508672282465.jpg" target="_blank" rel="noopener">得到招聘赠书</a></p></li></ul>]]></content>
<summary type="html">
<h2 id="Hugo-研究"><a href="#Hugo-研究" class="headerlink" title="Hugo 研究"></a>Hugo 研究</h2><p>对 Hugo 有点着迷了,看到了 <a href="https://www.youtube.com/
</summary>
<category term="hugo" scheme="http://wind13.github.io/tags/hugo/"/>
<category term="netlify" scheme="http://wind13.github.io/tags/netlify/"/>
</entry>
<entry>
<title>当日笔记-20080921</title>
<link href="http://wind13.github.io/2018/09/21/daily-note-20080921/"/>
<id>http://wind13.github.io/2018/09/21/daily-note-20080921/</id>
<published>2018-09-21T10:25:07.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="准备做的事"><a href="#准备做的事" class="headerlink" title="准备做的事"></a>准备做的事</h2><ul><li><input checked disabled type="checkbox"> <p>尝试使用 Hugo;</p><ul><li>目录结构:<ul><li>archetypes:包括内容类型,在创建新内容时自动生成内容的配置</li><li>content:包括网站内容,全部使用markdown格式</li><li>layouts:包括了网站的模版,决定内容如何呈现</li><li>static:包括了css, js, fonts, media等,决定网站的外观</li></ul></li><li>常用命令:<ul><li><code>hugo server -t hyde --buildDrafts</code> 其中 <code>-t</code> 指 theme 主题, <code>--buildDrafts</code> 指草稿也渲染。</li></ul></li></ul></li><li><input disabled type="checkbox"> <p>尝试将 Blog 从 Hexo 转到 Hugo;</p><ul><li>用 Hexo 生成目前的 Blog 需要 36 秒,够慢的,看换了 Hugo 后会是多快?</li><li>找到 <a href="https://github.com/wd/hexo2hugo" target="_blank" rel="noopener">hexo2hugo</a> 尝试一下。基本可用,但仅能将 _posts 目录下的 md 文件转换一下格式,所以仍存在的问题如下:<ul><li><input disabled type="checkbox"> 并不能转换其他的配置功能,如搜索、回复、赞赏、分享等功能;</li><li><input disabled type="checkbox"> 转换时未能处理命名为 <code>index.md</code> 的问题;</li><li><input disabled type="checkbox"> 转换时未能处理无 <code>title</code> 的 meta data 问题,导致显示列表中没有标题链接;</li><li><input disabled type="checkbox"> 转换时未处理摘要的问题,导致列表中显示大段文字的情况;</li></ul></li><li>找到 <a href="https://danielfree.net/archives/migrate-from-hugo-to-hugo/" target="_blank" rel="noopener">Migrate from Hexo to Hugo</a> 看一下。 还有 <a href="https://www.babaei.net/blog/migrating-from-hexo-to-hugo/" target="_blank" rel="noopener">Migrating From Hexo To Hugo</a> 提到了 <a href="https://www.getgutenberg.io/" target="_blank" rel="noopener">Gutenburg</a> (written in <a href="https://www.rust-lang.org/" target="_blank" rel="noopener">Rust</a>)</li></ul></li><li><input disabled type="checkbox"> <p>尝试将转换过程写成自动化脚本,开放为开源项目;</p></li><li><input checked disabled type="checkbox"> <p>想继续使用 Next 主题,找到了:</p><ul><li><a href="https://github.com/leopku/hugo-theme-next" target="_blank" rel="noopener">NeXT</a> is a fast and clean theme for <a href="http://gohugo.io/" target="_blank" rel="noopener">Hugo</a>. which was inspired by a Hexo theme named <a href="https://github.com/iissnan/hexo-theme-next" target="_blank" rel="noopener">NexT</a>.</li><li>考虑有些需要的功能可以 fork 后提 pull request 支持项目。</li></ul></li></ul><h2 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h2><ul><li>Python2 和 Python3 共存,尝试运行 pip 安装 pytoml,结果用 python 运行时,仍然提示未安装,通过 <code>which python</code> 和 <code>which pip</code> 两个命令才发现,python 指向 python2 的版本,而 pip 指向 pip3 的版本,测试后发现当两个版本共存时,最好在使用具体命令时,要用 2 版本就用 <code>python2</code> 和 <code>pip2</code> ,要用 3 版本时,就用 <code>python3</code> 和 <code>pip3</code> ,这样就能明确区别开了。</li><li>尝试 <a href="https://github.com/gucheen/HexoConvertToHugo" target="_blank" rel="noopener">HexoConvertToHugo</a> 失败,不太好用,文档也不清楚,测试后报错,暂时放弃。</li><li>使用 hexo2hugo,开始的时候报错,以为是 <code>datetime</code> 库没安装,但安装后仍然报错,结果试了一下 python3 居然成功了,说明这个脚本是用 Python3 语法写的,Python 的这两个版本区别还真是麻烦,应该在脚本的最前面加上注释才对,或者直接改一下后缀名: xxx.py3 就清楚了。</li><li>使用 hexo2hugo,遇到第一行不是 <code>---</code> 的文档会报错,找不到 meta 信息,看了一眼程序逻辑比较固化,暂不修改了,直接修改文档匹配规则。</li><li>添加 next 主题,全新的站点,只添加一个文章,但在首页上看不到,能看到 <code>next</code> 的主题起作用了。换用 <code>ananke</code> 主题就显示正常了。一批批转移文件倒是可以,怀疑可能是 <code>index.md</code> 文件命名的问题,至少会导致 <code>All Posts</code> 链接被覆盖。</li></ul><h2 id="灵感记录"><a href="#灵感记录" class="headerlink" title="灵感记录"></a>灵感记录</h2><ul><li>互联网时代,每个人都可能成为扫地僧,整个互联网就象是少林寺的藏经阁,要学什么、怎么学,就要看你自己怎么把握了。<ul><li>萧峰和慕荣的爹都练走火了,为什么扫地僧没练走火?因为扫地僧不急功近利,有雄厚的佛法心法。</li><li>什么是互联网的修炼心法?终身学习!</li></ul></li></ul>]]></content>
<summary type="html">
<h2 id="准备做的事"><a href="#准备做的事" class="headerlink" title="准备做的事"></a>准备做的事</h2><ul>
<li><input checked disabled type="checkbox"> <p>尝试使用 Hug
</summary>
<category term="hexo" scheme="http://wind13.github.io/tags/hexo/"/>
<category term="blog" scheme="http://wind13.github.io/tags/blog/"/>
<category term="hugo" scheme="http://wind13.github.io/tags/hugo/"/>
<category term="next" scheme="http://wind13.github.io/tags/next/"/>
<category term="python" scheme="http://wind13.github.io/tags/python/"/>
<category term="灵感" scheme="http://wind13.github.io/tags/%E7%81%B5%E6%84%9F/"/>
</entry>
<entry>
<title>在得到 App 上听书《知识的边界》和《走近2050》感悟</title>
<link href="http://wind13.github.io/2018/09/21/book-comprehend/"/>
<id>http://wind13.github.io/2018/09/21/book-comprehend/</id>
<published>2018-09-21T05:58:46.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<p>人类已经进入互联网时代,互联网对人类的很多方面产生了巨大而深远的影响,有些方面在商业和科技的促进下转变得比较快,比如电子商务、信息搜索、出行交通等,但有些方面就显得相对落后,如:政府效能、教育培训、人才评定等,通常受阻于政策、传统、观念、制度等。</p><p>特别是教育培训方面,目前的学校教育依然延续着工业时代的教学方式和考试制度,延续着数年甚至数十年不变的课程和教材,很多细节上都缺乏深思与变通。</p><p>早期中国人在竹签上刻字,后来用毛笔写字,现在还需要吗?在电脑时代,更多的文字创作将由电脑输入产生,是不是更应该学习的是打字或语音输入呢?而现在的学校教育依然是使用铅笔、钢笔写字,也许在不久的将来,回想起来才会发现这些细节的迟滞和落后。</p><p>如果你去问十个小学生,通常有九个都不喜欢写字,我认为写字这种方式未来并不会绝迹,就象毛笔字一样会变为一门艺术,只有少数对它情有独钟的人去练习和创作,而这通常会是在十多岁的少年时期才会有些人有兴趣去钻研的事,当然也可能象钢琴那样会成为少数人从小就开始苦练的一门手艺,不过考虑到硬笔书法的艺术性和难度,估计这种可能性不大,毕竟电脑设计领域已经可以将很多的优秀手写字体转化到电脑中了,只需要打字后切换一下字体就可以输出漂亮的硬笔书法体的文章了。</p><p>另一个方面就是教学方式了,互联网时代,知识的边界已经极大地扩展,人们基于兴趣可以在网上冲浪,可以通过一个个链接通向全新的领域和世界,未来的人才不再如工业时代那样统一和标准化,更加人性化、多样化、奇葩化,很多人基于自己的兴趣,可能会身兼数个你无法想象的技能组合,而这样的多样性才会给世界带来很多全新的创新思想和科技。因此我们的教学方式也应该变得更加符合这种发展的自然状态,也许:</p><ul><li>不再有课堂,而是一个自由上网、自由交流、自由合作的俱乐部;</li><li>不再有课程,而是遇到什么问题,解决什么问题,遇到什么兴趣,再观看什么教学视频,俱乐部的系统会记录学生的学习路径,适时地推送恰当的学习资料、视频和测试题等;</li><li>不再有专职的老师,而是集体学习、互相进步的社群,可以结伴前行,可以搭配协作,可以远程互助等,没有老师,所有人都在其中自学,同时又可能是每个人都是老师,在必要的时候教授别人相应的知识,解答别人相应的困惑,记录下自己的学习经验和感悟供他人参考……</li></ul><p>未来人类更加不需要顾虑物质生活的限制了,而人类会逐渐发现对物质生活追求而获得的满足感将会非常有限,毕竟一个人整天吃喝玩乐也持续不了多久,终归会落入空虚和无聊之中,而对于未知世界的探索将会填补这些需求,也就是人们会更倾向于对精神生活的追求,而精神世界的追求则是有无限的想象空间的,随着科技的发展,人们可以更随心所欲地发展个人的兴趣爱好,多数时间感觉更象是在玩耍中不断扩展自己的知识边界,也就是传统意义上的学习和提升,同时也会不断涉及到社会的高级工作中,因为低级工作通常已经被机器智能所代替了,人们在这些工作中创造出更多更灿烂的文化和科技等,使得人类文明进一步繁荣和发展……</p>]]></content>
<summary type="html">
<p>人类已经进入互联网时代,互联网对人类的很多方面产生了巨大而深远的影响,有些方面在商业和科技的促进下转变得比较快,比如电子商务、信息搜索、出行交通等,但有些方面就显得相对落后,如:政府效能、教育培训、人才评定等,通常受阻于政策、传统、观念、制度等。</p>
<p>特别是教育培
</summary>
<category term="得到 App" scheme="http://wind13.github.io/tags/%E5%BE%97%E5%88%B0-App/"/>
<category term="互联网时代" scheme="http://wind13.github.io/tags/%E4%BA%92%E8%81%94%E7%BD%91%E6%97%B6%E4%BB%A3/"/>
<category term="教育" scheme="http://wind13.github.io/tags/%E6%95%99%E8%82%B2/"/>
</entry>
<entry>
<title>go 语言学习</title>
<link href="http://wind13.github.io/2018/09/19/go-learn/"/>
<id>http://wind13.github.io/2018/09/19/go-learn/</id>
<published>2018-09-19T09:56:00.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="安装、升级、卸载等"><a href="#安装、升级、卸载等" class="headerlink" title="安装、升级、卸载等"></a>安装、升级、卸载等</h2><ul><li><a href="https://golang.org/" target="_blank" rel="noopener">官网</a></li><li><a href="https://tour.go-zh.org/welcome/1" target="_blank" rel="noopener">中文官网教程</a></li><li><a href="https://wuyin.io/2018/06/11/golang-cheat-sheet/" target="_blank" rel="noopener">Golang 速查表</a></li><li>安装简单,按官网的说明来就好了,macOS 上就是下载个 pkg 的包双击安装即可。</li><li>卸载也简单,删除那个 <code>/usr/local/go</code> 的目录即可。</li><li>升级官网上没提,搜了一下基本就是先卸载再安装,我试了一下直接安装最新下载的也可以,会提示发现旧版本,确定后会自动卸载再安装。</li></ul><h2 id="国际惯例:Hello-world"><a href="#国际惯例:Hello-world" class="headerlink" title="国际惯例:Hello world!"></a>国际惯例:Hello world!</h2><ul><li>参考:<a href="http://www.cnblogs.com/ghj1976/archive/2013/03/24/2979668.html" target="_blank" rel="noopener">Go安装的设置问题:GOROOT,GOPATH</a></li><li>学习项目:<a href="https://github.com/wind13/golang-learn" target="_blank" rel="noopener">Learn golang notes</a></li></ul><h2 id="名词概念"><a href="#名词概念" class="headerlink" title="名词概念"></a>名词概念</h2><ul><li>程序实体:变量、常量、函数、结构体和接口等的统称。</li><li>标识符:各个程序实体的名字。可以是任何 Unicode 编码可以表示的字母字符(甚至中文,但不推荐)、数字以及下划线等,但首字母不能是数字。</li><li>命令源码文件:可以被直接运行,也包含程序实体。</li><li>库源码文件:不可以被直接运行,仅用于存放程序实体。</li><li>GOPATH:Go 语言的源码文件都需要存放在环境变量 GOPATH 包含的某个工作区(目录)中的 src 目录下的某个代码包(目录)中。</li><li><code>*string</code> 是字符串的指针类型,而不是字符串类型。</li><li><code>:=</code> 是重定义变量类型并赋值,可以改变外部变量类型和值,而 <code>=</code> 只能赋给相同类型的值,类型不对时编译期会报错。</li><li>类似 toString() 方法的接口:</li></ul><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Stringer <span class="keyword">interface</span> {</span><br><span class="line"> String() <span class="keyword">string</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>Channel and go routines, 同一时间只允许一个 go routine 访问 channel,所以可以用这个机制来进行安全稳定的 concurrency 并发编程。</li><li><code>go run -race main.go</code> Running with race detector. 使用竞跑模式运行,各 goroutine 会争抢优先级,方便发现一些隐藏的多 goroutine 运行时冲突问题。</li></ul><h2 id="初学者入门"><a href="#初学者入门" class="headerlink" title="初学者入门"></a>初学者入门</h2><p>极客时间的那个 《Go语言核心 36 讲》 显然不是针对初学者的,所以要先看看以下内容:</p><ul><li><a href="https://tour.golang.org" target="_blank" rel="noopener">官方教程</a></li></ul><h2 id="高级内容"><a href="#高级内容" class="headerlink" title="高级内容"></a>高级内容</h2><ul><li><a href="https://www.youtube.com/watch?v=QDDwwePbDtw" target="_blank" rel="noopener">Advanced Go Concurrency Patterns</a> 介绍了 goroutine 编程的一些高级模式和技巧,如: <ul><li>for select 循环</li><li>select nil channel case</li><li>run race detector</li><li>service channel, reply channels(chan chan error)</li></ul></li></ul><h2 id="Web-Framework"><a href="#Web-Framework" class="headerlink" title="Web Framework"></a>Web Framework</h2><ul><li><a href="https://iris-go.com/" target="_blank" rel="noopener">iris</a> 号称最快的 web 框架,因为基于fasthttp性能非常的好,需要考虑的是如果选它做web框架,你的代码将难以迁移到别的框架上,因为它实现了和标准库net/http不一样的接口。 看了一下文档,相当全面。</li><li><a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> The world’s fastest framework for building websites 静态网站生成器<ul><li><a href="https://jimmysong.io/posts/building-github-pages-with-hugo/" target="_blank" rel="noopener">零基础使用Hugo和GitHub Pages创建自己的博客</a> 非常专业的博客</li><li><a href="https://gohugo.io/getting-started/usage/" target="_blank" rel="noopener">Basic Usage</a> 基础使用方法介绍</li><li><a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/" target="_blank" rel="noopener">Host on GitHub</a> 官方文档</li></ul></li><li><a href="https://echo.labstack.com/" target="_blank" rel="noopener">Echo</a> 最流行的框架,功能、文档齐全</li><li><a href="http://revel.github.io/" target="_blank" rel="noopener">Revel</a> 全栈框架,但<a href="https://github.com/diyan/go-web-framework-comparsion" target="_blank" rel="noopener">据说</a>不太合 golang 的语法习惯。 借鉴的java和scala语言的 play框架 的很多想法。</li><li><a href="https://github.com/go-martini/martini" target="_blank" rel="noopener">Martini</a> <a href="https://www.restapiexample.com/rest-api-tutorial/golang-tutorial/popular-golang-web-framework-2017/" target="_blank" rel="noopener">据说</a>是最易用的 web 框架,是一个强大为了编写模块化Web应用而生的GO语言框架。</li><li><a href="https://github.com/urfave/negroni" target="_blank" rel="noopener">Negroni</a> 不是一个框架,它是为了方便使用 net/http 而设计的一个库而已。</li><li><a href="https://beego.me/" target="_blank" rel="noopener">Beego</a> 国人开发的一个使用 Go 的思维来帮助您构建并开发 Go 应用程序的开源框架</li><li><a href="https://www.do1618.com/archives/819/golang-web-framework/" target="_blank" rel="noopener">Golang Web FrameWork 比较</a></li><li><a href="http://fuxiaohei.me/2014/3/13/go-web-framework.html" target="_blank" rel="noopener">Go语言的Web框架</a></li><li><a href="https://colobu.com/2016/04/06/the-fastest-golang-web-framework/" target="_blank" rel="noopener">谁是最快的Go Web框架</a></li><li><a href="http://www.cnblogs.com/sunshine-anycall/p/4967432.html" target="_blank" rel="noopener">使用Golang(Margini)+Mongodb打造你的第一个站点</a></li></ul><h2 id="GraphQL"><a href="#GraphQL" class="headerlink" title="GraphQL"></a>GraphQL</h2><ul><li><a href="https://linux.cn/article-8524-1.html" target="_blank" rel="noopener">GraphQL 用例:使用 Golang 和 PostgreSQL 构建一个博客引擎 API</a></li><li><a href="https://github.com/nilstgmd/graphql-starter-kit" target="_blank" rel="noopener">GraphQL Starter Kit for GoLang</a> A GraphQL server example written in GoLang integrating with Cassandra and MongoDB.</li><li><a href="https://github.com/graphql-go/graphql" target="_blank" rel="noopener">graphql-go/graphql</a> An implementation of GraphQL for Go / Golang</li></ul><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><h3 id="重复定义"><a href="#重复定义" class="headerlink" title="重复定义"></a>重复定义</h3><ul><li>遇到 <code>no new variables on left side of :=</code> 报错,说明左边的变量被重复定义了,去上面的代码中找同名的变量,一定有,解决方法就是换个变量名。</li></ul><h3 id="通道锁死"><a href="#通道锁死" class="headerlink" title="通道锁死"></a>通道锁死</h3><ul><li><code>fatal error: all goroutines are asleep - deadlock!</code></li><li>一般发生在通道中没内容,而不断从通道取值时,另一种情况是向通道送值,但没放在单独的 goroutine 中。</li><li>解决思路,一个是将通道送值放在 go func 即 goroutine 中,另外就是取值用 for select 后要有退出机制,在恰当的条件时 return 就可以退出,实在没有合适的条件,可以用 time.After 设置超时退出。</li></ul><h2 id="文件组织规则"><a href="#文件组织规则" class="headerlink" title="文件组织规则"></a>文件组织规则</h2><ul><li>同目录的代码包声明要一致;</li><li>代码包声明可以与目录名称不同;</li><li>名称首字母大写的程序实体才可以被包外引用,否则只能被包内引用。</li><li>internal 代码包仅能被当前模块的其他代码引用,即模块级私有。</li><li>同目录中只能有一个入口函数 main,否则会被(vscode)警告,算是最佳实践吧。</li></ul><h2 id="Go-相关项目"><a href="#Go-相关项目" class="headerlink" title="Go 相关项目"></a>Go 相关项目</h2><ul><li><a href="https://www.docker.com/" target="_blank" rel="noopener">Docker</a> 容器</li><li><a href="https://github.com/spf13/cobra" target="_blank" rel="noopener">Cobra Cli</a> 开发命令行工具的工具,Go 语言的牛 X 工具。</li><li><a href="https://github.com/spf13/viper" target="_blank" rel="noopener">Viper</a> Go configuration with fangs! 管理配置文件的工具。</li><li><a href="https://github.com/spf13/afero" target="_blank" rel="noopener">Afero</a> A FileSystem Abstraction System for Go</li><li><a href="https://github.com/go-vgo/robotgo/blob/master/README_zh.md" target="_blank" rel="noopener">Robotgo</a> Golang 跨平台自动化系统,控制键盘鼠标位图和读取屏幕,窗口句柄以及全局事件监听 </li></ul><h2 id="练习题:Web-Crawler"><a href="#练习题:Web-Crawler" class="headerlink" title="练习题:Web Crawler"></a>练习题:<a href="https://tour.golang.org/concurrency/10" target="_blank" rel="noopener">Web Crawler</a></h2><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><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">"fmt"</span></span><br><span class="line"><span class="string">"sync"</span></span><br><span class="line"><span class="string">"time"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Fetcher <span class="keyword">interface</span> {</span><br><span class="line"><span class="comment">// Fetch returns the body of URL and</span></span><br><span class="line"><span class="comment">// a slice of URLs found on that page.</span></span><br><span class="line">Fetch(url <span class="keyword">string</span>) (body <span class="keyword">string</span>, urls []<span class="keyword">string</span>, err error)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> TIMEOUT = <span class="number">3</span></span><br><span class="line"><span class="keyword">const</span> MAX_DEPTH = <span class="number">4</span></span><br><span class="line"><span class="keyword">var</span> queue = <span class="built_in">make</span>(<span class="keyword">chan</span> Job)</span><br><span class="line"><span class="keyword">var</span> successes = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>)</span><br><span class="line"><span class="keyword">var</span> errors = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>)</span><br><span class="line"><span class="keyword">var</span> history = History{h: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]Job)}</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Job <span class="keyword">struct</span> {</span><br><span class="line">url <span class="keyword">string</span></span><br><span class="line">depth <span class="keyword">int</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// History is safe to use concurrently.</span></span><br><span class="line"><span class="keyword">type</span> History <span class="keyword">struct</span> {</span><br><span class="line">h <span class="keyword">map</span>[<span class="keyword">string</span>]Job</span><br><span class="line">mux sync.Mutex</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// Inc increments the history</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *History)</span> <span class="title">Add</span><span class="params">(url <span class="keyword">string</span>, depth <span class="keyword">int</span>)</span></span> {</span><br><span class="line">c.mux.Lock()</span><br><span class="line"><span class="comment">// Lock so only one goroutine at a time can access the map c.h.</span></span><br><span class="line">_, exist := c.h[url]</span><br><span class="line"><span class="keyword">if</span> !exist {</span><br><span class="line">c.h[url] = Job{url, depth}</span><br><span class="line">queue <- Job{url, depth}</span><br><span class="line">}</span><br><span class="line">c.mux.Unlock()</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">fetchWeb</span><span class="params">(url <span class="keyword">string</span>, depth <span class="keyword">int</span>, fetcher Fetcher)</span></span> {</span><br><span class="line"><span class="keyword">if</span> depth <= <span class="number">0</span> {</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">}</span><br><span class="line">body, uris, err := fetcher.Fetch(url)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="comment">// fmt.Println(err)</span></span><br><span class="line">errors <- <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>{url: err.Error()}</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">// fmt.Printf("found: %s %q\n", url, body)</span></span><br><span class="line">successes <- <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>{url: body}</span><br><span class="line"><span class="keyword">for</span> _, u := <span class="keyword">range</span> uris {</span><br><span class="line">history.Add(u, depth<span class="number">-1</span>)</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// Crawl uses fetcher to recursively crawl</span></span><br><span class="line"><span class="comment">// pages starting with url, to a maximum of depth.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Crawl</span><span class="params">(url <span class="keyword">string</span>, depth <span class="keyword">int</span>, fetcher Fetcher)</span></span> {</span><br><span class="line">quit := time.After(TIMEOUT * time.Second) <span class="comment">// Timeout</span></span><br><span class="line"><span class="comment">// Fetch URLs in parallel.</span></span><br><span class="line"><span class="comment">// Don't fetch the same URL twice.</span></span><br><span class="line"><span class="comment">// This implementation doesn't do either:</span></span><br><span class="line"><span class="keyword">go</span> history.Add(<span class="string">"https://golang.org/"</span>, <span class="number">4</span>)</span><br><span class="line"><span class="keyword">for</span> {</span><br><span class="line"><span class="keyword">select</span> {</span><br><span class="line"><span class="keyword">case</span> q := <-queue:</span><br><span class="line"><span class="comment">// fmt.Println(q)</span></span><br><span class="line"><span class="keyword">go</span> fetchWeb(q.url, q.depth, fetcher)</span><br><span class="line"><span class="keyword">case</span> s := <-successes:</span><br><span class="line"><span class="keyword">for</span> url, body := <span class="keyword">range</span> s {</span><br><span class="line">fmt.Println(url, body)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">case</span> e := <-errors:</span><br><span class="line"><span class="keyword">for</span> url, err := <span class="keyword">range</span> e {</span><br><span class="line">fmt.Println(url, err)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">case</span> <-quit:</span><br><span class="line">fmt.Println(<span class="string">"quit"</span>)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">}</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">Crawl(<span class="string">"https://golang.org/"</span>, MAX_DEPTH, fetcher)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// fakeFetcher is Fetcher that returns canned results.</span></span><br><span class="line"><span class="keyword">type</span> fakeFetcher <span class="keyword">map</span>[<span class="keyword">string</span>]*fakeResult</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> fakeResult <span class="keyword">struct</span> {</span><br><span class="line">body <span class="keyword">string</span></span><br><span class="line">urls []<span class="keyword">string</span></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="params">(f fakeFetcher)</span> <span class="title">Fetch</span><span class="params">(url <span class="keyword">string</span>)</span> <span class="params">(<span class="keyword">string</span>, []<span class="keyword">string</span>, error)</span></span> {</span><br><span class="line"><span class="keyword">if</span> res, ok := f[url]; ok {</span><br><span class="line"><span class="keyword">return</span> res.body, res.urls, <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="string">""</span>, <span class="literal">nil</span>, fmt.Errorf(<span class="string">"not found: %s"</span>, url)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// fetcher is a populated fakeFetcher.</span></span><br><span class="line"><span class="keyword">var</span> fetcher = fakeFetcher{</span><br><span class="line"><span class="string">"https://golang.org/"</span>: &fakeResult{</span><br><span class="line"><span class="string">"The Go Programming Language"</span>,</span><br><span class="line">[]<span class="keyword">string</span>{</span><br><span class="line"><span class="string">"https://golang.org/pkg/"</span>,</span><br><span class="line"><span class="string">"https://golang.org/cmd/"</span>,</span><br><span class="line">},</span><br><span class="line">},</span><br><span class="line"><span class="string">"https://golang.org/pkg/"</span>: &fakeResult{</span><br><span class="line"><span class="string">"Packages"</span>,</span><br><span class="line">[]<span class="keyword">string</span>{</span><br><span class="line"><span class="string">"https://golang.org/"</span>,</span><br><span class="line"><span class="string">"https://golang.org/cmd/"</span>,</span><br><span class="line"><span class="string">"https://golang.org/pkg/fmt/"</span>,</span><br><span class="line"><span class="string">"https://golang.org/pkg/os/"</span>,</span><br><span class="line">},</span><br><span class="line">},</span><br><span class="line"><span class="string">"https://golang.org/pkg/fmt/"</span>: &fakeResult{</span><br><span class="line"><span class="string">"Package fmt"</span>,</span><br><span class="line">[]<span class="keyword">string</span>{</span><br><span class="line"><span class="string">"https://golang.org/"</span>,</span><br><span class="line"><span class="string">"https://golang.org/pkg/"</span>,</span><br><span class="line">},</span><br><span class="line">},</span><br><span class="line"><span class="string">"https://golang.org/pkg/os/"</span>: &fakeResult{</span><br><span class="line"><span class="string">"Package os"</span>,</span><br><span class="line">[]<span class="keyword">string</span>{</span><br><span class="line"><span class="string">"https://golang.org/"</span>,</span><br><span class="line"><span class="string">"https://golang.org/pkg/"</span>,</span><br><span class="line">},</span><br><span class="line">},</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="安装、升级、卸载等"><a href="#安装、升级、卸载等" class="headerlink" title="安装、升级、卸载等"></a>安装、升级、卸载等</h2><ul>
<li><a href="https://golang.org/" target
</summary>
</entry>
<entry>
<title>再见了 Redux (翻译)</title>
<link href="http://wind13.github.io/2018/09/05/goodbye-redux-cn/"/>
<id>http://wind13.github.io/2018/09/05/goodbye-redux-cn/</id>
<published>2018-09-05T09:35:11.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<p>作者:<a href="https://medium.com/@jackrobertscott" target="_blank" rel="noopener">Jack Scott</a> </p><p><a href="https://medium.com/@jackrobertscott/goodbye-redux-26e6a27b3a0b" target="_blank" rel="noopener">原文(英语)</a> 国内网可能访问不到……大致翻译如下:</p><p>本文主要分析了一下我们过去为什么需要 Redux,而为什么以后又不再需要了。</p><p><img src="https://upload-images.jianshu.io/upload_images/3664876-14f4fcccb131ca0a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Goodbye Redux"></p><p>在过去的几年里,互联网技术已经转向用前端 JavaScript 框架来实现网站和手机应用,以达到更好的用户体验。这非常棒 🔥 ,我个人很欣赏这些框架提供的灵活性。</p><blockquote><p>但是灵活得是否有些过头了……</p></blockquote><p>为了能更好地理解这个问题,让我们把时钟拨回到 JavaScript 框架出现以前,看看我们是怎么开发应用的。</p><h2 id="⏳-JavaScript-以前的大陆-A-Land-Before-JavaScript…"><a href="#⏳-JavaScript-以前的大陆-A-Land-Before-JavaScript…" class="headerlink" title="⏳ JavaScript 以前的大陆 A Land Before JavaScript…"></a>⏳ JavaScript 以前的大陆 A Land Before JavaScript…</h2><p>在前几个前端框架(最值得注意的是AngularJS、Backbone和Ember)出现之前,我们只是在服务器上渲染模板,然后将完整的HTML页面发送到浏览器。当时流行的框架包括:</p><p><img src="https://upload-images.jianshu.io/upload_images/3664876-519ee7773ccf33c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="sf, django, rails"></p><ul><li>Django (Python)——2005年7月21日发布 ~13 年前</li><li>Ruby on Rails —— 2005年12月13日发布 ~13 年前</li><li>Symphony (PHP) —— 2005年10月22日发布 ~13 年前</li></ul><p>这些框架主要是围绕了 MVC 概念也就是 Model-View-Controller 来开发的,Model 表示数据的模型,View 表示怎么显示这些数据,而 Controller 则连接这两部分。</p><blockquote><p>我的意思是说,这其中也有 JavaScript,但我们更多的时候是在说 jQuery 做的滑动条和一些完全没必要的动态网页效果</p></blockquote><p>在这些框架上编写的应用有一些问题,但总得来说还不错,直到有一天 Ryan Dahl 有了一个很棒的主意,他开发了第一版的 Node.js,可以让开发人员写服务端程序,而不止是用 JavaScript 做些愚蠢的动画。</p><ul><li>Node.js ——2009年5月27日发布 ~9 年前</li></ul><p>猛然间人们似乎看到了 JavaScript 的无限可能性,用一丁点儿的代码就能做很多事儿,这充分打开了其他开发人员的想象力,人们不仅创建更多强大的 Node.js 工具,还开始创建有趣的前端框架,在接下来的几年里,JavaScript 就象滚雪球一样高速发展起来:</p><p><img src="https://upload-images.jianshu.io/upload_images/3664876-f415e7981f12340a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="AngularJS, Backbone.js, Ember.js"></p><ul><li>Express.js(后端)——2010年11月16日发布 ~8 年前</li><li>Backbone.js(前端)——2010年10月12日发布 ~8 年前</li><li>AngularJS(前端)——2010年10月20日发布 ~8 年前</li><li>Ember.js(前端)——2011年12月8日发布 ~8 年前</li></ul><p>这就开始了应用开发模式的重大转变。之前由服务端直接处理的 MVC 模式被分拆为两部分:一个服务端的 MC 和一个客户端的 V(MC),客户端使用的就是上述的前端框架。在早期的这些框架中,还包含 Model 和 Controller 层在 View 中。两份 Model 和 Controller,前端也有一份 MC,这样看来是要写更多的代码了。</p><h2 id="🤦-脸书有个头疼的问题-Facebook-Had-A-Problem"><a href="#🤦-脸书有个头疼的问题-Facebook-Had-A-Problem" class="headerlink" title="🤦 脸书有个头疼的问题 Facebook Had A Problem"></a>🤦 脸书有个头疼的问题 Facebook Had A Problem</h2><p>正当所有人开心地使用上述方案的时候,Facebook 来了,随着它的迅速崛起,Facebook 变成了最大的网页应用,而为了解决页头上即时消息的数量显示问题(实际上这个小问题在海量用户使用的场景下是比较复杂的),旧的方案也并不能很好地应对……</p><p><img src="https://upload-images.jianshu.io/upload_images/3664876-6275231c73de14d7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Facebook head aches"></p><p>于是他们推出了 React:</p><ul><li>React(前端) ——2013年 三月发布 ~5 年前</li></ul><p>而 React 只管 View 层,于是又有了 Flux,之后是 Redux(Redo Flux),有兴趣了解详情的可以看这个视频:</p><p><a href="https://v.youku.com/v_show/id_XMTU1MDg5OTQ1Ng==.html" target="_blank" rel="noopener">Youku视频</a> <a href="https://v.qq.com/x/page/g0189w2yt1r.html" target="_blank" rel="noopener">QQ视频</a></p><h2 id="🍐-……于是这东西变得象个鸭梨-…Then-Things-Started-to-Go-Pear-Shaped"><a href="#🍐-……于是这东西变得象个鸭梨-…Then-Things-Started-to-Go-Pear-Shaped" class="headerlink" title="🍐 ……于是这东西变得象个鸭梨 …Then Things Started to Go Pear Shaped"></a>🍐 ……于是这东西变得象个鸭梨 …Then Things Started to Go Pear Shaped</h2><p>Redux 的工作方式是把一个应用中几乎所有的动态信息都保存在一个 JavaScript 对象中。这样不管你在应用的哪个地方看到的数据都来自同一个地方,也就能保持一致,这样也就解决了 Facebook 所头疼的问题。</p><p>于是突然又来了一种新框架:React + Redux 解决方案,Facebook 用它来解决问题,而从此以后所有人都过上了幸福的生活……对吗?</p><h2 id="✋-不尽然-Not-quite"><a href="#✋-不尽然-Not-quite" class="headerlink" title="✋ 不尽然 Not quite."></a>✋ 不尽然 Not quite.</h2><p>问题在于人们(包括我)开始用一个对象保存所有信息,其中的每一部分都是由服务端获得,没错这可以保证数据的及时更新,但同时也存在 3 个缺点:</p><ol><li>这需要大量的多余的代码才能很好地运行,这很浪费时间。</li><li>因为所有代码放在一处,这可能带来“旧数据”的问题,也就是说你可能在应用中见到一些来自之前状态的不想要的数据。</li><li>对于新的开发人员学习曲线太高,继而使得前端Web开发很难被新的开发人员采用。</li></ol><p>我们有一个向用户显示数据的相对简单的老式 MVC 框架应用,其中也就是几个简单的模板,在2005年,我们成功地将它转换为一个单页面应用,它的前端代码通常是后端代码的 10 倍。例如:我最近开发了一个简单的应用,然后我用 <a href="https://wakatime.com/" target="_blank" rel="noopener">WakaTime</a> 来衡量我在编码上的耗时情况,以下是测量结果:</p><ul><li>React Redux 前端代码库—— 32 小时.</li><li>Express + Mongoose 后端代码库——4 小时.</li></ul><h2 id="🤯-你当真?Are-you-serious"><a href="#🤯-你当真?Are-you-serious" class="headerlink" title="🤯 你当真?Are you serious??"></a>🤯 你当真?Are you serious??</h2><p>我花了 8 倍的时间在前端?让我们看看原因吧,下面是一个示例,一个很普通的取数据(例如取得所有用户)到前端的流程:</p><blockquote><p>🚧 警告:下面的步骤描述非常技术化,如果你看不太懂没关系。Warning: the following steps are super techy so don’t worry if you get lost.</p></blockquote><ol><li>创建一个组件来显示用户列表(这一步没啥问题);</li><li>创建一个 <code>fetch</code> 请求到后端接口;</li><li>在 <code>state</code> 中添加一个新字段;</li><li>添加一个 <code>action</code> 用来更新 <code>state</code> 的数据;</li><li>添加一个 <code>thunk</code> 方法来运行 <code>fetch</code> 请求,然后使用新的 <code>action</code> 来更新 <code>state</code> 状态;</li><li>使用 <code>connect()</code> 将这个 <code>thunk</code> 方法加到组件中的 <code>dispatch</code> 方法中;</li><li>再次使用 <code>connect()</code> 从 <code>state</code> 中提取数据;</li><li>在组件的 <code>prop types</code> 属性类型中声明 <code>thunk</code> 方法和提取的数据字段;</li><li>在 <code>componentDidMount()</code> 方法中调用 <code>thunk</code> 方法;</li><li>最后,渲染数据到界面;</li></ol><p>我的天……10步,回到 Ruby on Rails 的时代,我只需要把数据放到 HTML 的模板中就完事儿了,达到的效果差不多,我想这中间肯定有什么问题吧?!</p><h2 id="☝️-一条新的路径-A-New-Approach"><a href="#☝️-一条新的路径-A-New-Approach" class="headerlink" title="☝️ 一条新的路径 A New Approach"></a>☝️ 一条新的路径 A New Approach</h2><p>Redux 只是解决了前端数据的一致性,但它也带来了如前所述的问题,那么它的价值到底是什么?</p><blockquote><p>基本上我们重写了整个前端只是解决了屈指可数的几个小问题。</p></blockquote><p>Facebook 也意识到了这个问题,启动了一个新项目叫 GraphQL,GraphQL 目前还是个技术名词,我不确定大家是否知道它为什么酷?</p><p>GraphQL 完全不同于 Redux,Facebook 又创造了一个大神级的产品,但却没指出这宝贝为什么这么重要,这也是为什么我花时间写此文的原因。</p><blockquote><p>简言之,如果说 Redux 是一匹马的话,GraphQL 就是一辆车。</p></blockquote><h3 id="什么?怎么-Redux-成了一匹马?"><a href="#什么?怎么-Redux-成了一匹马?" class="headerlink" title="什么?怎么 Redux 成了一匹马?"></a>什么?怎么 Redux 成了一匹马?</h3><p>我之所以把它们比做一匹马和一辆车,原因是这俩完全是两个物种,一个是有四条腿的马动物,一个是有四个轮子的机器。然而,它们的作用是一样的,都是把人运到想去的地方。虽然它们各自有不同的适合场景,但通常来说,汽车会更快些。</p><h3 id="那么,GraphQL-到底是什么?"><a href="#那么,GraphQL-到底是什么?" class="headerlink" title="那么,GraphQL 到底是什么?"></a>那么,GraphQL 到底是什么?</h3><p>官方文档是这样说的:“GraphQL 是一种 APIs 接口的查询语言”,感觉不清不楚的,其实他们所谓的查询语言基本上一个就可以替代上百个 HTTP 接口,因为这个技术还很新,所以文档和支持的技术还有点难懂,有一定的学习曲线。这儿给你一个例子看是否有帮助:</p><p>GraphQL 可以替代类似这样的接口:</p><ul><li>GET /users/1234567890</li><li>POST /cars</li><li>PUT /example/endpoints</li></ul><p>只查询你需要的字段,如下:</p><figure class="highlight js"><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><br><span class="line"> user(id: <span class="string">"1234567890"</span>) {</span><br><span class="line"> name,</span><br><span class="line"> email</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>返回:</p><figure class="highlight plain"><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><br><span class="line"> "user": {</span><br><span class="line"> "name": "Luke Skywalker",</span><br><span class="line"> "email": "[email protected]"</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>等一下——<strong>自定义的查询</strong>……这可是需要点儿时间去实现的,也许你这么认为~</p><p>但实际上不用,原因在于:由于只请求需要的数据,突然你不需要那么多服务端请求了,也就是说你不需要写那么多代码去处理那么多服务端请求了,于是,你就节省了大量不需要实现的代码和时间。</p><h2 id="🤷-但这就能替代-Redux-了吗?But-how-does-this-replace-Redux"><a href="#🤷-但这就能替代-Redux-了吗?But-how-does-this-replace-Redux" class="headerlink" title="🤷 但这就能替代 Redux 了吗?But how does this replace Redux?"></a>🤷 但这就能替代 Redux 了吗?But how does this replace Redux?</h2><p>问得好!简单地说,<strong>不能</strong>。不过,它鼓励你不要象 Redux 那样把所有信息存在一个单独的对象中,因为每个查询只针对应用的一小部分,而不是整个应用。在一整个应用的数据源中只关注一小部分,这应该算是个 <code>anti-pattern</code> 反模式、反常识(甚至是有点不合逻辑)的。</p><blockquote><p>通过使用 GraphQL 你就可以摆脱对 Redux 的依赖从而省掉大量的代码。</p></blockquote><p>还有一点要注意:Redux 和 GraphQL 是可以共存的,这样你可以平滑地过渡,这儿有一些关于两者整合的文章:</p><p><a href="https://s3.amazonaws.com/apollo-docs-1.x/redux.html" target="_blank" rel="noopener">Integrating with Redux | Apollo React Docs</a></p><p>用不用 Redux 变成一种选择。是用它解决一些小任务而面对头疼的问题,还是换一种方法完成那些任务?</p><h3 id="那么,你会怎么选择?"><a href="#那么,你会怎么选择?" class="headerlink" title="那么,你会怎么选择?"></a>那么,你会怎么选择?</h3><p>Redux 在当时确实解决了问题,但就在同时,Web 开发行业又在 <code>Web sockets</code> 领域有了巨大的进步。</p><p>Web sockets 是在服务端和客户端建立持续的连接,服务端就可以通知客户端何时更新。你猜怎么着?GraphQL 用一种叫 <code>subscriptions</code> 的订阅技术直接就能支持 web sockets,我们可以用这种 <code>subscriptions</code> 的订阅机制来更新应用中想保持同步的部分。</p><p>核心的区别在于:与其让客户端(用 Redux)告诉我们哪里要更新,不如让服务端直接通知客户端更新。结果是一样的,这儿有一些例子是怎么用 MongoDB 或 Mongoose 实现 Web socket 和 <code>subscriptions</code> 的。</p><p><a href="http://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-change-streams.html" target="_blank" rel="noopener">A Node.js Perspective on MongoDB 3.6: Change Streams</a></p><p><a href="https://mongoosejs.com/docs/api.html#model_Model.watch" target="_blank" rel="noopener">Mongoose v5.2.12: API — Model.watch()</a></p><h2 id="🚀-未来很精彩!The-Future-Looks-Awesome"><a href="#🚀-未来很精彩!The-Future-Looks-Awesome" class="headerlink" title="🚀 未来很精彩!The Future Looks Awesome!"></a>🚀 未来很精彩!The Future Looks Awesome!</h2><p>GraphQL 开发没多久,但眼下也可以用在产品上了。我不想撒谎,官方文档确实能把人搞晕,需要对 JavaScript 和 服务端运行机制有很强的理解才行。然而如果你还没那么强,但想了解更多,这有一个很流行的教程:</p><p><a href="https://graphql.org/learn/" target="_blank" rel="noopener">GraphQL: A query language for APIs.</a></p><p>还有很多有用的库可以帮你逐步地整合 GraphQL 到已有产品中。不用担心,你不用一次弄完,这些库可以帮你轻松地、慢慢地改善你的应用。Apollo 就是一家做这事儿的公司。</p><p><a href="https://www.apollographql.com/" target="_blank" rel="noopener">Apollo GraphQL</a></p><p>好了,我希望这篇文章可以对阐明一些复杂的概念有帮助。</p><p>如果你喜欢这篇文章,请点赞——这对我来说是很大的鼓励——或者有问题请留言。</p><p>谢谢!🙌 </p>]]></content>
<summary type="html">
<p>作者:<a href="https://medium.com/@jackrobertscott" target="_blank" rel="noopener">Jack Scott</a> </p>
<p><a href="https://medium.com/@jackr
</summary>
<category term="react" scheme="http://wind13.github.io/tags/react/"/>
<category term="redux" scheme="http://wind13.github.io/tags/redux/"/>
<category term="graphql" scheme="http://wind13.github.io/tags/graphql/"/>
</entry>
<entry>
<title>在 vscode 的 vi 模式下,按中文标点移动光标的方法</title>
<link href="http://wind13.github.io/2018/08/27/vscode-vi-segment-chinese-punctuation/"/>
<id>http://wind13.github.io/2018/08/27/vscode-vi-segment-chinese-punctuation/</id>
<published>2018-08-27T10:03:51.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><p>首先,vscode 是目前最好的编程工具,未来前途也无可限量,其次 vi 的快捷键模式也是最高效的键盘输入模式,在 vscode 中可以添加 vi 快捷键的支持(在首选项-按键映射扩展中可以安装 Vim 即可,或在插件商店搜索:<code>@recommended:keymaps</code> 也能添加)。</p><p>但是在编辑中文时会有一个问题:</p><p>因为英文单词是由空格隔开的,所以在 vi 模式时按 w 键天然是能按单词移动的,而中文字句是连在一起的,所以会在移动光标时,整段中文字直接跳过,非常不符合使用的习惯。</p><h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><p>在 vscode 的用户设置(在 macOS 中按 Cmd + , 编辑)中添加这两项即可:</p><figure class="highlight plain"><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">"editor.wordSeparators": "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?,。;、:“”!?《》【】……¥",</span><br><span class="line">"vim.iskeyword": "/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-,。;、:“”!?《》()【】……¥",</span><br></pre></td></tr></table></figure><p>前面都是默认的,后面只是添加上了中文的标点符号,这样就不会整段移动,而是在中文标点处停止再继续,基本符合使用的习惯了。</p>]]></content>
<summary type="html">
<h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><p>首先,vscode 是目前最好的编程工具,未来前途也无可限量,其次 vi 的快捷键模式也是最高效的键盘输入模式,在 vsco
</summary>
</entry>
<entry>
<title>如何保持专注高效地工作</title>
<link href="http://wind13.github.io/2018/07/31/how-to-focus-work/"/>
<id>http://wind13.github.io/2018/07/31/how-to-focus-work/</id>
<published>2018-07-31T10:19:58.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="问题和现象"><a href="#问题和现象" class="headerlink" title="问题和现象"></a>问题和现象</h2><p>小张喜欢做运维技术研究,特别是最新的 k8s 技术,在应聘时选择了一家公司,就是因为这家公司有相关的 k8s 方面的技术栈,然而到了这家公司一段时间后,感觉最近工作越来越压力大,越来越不顺利。</p><p>具体的一个事例是这样的,公司需要安装一套监控系统,小张本来是会直接部署服务器的,然而对技术的热爱,让他想去尝试用 docker 来实现部署,于是选择了用这个方案开始尝试,然而因为懂这方面技术的同事并不多,他只能一个人研究摸索,在这期间遇到很多技术难题,有些解决了,有些迟迟解决不了,也没有人可以讨论沟通,一个人在网上搜寻答案效率非常低。 同时公司其他同事还会因为各类大小不同的软硬件故障、系统问题时不时来打扰他,他也基本都热心去帮助解决,小张是一个遇到技术问题就想去解决的偏执狂,但这样也就会占用很多的工作时间,一转眼两周时间过去了,公司领导问监控系统的情况,得知居然还没有完成时,非常不满意,责令他当天必须完成,此时,小张感受到了无限的压力还有一肚子的委屈,却又不知道跟谁说理去,可谓“身心俱疲”啊!</p><p>分析以上情况,我给予两方面的建议如下:</p><h2 id="一、怎么安排好重要的工作?"><a href="#一、怎么安排好重要的工作?" class="headerlink" title="一、怎么安排好重要的工作?"></a>一、怎么安排好重要的工作?</h2><p>在接到公司安排的工作后,要做如下思考:</p><ol><li>公司为什么要做这个?对公司的意义在哪里?</li><li>预期的完成时间大概是什么时间?</li><li>预期的完成状态是什么样子?</li></ol><p>比如上例中,可能的答案是这样的:</p><ol><li>监控系统,这事对公司挺重要,即便技术上没什么难度,但多了决策的依据,所以对公司业务分析和决策很有意义,或者对于把控服务器的状态有很大的帮助,作为运维环节,监控系统也是必不可少的。</li><li>预期的完成时间,最长是一周,如果不顺利两周内怎么说也是要完成的。同时也可以跟公司沟通一下具体的期望完成时间。</li><li>预期完成的状态,其实要求并不高,只要先有一个监控数据界面就好了,后面有机会可以不断优化。公司并没有强调是不是用 docker 来容器化。</li></ol><p>通过沟通和分析得到以上问题的答案后,就可以将这件事安排到自己的工作面板中了,工作面板分为四列:Backlog(任务池)、待处理、处理中和已完成。</p><ol><li>Backlog(任务池): 这里通常堆了一堆想要做的事情、别人安排的事情,但是目前一定还没有开始的事情。</li><li>待处理: 这里通常是近期准备开始的事情,相应的解决方案、配套资源都已经到位,都知道详细的需求了,没有什么阻碍和问题了,只差的是具体的执行和操作了,通常这里的任务是要有预估完成时间、具体的执行人员安排以及优先次序的排列的。</li><li>处理中: 这里通常一个人只有一件正在做的事,也就是当下优先级最高的事情,可以按一定的周期(如:每天)更新完成状态(如:完成35%,或 2/5 表示共有5个子步骤/任务,已经完成 2 个。)</li><li>已完成: 已经交出结果,并通过验收的任务,没什么好说的,可以记录下实际的完成时间,未来可用于复盘或与预计完成时间对比和参考,不断调整预估的准确性。</li></ol><p>如果有些重要的工作环节比较多比较复杂,就需要拆分成多个任务放在上面的面板中,通常一个任务持续时间不要超过两天,但也不要短过半小时(即一个番茄钟的时间)。</p><h2 id="二、怎么处理干扰多的情况?"><a href="#二、怎么处理干扰多的情况?" class="headerlink" title="二、怎么处理干扰多的情况?"></a>二、怎么处理干扰多的情况?</h2><p>在公司工作,难免会有同事之间的协作,也就难免出现同事来打扰说事儿,首先不要在情绪上反感和讨厌这类打扰,通常来说这类打扰都是一次很好的机会,什么机会呢?</p><ol><li>了解公司问题、现状、同事的困难、业务的阻碍等;</li><li>表现你解决问题的能力、掌握的技术等的机会;</li><li>同事加强协作的机会,现在你帮他,也许哪天你也需要他帮你;</li></ol><p>如果哪一天你发现,再也没人来打扰你了,估计反倒是个危险的信号,你可能要离开这家公司了,同事们已经不再需要你了。</p><p>那么干扰太多又会占用很多时间,影响正常的工作进度怎么办?以下列出处理的具体步骤:</p><ol><li>当前是否在番茄工作中,如果是,礼貌地告知来访同事正在忙,大概15分钟后去找他;</li><li>如果不在番茄工作中,或者番茄工作完后,就主动去找来访同事,花10分钟了解问题缘由;</li><li>如果预估 5 分钟内可以解决,那就现场解决;</li><li>如果预估比较麻烦或者尝试了 5 分钟后仍不能解决,就给同事说明情况,告知问题的处理现状和可能原因,但要解决也许需要更多的时间和资源,需要另行安排。</li><li>在 4 的情况时,就要把问题和事情记录下来,也就是添加到 Backlog 一栏中,同时与当前手头的工作(即进行中那一栏的工作,通常只能有一件事)比较一下优先级,如果优先级不高,就继续手头的工作。</li><li>Backlog 中的工作最好也能排出优先级,最好能有预估的时间,初期可以给自己稍微宽松一些的期限设定,按照自己的工作时间来排程,比如:明天上午完成 A 事件,明天下午完成 B 事件,后天一天完成 C 事件的一半,大后天彻底完成 C 等。这样,你就可以给相应的同事或领导回报你的安排,如:“张总,您说的 C 事件,按我手头工作的排序,预计在后天开始,大后天完成,到时候需要您配合给我一台测试的电脑……您看怎么样?”,如果张总觉得不行,后天太迟,你可以把你当前的安排呈现给他,跟他沟通:“张总,您看,这是李总安排的 A 事件,还有王总安排的 B 事件,我预估顺利的话,明天一天也是要被占用的,如果您这事更急,可能需要您跟李总和王总一起商量一下,看我这边最优先做哪件。”</li><li>一旦最终商讨后定下了新的计划,就可以把新的时间安排以适当的形式(如:邮件、或公司的工作平台等)通知相关人员。</li></ol><p>相信以上思路可以给出一些启发性的思路,具体的工作还要具体分析,但总的原则要抓住,那些影响高效专注工作的问题,都是有办法解决的,不急不燥,保持自律(戒除“贪、嗔、痴”,哈哈……),总是能够解决的。</p>]]></content>
<summary type="html">
<h2 id="问题和现象"><a href="#问题和现象" class="headerlink" title="问题和现象"></a>问题和现象</h2><p>小张喜欢做运维技术研究,特别是最新的 k8s 技术,在应聘时选择了一家公司,就是因为这家公司有相关的 k8s 方面的
</summary>
</entry>
<entry>
<title>Ant Design React 使用记录</title>
<link href="http://wind13.github.io/2018/07/26/Ant-Design-React-Note/"/>
<id>http://wind13.github.io/2018/07/26/Ant-Design-React-Note/</id>
<published>2018-07-26T09:22:11.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h2><h3 id="Table-组件的服务端分页问题"><a href="#Table-组件的服务端分页问题" class="headerlink" title="Table 组件的服务端分页问题"></a>Table 组件的服务端分页问题</h3><ul><li><a href="http://09x.ant.design/components/table/" target="_blank" rel="noopener">Table 表格</a></li></ul><p>仔细看了一下,虽然 mock 中的数据是全部数据集,但是是模拟远程数据库的概念的,每次返回到客户端的数据还是单个页面的数据,所以这里可以理解为本身的设计就是支持服务端分页的。</p><h3 id="路由带参数问题"><a href="#路由带参数问题" class="headerlink" title="路由带参数问题"></a>路由带参数问题</h3><ul><li><a href="https://reacttraining.com/react-router/web/api/Route/route-props" target="_blank" rel="noopener">Route props - match</a></li></ul><h3 id="下载-Excel-模板的问题"><a href="#下载-Excel-模板的问题" class="headerlink" title="下载 Excel 模板的问题"></a>下载 Excel 模板的问题</h3><ul><li><a href="http://www.hacksparrow.com/using-node-js-to-download-files.html" target="_blank" rel="noopener">Using Node.js to download files</a></li></ul><h3 id="后端文档路径:-http-jp-open-service-thinkmacro-cn-swagger-ui-html"><a href="#后端文档路径:-http-jp-open-service-thinkmacro-cn-swagger-ui-html" class="headerlink" title="后端文档路径: http://jp-open-service.thinkmacro.cn/swagger-ui.html"></a>后端文档路径: <a href="http://jp-open-service.thinkmacro.cn/swagger-ui.html" target="_blank" rel="noopener">http://jp-open-service.thinkmacro.cn/swagger-ui.html</a></h3><h3 id="Form-相关参考:-http-react-component-github-io-form"><a href="#Form-相关参考:-http-react-component-github-io-form" class="headerlink" title="Form 相关参考: http://react-component.github.io/form/"></a>Form 相关参考: <a href="http://react-component.github.io/form/" target="_blank" rel="noopener">http://react-component.github.io/form/</a></h3><h3 id="Post-提交跨域问题:"><a href="#Post-提交跨域问题:" class="headerlink" title="Post 提交跨域问题:"></a>Post 提交跨域问题:</h3><ul><li>遇到 <code>Failed to load http://jp-open-service.thinkmacro.cn/login: No 'Access-Control-Allow-Origin' header is present on the requested</code></li><li>post 请求后,得到这个返回,是不是又是跨域问题?</li><li>发现问题,接口是用 query 传参的</li><li>又发现:如果密码正确,就有那项,如果密码不对,报500错就没有了。</li><li>估计是抛出异常时走了不同的代码逻辑。</li></ul><h3 id="解决向-route-子组件统一传参的问题:"><a href="#解决向-route-子组件统一传参的问题:" class="headerlink" title="解决向 route 子组件统一传参的问题:"></a>解决向 route 子组件统一传参的问题:</h3><ul><li><a href="https://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-children" target="_blank" rel="noopener">How to pass props to {this.props.children}</a></li><li><a href="https://stackoverflow.com/questions/31862839/passing-props-to-react-router-children-routes" target="_blank" rel="noopener">Passing props to React Router children routes</a></li></ul><h3 id="解决子组件中定义-meta-属性的需求:"><a href="#解决子组件中定义-meta-属性的需求:" class="headerlink" title="解决子组件中定义 meta 属性的需求:"></a>解决子组件中定义 meta 属性的需求:</h3><ul><li><a href="https://github.com/nfl/react-helmet" target="_blank" rel="noopener">react-helmet</a> A document head manager for React</li><li><a href="https://github.com/kodyl/react-document-meta" target="_blank" rel="noopener">React Document Meta</a> HTML meta tags for React-based apps.</li></ul><h2 id="相关文档资料"><a href="#相关文档资料" class="headerlink" title="相关文档资料"></a>相关文档资料</h2><ul><li><a href="http://reactkungfu.com/2016/03/dive-into-react-codebase-handling-state-changes/" target="_blank" rel="noopener">Dive into React codebase: Handling state changes</a> 深入了解 React 的状态变化机制</li><li><a href="https://www.jianshu.com/p/4784216b8194" target="_blank" rel="noopener">React组件生命周期小结</a></li><li><a href="https://github.com/AlanWei/blog/issues/10" target="_blank" rel="noopener">React v16.3 版本新生命周期函数浅析及升级方案</a></li></ul>]]></content>
<summary type="html">
<h2 id="遇到的问题"><a href="#遇到的问题" class="headerlink" title="遇到的问题"></a>遇到的问题</h2><h3 id="Table-组件的服务端分页问题"><a href="#Table-组件的服务端分页问题" class="
</summary>
<category term="antd" scheme="http://wind13.github.io/tags/antd/"/>
<category term="react" scheme="http://wind13.github.io/tags/react/"/>
<category term="redux" scheme="http://wind13.github.io/tags/redux/"/>
<category term="react-route" scheme="http://wind13.github.io/tags/react-route/"/>
</entry>
<entry>
<title>白话理解 Node.js 异步单线程</title>
<link href="http://wind13.github.io/2018/05/22/baihua-async/"/>
<id>http://wind13.github.io/2018/05/22/baihua-async/</id>
<published>2018-05-22T10:37:39.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<p>Nginx 和 Node.js 都是多进程单线程的。它通过事件轮询(event loop <a href="http://www.runoob.com/nodejs/nodejs-event-loop.html" target="_blank" rel="noopener">Node.js 事件循环</a>)来实现并行操作,因此,我们要尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。参考 <a href="http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/" target="_blank" rel="noopener">Understanding the node.js event loop</a></p><p>主线程和子线程,这里说的单线程,是说主线程只有一个,所以要把阻塞的运算处理分拆到子线程中去运行。</p><ul><li>使用回调函数</li><li>以非阻塞操作进行请求响应</li></ul><h2 id="几种可能的响应网络请求的方式:"><a href="#几种可能的响应网络请求的方式:" class="headerlink" title="几种可能的响应网络请求的方式:"></a>几种可能的响应网络请求的方式:</h2><ul><li>同步;最简单,但一个访问会阻塞其他访问;</li><li>分出新进程;还算简单,但大量的访问请求意味着大量的进程,会占用大量内存资源;</li><li>多线程;比较复杂,有些机器不支持线程,随着线程的增加,编程复杂度的增加也是很可怕的,很快就不知道怎么控制线程间的共享资源了。另外,线程占用内存会随请求数量增加快速增加,这也是为什么 Apache 比 Nginx 响应同样数量请求时占用更多的内存的原因。</li><li>单线程异步回调;也算简单,通过异步调用将主线程的任务分派到子线程中,通过回调函数来实现任务完成后的通知主线程及执行后续任务。</li></ul><h2 id="白话理解"><a href="#白话理解" class="headerlink" title="白话理解"></a>白话理解</h2><p>假设我们想做机器人卖米线的生意,我们要给机器人编程序,有煮米线的程序、收钱找钱的程序、擦桌子收碗的程序、端盘上饭的程序等。</p><p>同步的程序是最容易编写的,就是一件一件地做,一项一项地完成,一个步骤一个步骤地操作等。</p><p>那么同步的方式会带来什么问题呢?就是每来一个顾客请求,我们就开始处理这个请求,不理其他顾客甚至当前顾客的其他请求,如果当前的事情是比较费时的,比如煮米线,那么就会阻塞其他所有请求和顾客,这显然是不能接受的。</p><p>那么新进程的方式是什么意思呢?就好比复制多开了很多个米线摊,其他顾客的请求自然可以由其他米线摊来处理,但显然这很浪费资源,只有在需要开分店的时候才比较合适,那就是分布式架构加负载均衡所解决的问题了。但我们不能在一个店还没开好(高效运转)的时候就去搞连锁,那样会亏死的,所以先要把一个店的运转高效起来再说。</p><p>那么多线程的方式呢?可以想象就是一个摊儿或店,但雇佣了多个人,有人收钱,有人煮米线,但每个服务仍是同步单线程状态、即初级机器人水平,也就是说只专心做手头的事,做完一件事才做下一件事。</p><p>单线程异步回调的方式呢?就好像来了一个灵活的(机器)人(主线程),他来操作其他机器人,他接受请求,再命令其他专业的机器人做,然后他就又接受下一个请求……</p><p>这样就需要其他机器人是可以接受命令的,而煮米线机器人原来的方法是同步的,如下:</p><figure class="highlight javascript"><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="comment">/**</span></span><br><span class="line"><span class="comment"> * 口味: 大/小份,</span></span><br><span class="line"><span class="comment"> * 份量: 麻辣/三鲜</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">煮米线(口味, 份量) {</span><br><span class="line"> 花 <span class="number">5</span> 分钟煮一碗 此口味 此份量 的米线;</span><br><span class="line"> <span class="keyword">return</span> 米线;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>新的方法:</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 需求参数:</span></span><br><span class="line"><span class="comment"> * 口味: 大/小份,</span></span><br><span class="line"><span class="comment"> * 份量: 麻辣/三鲜</span></span><br><span class="line"><span class="comment"> * 完事儿干啥:</span></span><br><span class="line"><span class="comment"> * callback 回调函数</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">煮米线({需求参数}, 完事儿干啥) {</span><br><span class="line"> 花 <span class="number">5</span> 分钟煮一碗 需求参数.此口味 需求参数.此份量 的米线;</span><br><span class="line"> call 完事儿干啥();</span><br><span class="line">}</span><br><span class="line">下单米线(某口味, 某份量, 服务员) {</span><br><span class="line"> 煮米线({口味: 某口味, 份量:某份量}, 服务员.上菜);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>调用方法:</p><figure class="highlight javascript"><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">下单米线(三鲜, 小份, 服务员A);</span><br><span class="line">下单米线(麻辣, 大份, 服务员B);</span><br></pre></td></tr></table></figure><p>运行结果:</p><figure class="highlight javascript"><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">煮一碗 小份 三鲜 米线</span><br><span class="line">服务员A 端给客人</span><br></pre></td></tr></table></figure><h2 id="For-循环也要注意阻塞问题"><a href="#For-循环也要注意阻塞问题" class="headerlink" title="For 循环也要注意阻塞问题"></a>For 循环也要注意阻塞问题</h2><h3 id="以下示例证明-for-循环较大时会是个阻塞操作,同时证明-Node-js-是单线程的。"><a href="#以下示例证明-for-循环较大时会是个阻塞操作,同时证明-Node-js-是单线程的。" class="headerlink" title="以下示例证明 for 循环较大时会是个阻塞操作,同时证明 Node.js 是单线程的。"></a>以下示例证明 for 循环较大时会是个阻塞操作,同时证明 Node.js 是单线程的。</h3><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">proveSingleBlock</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> start = <span class="built_in">Date</span>.now();<span class="comment">//获取当前时间戳</span></span><br><span class="line"> <span class="keyword">var</span> n = <span class="number">0</span></span><br><span class="line"> setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">Date</span>.now() - start);</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">1000000000</span>; i++){<span class="comment">//执行长循环</span></span><br><span class="line"> n = n+<span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }, <span class="number">1000</span>);</span><br><span class="line"> setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">Date</span>.now() - start);</span><br><span class="line"> <span class="built_in">console</span>.log(n);</span><br><span class="line"> }, <span class="number">2000</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们在 Node.js 中就需要将如下的耗时较长的 for 循环:</p><figure class="highlight javascript"><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">function</span> <span class="title">block</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> n = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> x = <span class="number">0</span> ; x < <span class="number">1000000000</span>; x++){</span><br><span class="line"> <span class="comment">//do something crazy.</span></span><br><span class="line"> n = n+x;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> n;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>改写为下面这样:</p><figure class="highlight javascript"><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">function</span> <span class="title">noblock</span>(<span class="params">callback</span>) </span>{</span><br><span class="line"> setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> r = block();</span><br><span class="line"> <span class="keyword">if</span> (callback) { callback(r); }</span><br><span class="line"> }, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'async'</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>测试代码如下:</p><figure class="highlight javascript"><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="keyword">var</span> start = <span class="built_in">Date</span>.now();<span class="comment">//获取当前时间戳</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// block version</span></span><br><span class="line"><span class="built_in">console</span>.log(block());</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'Block version:'</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Date</span>.now() - start);</span><br><span class="line"></span><br><span class="line"><span class="comment">// no block setTimeout version</span></span><br><span class="line"><span class="built_in">console</span>.log(noblock(<span class="function"><span class="keyword">function</span>(<span class="params">r</span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(r);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'No block version:'</span>);</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">Date</span>.now() - start);</span><br><span class="line">}));</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">'Main end:'</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Date</span>.now() - start);</span><br></pre></td></tr></table></figure><h2 id="使用-ES6-的-Promise-实现异步"><a href="#使用-ES6-的-Promise-实现异步" class="headerlink" title="使用 ES6 的 Promise 实现异步"></a>使用 ES6 的 Promise 实现异步</h2><figure class="highlight javascript"><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="string">'#link'</span>).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"Enter"</span>);</span><br><span class="line"> <span class="keyword">var</span> asyncFunct = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve, reject</span>) </span>{</span><br><span class="line"> $(<span class="string">'#link'</span>).animate({ <span class="attr">width</span>: <span class="number">200</span> }, <span class="number">2000</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"finished"</span>);</span><br><span class="line"> resolve();</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line"> asyncFunct.then(<span class="function">(<span class="params">result</span>) =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"Exit"</span>);</span><br><span class="line"> });</span><br><span class="line">});</span><br></pre></td></tr></table></figure><p>还有 async/await, generator/yield 等</p><h2 id="多线程方案"><a href="#多线程方案" class="headerlink" title="多线程方案"></a>多线程方案</h2><h3 id="用-libuv-库来支持多线程"><a href="#用-libuv-库来支持多线程" class="headerlink" title="用 libuv 库来支持多线程"></a>用 libuv 库来支持多线程</h3><p>如果我们非要让 Node.js 支持多线程,还是提倡使用官方的做法,利用 libuv 库来实现。</p><blockquote><p>libuv是一个跨平台的异步I/O库,它主要用于 Node.js 的开发,同时他也被Mozilla’s Rust language, Luvit, Julia, pyuv等使用。它主要包括了Event loops事件循环, Filesystem 文件系统, Networking 网络支持, Threads 线程, Processes 进程, Utilities 其他工具。</p></blockquote><h3 id="tagg2模块-threads-a-gogo-库"><a href="#tagg2模块-threads-a-gogo-库" class="headerlink" title="tagg2模块 threads_a_gogo 库"></a>tagg2模块 <a href="https://github.com/xk/node-threads-a-gogo" target="_blank" rel="noopener">threads_a_gogo</a> 库</h3><p><a href="https://cnodejs.org/topic/518b679763e9f8a5424406e9" target="_blank" rel="noopener">threads_a_gogo 实现 nodejs 多线程,真正的非阻塞</a></p><h2 id="多进程方案"><a href="#多进程方案" class="headerlink" title="多进程方案"></a>多进程方案</h2><p>在支持 html5 的浏览器里,我们可以使用 webworker 来将一些耗时的计算丢入 worker 进程中执行,这样主进程就不会阻塞,用户也就不会有卡顿的感觉了。在 Node.js 中是否也可以使用这类技术,保证主线程的通畅呢?</p><h3 id="cluster"><a href="#cluster" class="headerlink" title="cluster"></a>cluster</h3><p>cluster可以用来让 Node.js 充分利用多核 cpu 的性能,同时也可以让 Node.js 程序更加健壮,官网上的 cluster 示例已经告诉我们如何重新启动一个因为异常而崩溃的子进程。</p><h3 id="webworker"><a href="#webworker" class="headerlink" title="webworker"></a>webworker</h3><p>想要像在浏览器端那样启动 worker 进程,我们需要利用 Node.js 核心 api 里的 child_process 模块。 child_process 模块提供了 fork 的方法,可以启动一个 Node.js 文件,将它作为 worker 进程,当 worker 进程工作完毕,把结果通过 send 方法传递给主进程,然后自动退出,这样我们就利用了多进程来解决主线程阻塞的问题。</p><h2 id="多进程和多线程"><a href="#多进程和多线程" class="headerlink" title="多进程和多线程"></a>多进程和多线程</h2><p>大部分多线程解决 cpu 密集型任务的方案都可以用我们之前讨论的多进程方案来替代,但是有一些比较特殊的场景多线程的优势就发挥出来了,比如 http web 服务器响应静态文件的例子。</p><p>以 express 处理小型静态文件为例,大致的处理流程如下:</p><ol><li>首先获取文件状态,判断文件的修改时间或者判断 etag 来确定是否响应 304 给客户端,让客户端继续使用本地缓存。</li><li>如果缓存已经失效或者客户端没有缓存,就需要获取文件的内容到 buffer 中,为响应作准备。</li><li>然后判断文件的 MIME 类型,如果是类似 html, js, css 等静态资源,还需要 gzip 压缩之后传输给客户端。</li><li>最后将 gzip 压缩完成的静态文件响应给客户端。</li></ol><p>用 ifile 包能得到 10 倍的速度和效率,不过 express 的作者TJ 说:</p><blockquote><p>请牢记你可能不需要这么高等级吞吐率的系统,就算是每月百万级别下载量的 npm 网站,也仅仅每秒处理 17 个请求而已,这样的压力甚至于 PHP 也可以处理掉(又黑了一把 php )。</p></blockquote><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>单线程的 Node.js 给我们编码带来了太多的便利和乐趣,我们应该时刻保持清醒的头脑,在写 Node.js 代码中切不可与 PHP 混淆,任何一个隐藏的问题都可能击溃整个线上正在运行的 Node.js 程序。</p><p>单线程异步的 Node.js 不代表不会阻塞,在主线程做过多的任务可能会导致主线程的卡死,影响整个程序的性能,所以我们要非常小心的处理大量的循环,字符串拼接和浮点运算等 cpu 密集型任务,合理的利用各种技术把任务丢给子线程或子进程去完成,保持 Node.js 主线程的畅通。</p><p>线程/进程的使用并不是没有开销的,尽可能减少创建和销毁线程/进程的次数,可以提升我们系统整体的性能和出错的概率。</p><p>最后请不要一味的追求高性能和高并发,因为我们可能不需要系统具有那么大的吞吐率。高效,敏捷,低成本的开发才是项目所需要的,这也是为什么 Node.js 能够在众多开发语言中脱颖而出的关键。</p><h2 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h2><ul><li><a href="https://www.jianshu.com/p/1887d9b446b2" target="_blank" rel="noopener">js的单线程和多进程</a></li><li><a href="https://github.com/DoubleSpout/threadAndPackage/blob/master/chapter.7.thread_and_process.md" target="_blank" rel="noopener">Node.js的线程和进程</a></li><li><a href="https://stackoverflow.com/questions/9516900/how-can-i-create-an-asynchronous-function-in-javascript" target="_blank" rel="noopener">How can I create an Asynchronous function in Javascript?</a></li></ul>]]></content>
<summary type="html">
<p>Nginx 和 Node.js 都是多进程单线程的。它通过事件轮询(event loop <a href="http://www.runoob.com/nodejs/nodejs-event-loop.html" target="_blank" rel="noopener"
</summary>
</entry>
<entry>
<title>GraphQL 学习</title>
<link href="http://wind13.github.io/2018/05/03/GraphQL-learning/"/>
<id>http://wind13.github.io/2018/05/03/GraphQL-learning/</id>
<published>2018-05-03T08:55:25.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h2><ul><li><a href="https://www.compose.com/articles/using-graphql-with-mongodb/" target="_blank" rel="noopener">Using GraphQL with MongoDB</a></li><li><a href="https://medium.com/entria/testing-a-graphql-server-using-jest-4e00d0e4980e" target="_blank" rel="noopener">Testing a GraphQL Server using Jest</a></li><li><a href="https://github.com/gajus/gajus.com-blog/blob/master/posts/using-dataloader-to-batch-requests/index.md" target="_blank" rel="noopener">using-dataloader-to-batch-requests</a></li><li><a href="https://hackernoon.com/how-graphql-replaces-redux-3fff8289221d" target="_blank" rel="noopener">How GraphQL Replaces Redux</a></li><li><a href="https://www.apollographql.com/client/" target="_blank" rel="noopener">js Client</a> Bind GraphQL data to your UI with one function call.</li></ul><h2 id="相关网站"><a href="#相关网站" class="headerlink" title="相关网站"></a>相关网站</h2><ul><li><a href="http://graphql.cn/" target="_blank" rel="noopener">GraphQL CN</a> A query language for APIs. 一种用于 API 的查询语言。</li><li><a href="http://graphql.cn/learn/best-practices/" target="_blank" rel="noopener">GraphQL 最佳实践</a></li><li><a href="https://github.com/chentsulin/awesome-graphql" target="_blank" rel="noopener">awesome-graphql</a></li><li><a href="https://www.howtographql.com/" target="_blank" rel="noopener">The Fullstack Tutorial for GraphQL</a> Youtube 视频教程</li><li><a href="https://github.com/graphql/graphiql" target="_blank" rel="noopener">GraphiQL</a> A graphical interactive in-browser GraphQL IDE. <a href="http://graphql.org/swapi-graphql" target="_blank" rel="noopener">Live demo</a></li><li><a href="https://lacinia.readthedocs.io/en/latest/" target="_blank" rel="noopener">Lacinia</a> - GraphQL for Clojure,<a href="https://github.com/walmartlabs/lacinia" target="_blank" rel="noopener">Github Repo</a> 一套 GraphQL 规范的完整实现,致力于维护对规范的外部兼容。</li><li><a href="https://github.com/alumbra/alumbra" target="_blank" rel="noopener">alumbra</a> Simple & Elegant GraphQL for Clojure!</li><li><a href="https://github.com/tendant/graphql-clj" target="_blank" rel="noopener">graphql-clj</a> A Clojure library designed to provide GraphQL implementation.</li><li><a href="http://graphql.cn/code" target="_blank" rel="noopener">流行的服务端框架、客户端库、服务</a></li><li><a href="https://dev-blog.apollodata.com/getting-started-with-typescript-and-apollo-a9aa2c7dcf87" target="_blank" rel="noopener">Getting started with TypeScript and Apollo</a></li><li><a href="https://facebook.github.io/relay/" target="_blank" rel="noopener">Relay</a> A JavaScript framework for building data-driven React applications</li><li><a href="https://github.com/swannodette/om-datascript" target="_blank" rel="noopener">Om Next w/ DataScript</a></li><li>Node.js 实现:<ul><li><a href="https://www.apollographql.com/docs/apollo-server/" target="_blank" rel="noopener">Apollo Server</a> is a flexible, community driven, production-ready HTTP GraphQL middleware for Express, Hapi, Koa, and more.</li><li><a href="https://github.com/graphql/express-graphql" target="_blank" rel="noopener">express-graphql</a></li></ul></li><li>以下内容部分摘自微信文章:<a href="https://mp.weixin.qq.com/s/g5zHRLFSBvHWaKLLhedtvQ" target="_blank" rel="noopener">微服务下使用GraphQL构建BFF的实践</a></li></ul><h2 id="微服务架构的优势-virtue-:"><a href="#微服务架构的优势-virtue-:" class="headerlink" title="微服务架构的优势(virtue):"></a>微服务架构的优势(virtue):</h2><p>简单说来,微服务是一种架构风格。通过对特定业务领域的分析与建模,将复杂的应用分解成小而专一、耦合度低并且高度自治的一组服务。微服务中的每个服务都是很小的应用,这些应用服务相互独立并且可部署。微服务通过对复杂应用的拆分,达到简化应用的目的,而这些耦合度较低的服务则通过 API 形式进行通信,所以服务之间对外暴露的都是 API,不管是对资源的获取还是修改。</p><ul><li>Isolation 隔离状态</li><li>Autonomy 自治</li></ul><h2 id="BFF-前端的中间层后端"><a href="#BFF-前端的中间层后端" class="headerlink" title="BFF 前端的中间层后端"></a>BFF 前端的中间层后端</h2><p>Backend for Frontends(以下简称 BFF) 顾名思义,是为前端而存在的后端 (服务) 中间层。引用了 BFF 之后,前端应用将直接和 BFF 通信,BFF 再和后端进行 API 通信,所以本质上来说,BFF 更像是一种“中间层”服务。</p><h3 id="BFF-其实是一种-API-Gateway-实现模式"><a href="#BFF-其实是一种-API-Gateway-实现模式" class="headerlink" title="BFF 其实是一种 API Gateway 实现模式"></a>BFF 其实是一种 API Gateway 实现模式</h3><h4 id="API-Gateway-的三种实现:"><a href="#API-Gateway-的三种实现:" class="headerlink" title="API Gateway 的三种实现:"></a>API Gateway 的三种实现:</h4><ul><li>一个 API Gateway 对所有客户端提供同一种 API,例:<code>/api/users</code></li><li>一个 API Gateway 通过 Router 对每种客户端提供分别的 API,例:<code>/mobile/api/users</code> 和 <code>/web/api/users</code></li><li>多个 API Gateway 分别对每种客户端提供分别的 API,例:如上,但两个 Gateway 分别为 Mobile Gateway 和 Web Gateway。</li></ul><p>BFF 其实是 API Gateway 的其中一种实现模式,即 BFF 更类似于第三种 API Gateway 实现,通常一个 BFF 对应一种客户端,再由 BFF 去调用后端的实际 API。</p><h2 id="GraphQL-与-REST-对比"><a href="#GraphQL-与-REST-对比" class="headerlink" title="GraphQL 与 REST 对比"></a>GraphQL 与 REST 对比</h2><h3 id="相比于-REST-风格,GraphQL-具有如下特性:"><a href="#相比于-REST-风格,GraphQL-具有如下特性:" class="headerlink" title="相比于 REST 风格,GraphQL 具有如下特性:"></a>相比于 REST 风格,GraphQL 具有如下特性:</h3><ol><li>定义数据模型:按需获取</li><li>数据分层</li><li>强类型</li><li>协议而非存储</li><li>无须版本化</li></ol><h3 id="对于-GraphQL-和-REST-之间的对比,主要有如下不同:"><a href="#对于-GraphQL-和-REST-之间的对比,主要有如下不同:" class="headerlink" title="对于 GraphQL 和 REST 之间的对比,主要有如下不同:"></a>对于 GraphQL 和 REST 之间的对比,主要有如下不同:</h3><ul><li>数据获取:REST 缺乏可扩展性, GraphQL 能够按需获取。GraphQL API 调用时,payload 是可以扩展的 ;</li><li>API 调用:REST 针对每种资源的操作都是一个 endpoint, GraphQL 只需要一个 endpoint( /graphql), 只是 post body 不一样 ;</li><li>复杂数据请求:REST 对于嵌套的复杂数据需要多次调用,GraphQL 一次调用, 减少网络开销;</li><li>错误码处理:REST 能够精确返回 HTTP 错误码,GraphQL 统一返回 200,对错误信息进行包装;</li><li>版本号:REST 通过 v1/v2 实现,GraphQL 通过 Schema 扩展实现;</li></ul><h2 id="微服务-GraphQL-BFF-实践"><a href="#微服务-GraphQL-BFF-实践" class="headerlink" title="微服务 + GraphQL + BFF 实践"></a>微服务 + GraphQL + BFF 实践</h2><p>在微服务下基于 GraphQL 构建 BFF,例如在项目对应的业务场景下,微服务后台有近 10 个微服务,客户端包括针对不同角色的 4 个 App 以及一个 Web 端。对于每种类型的 App,都有一个 BFF 与之对应。每种 BFF 只服务于这个 App。BFF 解析到客户端请求之后,会通过 BFF 端的服务发现,去对应的微服务后台通过 CQRS 的方式进行数据查询或修改。</p><p>使用 GraphQL-express 框架构建项目的 BFF 端,然后通过 Docker 进行部署。BFF 和微服务后台之间,还是通过 registrator 和 Consul 进行服务注册和发现。</p><p><img src="http://mmbiz.qpic.cn/mmbiz_png/aaVJqS7LaMLClPic6l1HLPZAEorehByj4Lg18e9bbBrEm61icnjq8xs5jz81PJLIuWVPo7ZdXW7iab9dicAIQdQzzw/640" alt="整体技术架构"></p><p>三个 App 客户端分别使用 GraphQL 的形式请求对应的 BFF。BFF 层再通过 Consul 服务发现和后端通信。</p><h3 id="关于系统中的鉴权问题"><a href="#关于系统中的鉴权问题" class="headerlink" title="关于系统中的鉴权问题"></a>关于系统中的鉴权问题</h3><p>用户登录后,App 直接访问 KeyCloak 服务获取到 id_token,然后通过 id_token 透传访问 auth-api 服务获取到 access_token, access_token 以 JWT (Json Web Token) 的形式放置到后续 http 请求的头信息中。</p><p>在我们这个系统中 BFF 层并不做鉴权服务,所有的鉴权过程全部由各自的微服务模块负责。BFF 只提供中转的功能。BFF 是否需要集成鉴权认证,主要看各系统自己的设计,并不是一个标准的实践。</p><h3 id="BFF-is-pary-of-Application-BFF-就是客户端的一部分"><a href="#BFF-is-pary-of-Application-BFF-就是客户端的一部分" class="headerlink" title="BFF is pary of Application, BFF 就是客户端的一部分"></a>BFF is pary of Application, BFF 就是客户端的一部分</h3><ul><li>BFF 中定义的数据结构,就是客户端所真正关心的。</li><li>BFF 就是为客户端而生,是客户端的一部分。</li><li>需要说明的是,对于“业务的关注”并不是说,BFF 会处理所有的业务逻辑,业务逻辑还是应该由微服务关心,BFF 关注的是客户端需要什么。</li></ul><h3 id="GraphQL-Mutation-与-CQRS"><a href="#GraphQL-Mutation-与-CQRS" class="headerlink" title="GraphQL Mutation 与 CQRS"></a>GraphQL Mutation 与 CQRS</h3><p>不同于 query,所有 mutation 都会调用后端的 API,而后端的 API 对于资源的修改也是通过 SpringBoot EventListener 实现的 CQRS 模式。</p><h3 id="新架构的测试"><a href="#新架构的测试" class="headerlink" title="新架构的测试"></a>新架构的测试</h3><p>在引入了 BFF 的项目,我们的测试仍然使用金字塔原理,只是在客户端和后台之间,需要添加对 BFF 的测试。</p><ul><li>Client 的 integration-test 关心的是 App 访问 BFF 的连通性,App 中所有访问 BFF 的请求都需要进行测试;</li><li>BFF 的 integration-test 测试的是 BFF 到微服务 API 的连通性,BFF 中依赖的所有 API 都应该有集成测试的保障;</li><li>API 的 integration-test 关注的是这个服务对外暴露的所有 API,通常测试所有的 Controller 中的 API。</li></ul>]]></content>
<summary type="html">
<h2 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h2><ul>
<li><a href="https://www.compose.com/articles/using-graphql-with-mon
</summary>
<category term="TypeScript" scheme="http://wind13.github.io/tags/TypeScript/"/>
<category term="React" scheme="http://wind13.github.io/tags/React/"/>
<category term="GraphQL" scheme="http://wind13.github.io/tags/GraphQL/"/>
</entry>
<entry>
<title>一图看懂 AntD 的结构</title>
<link href="http://wind13.github.io/2018/03/29/one-pic-know-antd/"/>
<id>http://wind13.github.io/2018/03/29/one-pic-know-antd/</id>
<published>2018-03-29T03:07:53.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<p><img src="/images/antd-one-pic-bw.gif" alt="一图看懂 AntD 的结构"></p><p>个人理解,仅供参考!</p><p>在开发时,仅需关注图中的那些 <code>*.js</code> 文件即可。</p>]]></content>
<summary type="html">
<p><img src="/images/antd-one-pic-bw.gif" alt="一图看懂 AntD 的结构"></p>
<p>个人理解,仅供参考!</p>
<p>在开发时,仅需关注图中的那些 <code>*.js</code> 文件即可。</p>
</summary>
<category term="AntD" scheme="http://wind13.github.io/tags/AntD/"/>
<category term="一图" scheme="http://wind13.github.io/tags/%E4%B8%80%E5%9B%BE/"/>
</entry>
<entry>
<title>2018年3月23日这期“歌手”听后感</title>
<link href="http://wind13.github.io/2018/03/24/2018-3-23-singer-feeling/"/>
<id>http://wind13.github.io/2018/03/24/2018-3-23-singer-feeling/</id>
<published>2018-03-24T07:49:23.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h1 id="2018年3月23日这期“歌手”听后感"><a href="#2018年3月23日这期“歌手”听后感" class="headerlink" title="2018年3月23日这期“歌手”听后感"></a>2018年3月23日这期“歌手”听后感</h1><p>这一期两位歌手都唱了崔健的歌,腾格尔唱《从头再来》,华晨宇唱《假行僧》,可见崔健中国摇滚之父的称号不是虚的。</p><p>从1993年大学时听过崔健的歌后,就将他奉为中国甚至世界摇滚中最为独特另类的一个,后来在几十年中,偶尔再听还是那么独特,不管时代如何变迁,他的音乐依然在每次听到的时候都有特殊的感觉。</p><p>这期“歌手”再次证明了这一点,崔健的摇滚即使在今天这个信息智能时代听起来依然是最新潮、最牛逼的!</p><p>不过相对来说,我更欣赏华晨宇的改编,是新一代音乐人用自己的灵魂对崔健《假行僧》的自我诠释,中间一度听得我两眼含泪,华晨宇是个可怜孩子,心灵的孤独和寂苦在小时候长时间无人知道、无人理解、无人关爱,好在自己在音乐中找到了表达,从而也造就了今天的新一代音乐天才和新星。有过童年悲伤经历的人们应该能感受到音乐中那种透达心底的孤寂,也应该更能理解这表面有些怪异的音乐和演唱方式所传达的空灵宇宙间的无奈和无所谓……</p><p>腾格尔的演唱基本是崔健摇滚的原本风格,没太多新的创新,当然也没有崔健原版的风格独特和反抗精神。嗯,再去找崔健的原版演唱会看一下……</p>]]></content>
<summary type="html">
<h1 id="2018年3月23日这期“歌手”听后感"><a href="#2018年3月23日这期“歌手”听后感" class="headerlink" title="2018年3月23日这期“歌手”听后感"></a>2018年3月23日这期“歌手”听后感</h1><p>这一
</summary>
<category term="歌手" scheme="http://wind13.github.io/tags/%E6%AD%8C%E6%89%8B/"/>
<category term="崔健" scheme="http://wind13.github.io/tags/%E5%B4%94%E5%81%A5/"/>
<category term="华晨宇" scheme="http://wind13.github.io/tags/%E5%8D%8E%E6%99%A8%E5%AE%87/"/>
</entry>
<entry>
<title>为什么说一个全新的操作系统是必要的?</title>
<link href="http://wind13.github.io/2018/03/05/why-new-os-zh/"/>
<id>http://wind13.github.io/2018/03/05/why-new-os-zh/</id>
<published>2018-03-05T04:12:25.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<p>注:此文是 OSv 官网介绍的文章,感觉对于理解 OSv 很有帮助,特翻译如下,<a href="http://osv.io/why-new-os/" target="_blank" rel="noopener">原文地址</a></p><p>Today’s cloud-based applications run a heavyweight stack: the hypervisor, which divides the hardware resources among virtual machines; the operating system, which divides the virtual machine’s resources among applications; and the application server, which divides the application’s resources among the end users.</p><p>当今的云应用都运行在一个非常重的技术栈上: Hypervisor (虚拟机管理程序) ,要将硬件资源从虚拟机中分离; OS 操作系统,要将虚拟机从应用中分离; App Server 应用服务,要将应用资源从终端用户处分离。</p><p>Clearly, there is a lot of duplication going on. Each layer adds its own overhead in an attempt to abstract away and hide the problems caused by the lower layer. The result is inefficient and complex.</p><p>很明显,这中间有很多的重复。每一层都添加了额外的开销用来抽象和隐藏低一层所产生的问题。结果是低效和复杂的。</p><p>Enter OSv - the operating system for the cloud. On the one hand, designed and optimized to run on a hypervisor. On the other hand, designed to run an application stack without getting in the way. Designed for the cloud.</p><p>来到 OSv —— 专为云而生的操作系统。一方面,它是专为虚拟机管理而设计和优化的。另一方面,专为无障碍地运行整个应用(包括 OS 系统)。专为云设计。</p><h2 id="It’s-cloudy-out-there-and-we-love-it"><a href="#It’s-cloudy-out-there-and-we-love-it" class="headerlink" title="It’s cloudy out there and we love it"></a>It’s cloudy out there and we love it</h2><h2 id="它就在云上,我们喜欢它!"><a href="#它就在云上,我们喜欢它!" class="headerlink" title="它就在云上,我们喜欢它!"></a>它就在云上,我们喜欢它!</h2><p>The public cloud era opens new horizons and opportunities for hi-tech businesses. Virtualization is dominant, resources are evergreen and agility is the key. The role of the OS in this form changes. The need to massively scale out forces developers to run multiple copies of identical Virtual Machines (VMs). VMs are the new process that needs to be lightweight, blazing fast, scalable and cheap. DevOps and PaaS solutions bypass the OS and allow developers to deploy their code directly to the cloud. All these goodies are rapidly penetrating the enterprise space with matching private cloud capabilities and virtual appliances that act as bridges to the public cloud</p><p>公有云时代为高科技企业展开了全新的视野和机会。虚拟机占到了主导地位,资源的快速响应和持久在线是关键。而操作系统 OS 的角色在这样的情况下也有所改变。大规模扩展的需求迫使开发人员同时要运行多个相同的虚拟机(VM)。 VMs 是一个需要轻量级、快速、可扩展和廉价的新流程。DevOps 和 PaaS 解决方案绕过操作系统,允许开发者将代码直接放到云上。所有这些优点都迅速渗透到企业空间中,并提供了与公有云相匹配的私有云功能和虚拟设备。</p><h2 id="Virtualization-2-0"><a href="#Virtualization-2-0" class="headerlink" title="Virtualization 2.0"></a>Virtualization 2.0</h2><h2 id="虚拟化-2-0"><a href="#虚拟化-2-0" class="headerlink" title="虚拟化 2.0"></a>虚拟化 2.0</h2><p>VMware had brought virtualization into the x86 world (recall that virtualization was introduced by IBM’s mainframes in the 70s). While VMware has done a fantastic job shifting the enterprise from physical to virtual, it stopped there. Amazon Web Services had wider vision; Amazon do not use terminology such as virtual machine. Amazon sees the entire user workload and solves scaling issues.</p><p>VMware 将虚拟化引入到了 x86 型机的世界(记得虚拟化是由IBM的大型机在上世纪70年代引入的概念)。虽然 VMware 做了一项出色的工作,将企业从物理机带入虚拟机世界,但它也就止步于此。 而 Amazon 网络服务则有更广阔的视野; Amazon 不使用诸如虚拟机之类的术语。 Amazon 看到了用户整个的工作负载并解决了缩放问题。 </p><p>The right(tm) way - the new world is compose out of the smallest building blocks possible, running in clusters of multiple VMs. Common components are NoSQL databases, MemCacheD, front end webservers, backend webservers, etc. One single application is hosted within the virtual machine. That application uses a fraction of the guest OS capabilities - there is no hardware as the hypervisor owns that, there are no real users as this is a server, there are no other apps to schedule. Users pay for CPU cycles they don’t really need and need to maintain and tune a full blown generic OS.</p><p>正确(TM)的方式 —— 新的世界是由尽可能小的积木组成,运行在多个虚拟机集群中。 常见的组件是 NoSQL 数据库,缓存,前端 Web 服务器,后台服务器等,单个应用程序托管在虚拟机内。该应用程序使用了客户机操作系统功能的一小部分——没有 Hypervisor (虚拟机管理程序) 中的硬件,没有真正的用户,因为这是一个服务器,没有其他应用程序需要去调度。 所以用户不必为他们并不真正需要的 CPU 损耗付费,也不必维护和调整一个完整的通用操作系统。 </p><p>Unlike new infrastructure such as hypervisors, NoSQL, PaaS, etc, the operating system hasn’t changed much. The same OS image that powers physical machines, from tiny embedded devices to room-size top500 supercomputers, is also used in the cloud.</p><p>不象新的基础设施如 Hypervisors 虚拟机管理程序,NoSQL,PaaS 等,操作系统并没有太大变化。 与之相同的实现了物理机功能的操作系统映像 (从小型嵌入式设备的房间大小的TOP500超级计算机) 也都用在了云上。 </p><p>Typical cloud workloads run application servers using Java, Ruby, Python and JavaScript (node.js). This historical evolution is not ideal - Java, Linux and the hypervisor implement parallel/duplicated mechanisms for protection and abstraction. These mechanisms are redundant when combined, and impose a large overhead in terms of CPU and memory.</p><p>常见的云应用服务器使用 Java、Ruby、Python 和 JavaScript (node.js)。而这个历史演变过程实际并不理想 —— Java, Linux 和 Hypervisor (虚拟机管理程序) 为了保护和抽象而实现了并行或复制机制。这些机制在组合时是多余的,在 CPU 和内存方面强加了大量的开销。 </p><p>The management efforts needed to maintain Linux are extensive. Thousands of packages, multiple security updates, complex tuning and specialists to manage. It doesn’t stop in the OS level. JVM workloads require manual tuning in a variety of ways and VM templates and instances needs to be software managed by tools like Puppet and Chef.</p><p>维护 Linux 所需的管理工作是广泛的。 数千个包、多个安全更新、复杂的配置和专用列表需要管理。它不会停止在操作系统级别。JVM 工作负载需要以各种方式手动调优,VM 模板和实例也需要用像 Puppet 和 Chef 这样的工具软件来管理。 </p><p>These tools help to manage multiple OS configurations but if we’ll examine their operation on a single OS instance, we’ll discover that their roots go to the Unix OS of the 1970s. They’re based on pushing human configuration files and strings to /etc files. Typical OSs still do not have a fully automated API. OSv takes a simpler approach, with a common REST API for all configuration and data collection.</p><p>这些工具有助于管理多个操作系统配置, 但如果我们在一个操作系统实例上检查它们的操作,我们会发现它们根本是在 20 世纪 70 年代的 UNIX 操作系统上建立的, 它们是基于将人为的配置文件和字符串入到 /etc 文件目录中来实现的。 常见的操作系统仍然没有完全自动化的 API 。而 OSv 则是用一个简单的方法,用一个共同的 REST API 来完成所有的配置和数据采集。</p>]]></content>
<summary type="html">
<p>注:此文是 OSv 官网介绍的文章,感觉对于理解 OSv 很有帮助,特翻译如下,<a href="http://osv.io/why-new-os/" target="_blank" rel="noopener">原文地址</a></p>
<p>Today’s cloud-
</summary>
<category term="Hypervisor" scheme="http://wind13.github.io/tags/Hypervisor/"/>
<category term="OSv" scheme="http://wind13.github.io/tags/OSv/"/>
</entry>
<entry>
<title>SVG 相关学习</title>
<link href="http://wind13.github.io/2018/02/10/SVG-%E7%9B%B8%E5%85%B3%E5%AD%A6%E4%B9%A0/"/>
<id>http://wind13.github.io/2018/02/10/SVG-相关学习/</id>
<published>2018-02-10T11:32:40.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="JavaScript-library"><a href="#JavaScript-library" class="headerlink" title="JavaScript library"></a>JavaScript library</h2><ul><li><a href="http://svgjs.com/" target="_blank" rel="noopener">SVG.js</a> The lightweight library for manipulating and animating SVG.</li><li><a href="https://bonsaijs.org/" target="_blank" rel="noopener">Bonsai</a> A lightweight graphics library with an intuitive graphics API and an SVG renderer.</li><li><a href="http://snapsvg.io/" target="_blank" rel="noopener">Snap.svg</a> The JavaScript SVG library for the modern web</li></ul><h2 id="Draw-library"><a href="#Draw-library" class="headerlink" title="Draw library"></a>Draw library</h2><ul><li><a href="http://sc.chinaz.com/info/150826129135.htm" target="_blank" rel="noopener">15个最佳SVG的JavaScript库</a></li><li><a href="https://segmentfault.com/q/1010000002759556" target="_blank" rel="noopener">推荐 SVG 图标素材网站</a></li><li><a href="http://www.iconfont.cn/" target="_blank" rel="noopener">IconFont.cn</a> 国内图标库网站</li><li><a href="https://github.com/nullice/NViconsLib_Silhouette" target="_blank" rel="noopener">国内外社交网站矢量图标</a></li><li><a href="https://www.flaticon.com/" target="_blank" rel="noopener">FlatIcon</a> The largest database of free icons available in PNG, SVG, EPS, PSD and BASE 64 formats.</li><li><a href="https://worldvectorlogo.com/" target="_blank" rel="noopener">Worldvectorlogo</a> 矢量标志的所有品牌 完全免费和无限制</li></ul><h2 id="Tools"><a href="#Tools" class="headerlink" title="Tools"></a>Tools</h2><ul><li><a href="https://designer.io/" target="_blank" rel="noopener">Gravit Designer</a> 一款跨平台的设计工具,可以在 AppStore 中直接下载。新发现的,感觉不错,强烈推荐,需要英文门槛。 参考:<a href="http://www.sohu.com/a/205549958_99940811" target="_blank" rel="noopener">欢迎来到设计利器Gravit Designer的世界</a> </li><li><a href="https://www.wobastic.com/omber/" target="_blank" rel="noopener">Omber</a> 可制作图形和色彩渐变效果的工具,可在 AppStore 中直接下载。</li><li><a href="https://inkscape.org/zh/" target="_blank" rel="noopener">Inkscape</a> Draw Freely. 自油自画。跨系统,Linux 上也是首选。缺点:需要先安装<a href="https://www.xquartz.org/" target="_blank" rel="noopener">XQuartz</a>。</li><li><a href="https://vectr.com/" target="_blank" rel="noopener">Vectr</a> is a free graphics software used to create vector graphics easily and intuitively. It’s a simple yet powerful web and desktop cross-platform tool to bring your designs into reality. 可以在 AppStore 中直接下载。</li><li><a href="http://macsvg.org/" target="_blank" rel="noopener">macSVG</a> An open-source macOS app for designing HTML5 SVG art and animation. <a href="https://github.com/dsward2/macSVG" target="_blank" rel="noopener">Github repo</a></li><li><a href="https://www.calligra.org" target="_blank" rel="noopener">Calligra</a> part of the KDE community.</li><li><a href="http://glipssvgeditor.sourceforge.net/" target="_blank" rel="noopener">GlipsSvgEditor</a> An open source SVG graphics editor and a SCADA HMI editor. 似乎是(SCADA(Supervisory Control And Data Acquisition)系统,即数据采集与监视控制系统。)专业领域的画图工具,界面粗糙。</li><li><a href="http://latexdraw.sourceforge.net/" target="_blank" rel="noopener">LaTeXDraw</a> is a graphical drawing editor for LaTeX. LaTeXDraw can be used to 1) generate PSTricks code; 2) directly create PDF or PS pictures. LaTeXDraw is developed in Java and thus runs on top of Linux, Windows, and Mac OS X. You need Java 8 to launch LaTeXDraw.</li><li><a href="http://vectorpaint.yaks.co.nz/" target="_blank" rel="noopener">VectorPaint</a> Draw SVG online. 在线绘制工具。</li></ul>]]></content>
<summary type="html">
<h2 id="JavaScript-library"><a href="#JavaScript-library" class="headerlink" title="JavaScript library"></a>JavaScript library</h2><ul>
<li>
</summary>
<category term="SVG" scheme="http://wind13.github.io/tags/SVG/"/>
<category term="Graphic" scheme="http://wind13.github.io/tags/Graphic/"/>
<category term="JavaScript" scheme="http://wind13.github.io/tags/JavaScript/"/>
</entry>
<entry>
<title>Computer Vision 学习</title>
<link href="http://wind13.github.io/2018/02/07/Computer-Vision-%E5%AD%A6%E4%B9%A0/"/>
<id>http://wind13.github.io/2018/02/07/Computer-Vision-学习/</id>
<published>2018-02-07T16:17:34.000Z</published>
<updated>2019-10-28T23:32:40.000Z</updated>
<content type="html"><![CDATA[<h2 id="Computer-Vision-Library"><a href="#Computer-Vision-Library" class="headerlink" title="Computer Vision Library"></a>Computer Vision Library</h2><ul><li><a href="https://www.quora.com/What-are-pros-and-cons-of-OpenCV-and-TensorFlow-for-computer-vision" target="_blank" rel="noopener">What are pros and cons of OpenCV and TensorFlow for computer vision?</a></li><li><a href="http://libccv.org/" target="_blank" rel="noopener">ccv</a> A Modern Computer Vision Library</li><li><a href="http://simplecv.org/" target="_blank" rel="noopener">SimpleCV</a> Computer Vision platform using Python.</li><li><a href="https://cecas.clemson.edu/~stb/blepo/" target="_blank" rel="noopener">Blepo</a> Computer Vision Library</li><li><a href="https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000" target="_blank" rel="noopener">Python教程</a></li></ul><h2 id="OpenCV-vs-VXL-vs-LTI-Performance-Test"><a href="#OpenCV-vs-VXL-vs-LTI-Performance-Test" class="headerlink" title="OpenCV vs VXL vs LTI: Performance Test"></a>OpenCV vs VXL vs LTI: Performance Test</h2><blockquote><p>I recently read this comparison of four vision libraries: OpenCV, VXL, LTI and OpenCV with IPP. It was in the book Learning Learning OpenCV: Computer Vision with the OpenCV Library, authored by the creators of OpenCV themselves. For those who aren’t familiar with these libraries, here’s a brief introduction.</p></blockquote><h3 id="VXL"><a href="#VXL" class="headerlink" title="VXL"></a>VXL</h3><blockquote><p>VXL stands for Vision something Library. It is a C++ library that implements several common computer vision algorithms and related functionality. The idea is to replace the ‘X’ with one of the several letters:</p></blockquote><ul><li>VGL = Vision Geometry Library</li><li>VIL = Vision Image processing Library</li><li>VNL = Vision Numerics Library</li><li>VSL = Vision Streaming Library</li></ul><p>There are several other libraries as well</p><h3 id="LTI"><a href="#LTI" class="headerlink" title="LTI"></a>LTI</h3><blockquote><p>LTI-Lib is another object oriented library for computer vision. It has also been implemented in C++. It also includes classes that encapsulate multithreading, synchronization, serial port access, etc. And it ensures you don’t have to deal with changing operating systems or hardware.</p></blockquote><h3 id="OpenCV"><a href="#OpenCV" class="headerlink" title="OpenCV"></a>OpenCV</h3><blockquote><p>Yet another computer vision library. It includes over 500 functions for various commonly used algorithms. It also comes with a machine learning library and a portable window creation library. With version 2.0, OpenCV comes with a C++ interface as well. Before 2.0, it was only the C interface.</p></blockquote><h3 id="OpenCV-IPP"><a href="#OpenCV-IPP" class="headerlink" title="OpenCV + IPP"></a>OpenCV + IPP</h3><blockquote><p>OpenCV developers were friendly with the Intel Performance Primitives team. So, OpenCV makes use of IPP code (which is hand tuned and extremely optimized code) to speed up execution. And this, as you’ll see, gives a substantial boost to its execution speed.</p></blockquote>]]></content>
<summary type="html">
<h2 id="Computer-Vision-Library"><a href="#Computer-Vision-Library" class="headerlink" title="Computer Vision Library"></a>Computer Vision L
</summary>
<category term="Computer Vision" scheme="http://wind13.github.io/tags/Computer-Vision/"/>
<category term="OpenCV" scheme="http://wind13.github.io/tags/OpenCV/"/>
</entry>
</feed>