-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
2092 lines (1005 loc) · 528 KB
/
search.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
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>wsl-代理问题</title>
<link href="/2023/07/28/wsl-%E4%BB%A3%E7%90%86%E9%97%AE%E9%A2%98/"/>
<url>/2023/07/28/wsl-%E4%BB%A3%E7%90%86%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>wsl 设置代理时遇到的问题</p><span id="more"></span><figure class="highlight bash"><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="built_in">export</span> HTTP_PROXY=http://<span class="variable">${cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }</span><span class="string">'}:7890</span></span><br><span class="line"><span class="string">export HTTPS_PROXY=http://${cat /etc/resolv.conf | grep nameserver | awk '</span>{ <span class="built_in">print</span> <span class="variable">$2</span> }<span class="string">'}:7890</span></span><br></pre></td></tr></table></figure><p>如果无法访问宿主机ip, 可能是因为宿主机的防火墙没有打开</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">New-NetFirewallRule -DisplayName <span class="string">"WSL"</span> -Direction Inbound -InterfaceAlias <span class="string">"vEthernet (WSL)"</span> -Action Allow</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> wsl </category>
</categories>
<tags>
<tag> wsl </tag>
</tags>
</entry>
<entry>
<title>rust教程-08</title>
<link href="/2022/11/13/rust%E6%95%99%E7%A8%8B-08/"/>
<url>/2022/11/13/rust%E6%95%99%E7%A8%8B-08/</url>
<content type="html"><![CDATA[<p>rust 教程 07: vector, string, hashmap</p><span id="more"></span><h2 id="vector"><a class="markdownIt-Anchor" href="#vector"></a> Vector</h2><h3 id="vector-的基本使用"><a class="markdownIt-Anchor" href="#vector-的基本使用"></a> vector 的基本使用</h3><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="comment">// 必须要指明类型,或者通过 push,能够让编译器知道 v 的类型</span></span><br><span class="line"> <span class="comment">// 离开作用域的时候,v 就被删除了</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">v</span>: <span class="type">Vec</span><<span class="type">i32</span>> = <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 不用显示指明类型</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">v2</span> = <span class="built_in">vec!</span>[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>];</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 因为 push 了一个 i32 类型的数据,所以不需要显示地指明类型</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">v3</span> = <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> v3.<span class="title function_ invoke__">push</span>(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// -------</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 两种读取 vector 元素的方法</span></span><br><span class="line"> <span class="comment">// 1. 通过索引</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">x</span> = &v2[<span class="number">1</span>];</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 2. 通过 get 方法</span></span><br><span class="line"> <span class="keyword">match</span> v2.<span class="title function_ invoke__">get</span>(<span class="number">1</span>) {</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(x) => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"x is: {}"</span>, x);</span><br><span class="line"> },</span><br><span class="line"> <span class="literal">None</span> => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"x is None"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// -------</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 不能在同一作用域内同时拥有可变和不可变引用</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">v4</span> = <span class="type">Vec</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">first</span> = &v4[<span class="number">1</span>]; <span class="comment">// 不可变借用</span></span><br><span class="line"> v4.<span class="title function_ invoke__">push</span>(<span class="number">10</span>); <span class="comment">// 可变借用,和上面的不可变借用发生冲突,</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"first is {}"</span>, first);</span><br><span class="line"> <span class="comment">// 因为 push 的过程如果 vector 内存不够,则导致 vector 重新分配内润地址,所以此时不可变借用就失效了,因此编译器不允许这种情况出现</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// -------</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// for 循环</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">v5</span> = <span class="built_in">vec!</span>[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">i</span> <span class="keyword">in</span> &<span class="keyword">mut</span> v5 {</span><br><span class="line"> *i += <span class="number">10</span>; <span class="comment">// 修改 v5 的值</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">i</span> <span class="keyword">in</span> &v5 { <span class="comment">// 循环打印</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"i is {}"</span>, i);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"Hello, world!"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="vector-的例子"><a class="markdownIt-Anchor" href="#vector-的例子"></a> vector 的例子</h3><p>使用 enum 改变 vector 元素的类型</p><figure class="highlight rust"><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="keyword">enum</span> <span class="title class_">SheetCell</span> {</span><br><span class="line"> <span class="title function_ invoke__">Int</span>(<span class="type">i32</span>),</span><br><span class="line"> <span class="title function_ invoke__">Float</span>(<span class="type">f64</span>),</span><br><span class="line"> <span class="title function_ invoke__">Text</span>(<span class="type">String</span>),</span><br><span class="line">}</span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">row</span> = <span class="built_in">vec!</span>[</span><br><span class="line"> SheetCell::<span class="title function_ invoke__">Int</span>(<span class="number">1</span>),</span><br><span class="line"> SheetCell::<span class="title function_ invoke__">Float</span>(<span class="number">10.0</span>),</span><br><span class="line"> SheetCell::<span class="title function_ invoke__">Text</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdasd"</span>)),</span><br><span class="line"> ];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="string"><a class="markdownIt-Anchor" href="#string"></a> String</h2><p>rust 的核心语言层面,只有一个字符串类型,即字符串切片 str 或者 &str,对存储在其他地方、UTF-8编码的字符串的引用</p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="comment">// -------</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建字符串类型的几种方法</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdasd"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s1</span> = <span class="string">"adadad"</span>.<span class="title function_ invoke__">to_string</span>();</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">data</span> = <span class="string">"dasdad"</span>;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s2</span> = data.<span class="title function_ invoke__">to_string</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// -------</span></span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 更新 string</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s3</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdada"</span>);</span><br><span class="line"> s3.<span class="title function_ invoke__">push_str</span>(<span class="string">"asdadasd"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s4</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"sdasd"</span>);</span><br><span class="line"> s3.<span class="title function_ invoke__">push_str</span>(&s4); <span class="comment">// 不会改变 s4 的所有权</span></span><br><span class="line"> s3.<span class="title function_ invoke__">push</span>(<span class="string">'1'</span>); <span class="comment">// 附加一个字符</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 取得了 s3 的所有权,s3会失效</span></span><br><span class="line"> <span class="comment">// &s4 被强制转换为字符串切片 &str,解引用强制类型转换</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s5</span> = s3+&s4; </span><br><span class="line"></span><br><span class="line"> <span class="comment">// 可以直接用 format 来构建新字符串,这样不会改变所有权</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s5</span> = <span class="built_in">format!</span>(<span class="string">"{}-{}-{}"</span>, s1, s2, s5);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// -------</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 访问字符串元素</span></span><br><span class="line"> <span class="comment">// String 不支持索引形式访问元素</span></span><br><span class="line"> <span class="comment">// String 是对 vec<u8> 的包装</span></span><br><span class="line"> <span class="comment">// 由于 String 是一种 utF-8 编码,所以索引的位置指代的不一定就是字符的位置,有可能是某个字节</span></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">w</span> <span class="keyword">in</span> s5.<span class="title function_ invoke__">chars</span>() { <span class="comment">// 获得标量值</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{}"</span>, w);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> <span class="variable">w</span> <span class="keyword">in</span> s5.<span class="title function_ invoke__">bytes</span>() { <span class="comment">// 获得字节</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{}"</span>, w);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 字符串切片</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s6</span> = &s5[<span class="number">0</span>..<span class="number">4</span>]; <span class="comment">// 必须沿着字符的边界进行切割(比如一个字符占两个字节),否则就会 panic</span></span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="hashmapk-v"><a class="markdownIt-Anchor" href="#hashmapk-v"></a> HashMap<K, V></h2><p>以键值对的形式存储数据,一个键对应一个值</p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> std::collections::HashMap;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"></span><br><span class="line"> <span class="comment">// -----------</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// hashmap 是同构的,即 k 必须是同一类型,v 必须是同一类型</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">scores</span> = HashMap::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> scores.<span class="title function_ invoke__">insert</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdads"</span>), <span class="number">10</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 通过 collect 来创建 hashmap</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">teams</span> = <span class="built_in">vec!</span>[</span><br><span class="line"> <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdad"</span>),</span><br><span class="line"> <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"agdfgd"</span>),</span><br><span class="line"> ];</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">initial_scores</span> = <span class="built_in">vec!</span>[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>];</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">scores</span>: HashMap<_,_> = <span class="comment">// 用下划线是因为编译器可以根据 vector 中的元素推导出 k v 的类型</span></span><br><span class="line"> teams.<span class="title function_ invoke__">iter</span>().<span class="title function_ invoke__">zip</span>(initial_scores.<span class="title function_ invoke__">iter</span>()).<span class="title function_ invoke__">collect</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 所有权问题</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s1</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdasd"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s2</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdasd"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">map</span> = HashMap::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> map.<span class="title function_ invoke__">insert</span>(&s1, &s2); <span class="comment">// 传递引用不会改变所有权</span></span><br><span class="line"> <span class="comment">// map.insert(s1, s2); // 会改变 s1 和 s2 的所有权</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 通过 get 取得 hashmap 的值</span></span><br><span class="line"> <span class="keyword">match</span> map.<span class="title function_ invoke__">get</span>(&<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdas"</span>)) {</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(x) => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{}"</span>, x);</span><br><span class="line"> },</span><br><span class="line"> <span class="literal">None</span> => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"None"</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 通过 for 循环遍历 hashmap 的值</span></span><br><span class="line"> <span class="title function_ invoke__">for</span> (k,v) <span class="keyword">in</span> &map {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{}, {}"</span>, k, v);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 更新 hashmap</span></span><br><span class="line"> <span class="comment">// 每个 k 同时只能对应一个 v</span></span><br><span class="line"> <span class="comment">// 更新 hashmap 中的数据</span></span><br><span class="line"> <span class="comment">// 1. k 已经存在,对应一个 v</span></span><br><span class="line"> <span class="comment">// - 替换现有的 v</span></span><br><span class="line"> <span class="comment">// - 保留现有的 v,忽略新的 v</span></span><br><span class="line"> <span class="comment">// - 合并现有的 v 和新的 v</span></span><br><span class="line"> <span class="comment">// 2. k 不存在</span></span><br><span class="line"> <span class="comment">// - 添加一对 (k, v)</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">scores</span> = HashMap::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> scores.<span class="title function_ invoke__">insert</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdsd"</span>), <span class="number">10</span>);</span><br><span class="line"> scores.<span class="title function_ invoke__">insert</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdsd"</span>), <span class="number">12</span>); <span class="comment">// asdsd 的值已经改为 12,无论值是否存在,都在被设置为 12 </span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 对于 entry 而言</span></span><br><span class="line"> <span class="comment">// 如果 k 存在,则返回对应的 v 的一个可变引用</span></span><br><span class="line"> <span class="comment">// 如果 k 不存在,则将新的值插入进去,然后返回该值的可变引用</span></span><br><span class="line"> scores.<span class="title function_ invoke__">entry</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdsd"</span>)).<span class="title function_ invoke__">or_insert</span>(<span class="number">49</span>); <span class="comment">// 如果不存在则插入并返回新值的引用,如果存在则返回已有的值的引用</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">e</span> = scores.<span class="title function_ invoke__">entry</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdsd"</span>));</span><br><span class="line"> e.<span class="title function_ invoke__">or_insert</span>(<span class="number">666</span>);</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 基于现有的值 v 来更新</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">text</span> = <span class="string">"asdasd adfs asdsd asda"</span>;</span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">map</span> = HashMap::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> <span class="keyword">for</span> <span class="variable">word</span> <span class="keyword">in</span> text.<span class="title function_ invoke__">split_whitespace</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">count</span>: &<span class="keyword">mut</span> <span class="type">i32</span> = map.<span class="title function_ invoke__">entry</span>(word).<span class="title function_ invoke__">or_insert</span>(<span class="number">0</span>);</span><br><span class="line"> *count += <span class="number">1</span>; <span class="comment">// 注意 count 是一个可变引用</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>rust教程-07</title>
<link href="/2022/11/13/rust%E6%95%99%E7%A8%8B-07/"/>
<url>/2022/11/13/rust%E6%95%99%E7%A8%8B-07/</url>
<content type="html"><![CDATA[<p>rust 教程 07: 包</p><span id="more"></span><h2 id="package-和-crate"><a class="markdownIt-Anchor" href="#package-和-crate"></a> package 和 crate</h2><p>crate 的类型:</p><ul><li>binary</li><li>library</li></ul><p>crate root:</p><ul><li>源代码文件</li><li>rust 编译器从这里开始,组成 crate 的根 module</li></ul><p>package:</p><ul><li>包含 1 个 crate.toxl,他描述了如何构建这些 crates</li><li>只能包含 0-1 个 library crate</li><li>可以包含任意数量的 binary crate</li><li>但必须至少包含一个 crate(library 或者 binary)</li></ul><p>cargo 的惯例:</p><ul><li>src/main.rs:binary crate<ul><li>bianry crate 的 crate root</li><li>crate 名与 package 名相同</li></ul></li><li>src/lib.rs:library crate<ul><li>package 包含一个 library code</li><li>library crate 的 crate root</li><li>crate 名与 package 名相同</li></ul></li><li>crago 把 crate root 文件交给 rustc 来构建 library 或者 binary</li><li>一个 package 可以同时包含 src/main.rs 和 src/lib.rs</li><li>一个 package 可以有多个 binary crate</li></ul><h2 id="module"><a class="markdownIt-Anchor" href="#module"></a> Module</h2><p>Module:</p><ul><li>在一个 crate 内,将代码进行分组</li><li>增加可读性</li><li>控制项目的私有性:public、private</li></ul><p>建立 module:</p><ul><li>mod 关键字</li><li>可嵌套</li><li>可以包含其他项的定义</li></ul><h2 id="path-路径"><a class="markdownIt-Anchor" href="#path-路径"></a> path 路径</h2><p>为了在 rust 的模块中找到某个条目,需要使用路径,两种形式:</p><ul><li>绝对路径:从 crate root 开始,使用 crate 名或者字面值 crate</li><li>相对路径:从当前模块开始,使用 self、super 或者当前模块的标识符</li><li>路径至少由一个标识符组成,标识符之间使用 ::</li></ul><h2 id="私有性"><a class="markdownIt-Anchor" href="#私有性"></a> 私有性</h2><ul><li>模块不仅可以组织代码,还可以定义私有边界</li><li>如果想把函数或者 struct 等设为私有,可以将其放到某个模块中</li><li>rust 中所有的条目(函数、方法、struct、enum、模块、常量)等默认都是私有的</li><li>父级模块无法访问子模块中的私有条目</li><li>子模块可以使用所有祖先模块中的条目</li></ul><figure class="highlight rust"><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="keyword">mod</span> front_of_house {</span><br><span class="line"> <span class="comment">// 声明为公共的</span></span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">mod</span> hosting {</span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">add_to_waitlist</span>() {}</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">eat_at_restaurant</span>() {</span><br><span class="line"> <span class="comment">// 绝对路径</span></span><br><span class="line"> crate::front_of_house::hosting::<span class="title function_ invoke__">add_to_waitlist</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 相对路径</span></span><br><span class="line"> front_of_house::hosting::<span class="title function_ invoke__">add_to_waitlist</span>();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="super-关键字"><a class="markdownIt-Anchor" href="#super-关键字"></a> super 关键字</h2><p>访问父级模块或者方法</p><h2 id="pub-struct"><a class="markdownIt-Anchor" href="#pub-struct"></a> pub struct</h2><ul><li>struct 是公共的</li><li>struct 的字段默认是私有的</li><li>想把哪个字段设置为公有的,就在其前面设置为 pub</li></ul><h2 id="pub-enum"><a class="markdownIt-Anchor" href="#pub-enum"></a> pub enum:</h2><ul><li>enum 是公共的</li><li>所有元素也是公共的,不需要单独设置为 pub</li></ul><h2 id="use-关键字"><a class="markdownIt-Anchor" href="#use-关键字"></a> use 关键字</h2><ul><li>对于函数,引入到父级,即上一级即可;</li><li>对于 struct、enum,引入到同一级;</li><li>也就是对于同名条目,引入到父级即可</li><li>使用 use 导入到作用域内后,该名称在该作用域内是私有的<ul><li>使用 pub use 重导出,外部代码就可以引入到他们的作用域</li></ul></li></ul><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">mod</span> front_of_house {</span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">mod</span> hosting {</span><br><span class="line"> <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">add_to_waitlist</span>() {}</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用绝对路径引入 hosting</span></span><br><span class="line"><span class="comment">// 使用 as 搞个别名</span></span><br><span class="line"><span class="keyword">use</span> crate::front_of_house::hosting <span class="keyword">as</span> hosting1;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 使用相对路径引入 hosting</span></span><br><span class="line"><span class="comment">// 针对函数,一般是引入到上一级,避免引入多个相同名字的函数</span></span><br><span class="line"><span class="keyword">use</span> front_of_house::hosting <span class="keyword">as</span> hosting2;</span><br><span class="line"></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">eat_at_restaurant</span>() {</span><br><span class="line"> <span class="comment">// 绝对路径</span></span><br><span class="line"> crate::front_of_house::hosting::<span class="title function_ invoke__">add_to_waitlist</span>();</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 相对路径</span></span><br><span class="line"> front_of_house::hosting::<span class="title function_ invoke__">add_to_waitlist</span>();</span><br><span class="line"></span><br><span class="line"> hosting::<span class="title function_ invoke__">add_to_waitlist</span>();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="使用外部包-package"><a class="markdownIt-Anchor" href="#使用外部包-package"></a> 使用外部包 package</h2><ul><li>cargo.toml 添加依赖的包 package</li><li>use 将特定条目引入到作用域</li><li>std 包不需要放入到 c</li></ul><p>cargo.toml 中</p><p>使用嵌套路径来引入相同 package 下的多个条目</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> std:: {</span><br><span class="line"> cmd::Ordering,</span><br><span class="line"> io</span><br><span class="line">};</span><br><span class="line"><span class="keyword">use</span> std::io{</span><br><span class="line"> <span class="keyword">self</span>, <span class="comment">// 引入自己</span></span><br><span class="line"> write</span><br><span class="line">};</span><br></pre></td></tr></table></figure><h2 id="将模块内容移动到其他文件"><a class="markdownIt-Anchor" href="#将模块内容移动到其他文件"></a> 将模块内容移动到其他文件</h2><p>模块定义时,如果模块后边是 “;”,而不是代码块:</p><ul><li>rust 会从与模块同名的文件中加载内容</li><li>模块树的结构不会变化</li></ul><figure class="highlight bash"><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">src/</span><br><span class="line">├── front_of_house</span><br><span class="line">│ └── hosting.rs</span><br><span class="line">├── front_of_house.rs</span><br><span class="line">├── lib.rs</span><br><span class="line">└── main.rs</span><br></pre></td></tr></table></figure><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// src/front_of_house.rs</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">mod</span> hosting; <span class="comment">// 依旧要声明为 pub,公有类型</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// src/front_of_house/hosting.rs</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">add_to_waitlist</span>() {}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>rust教程-06</title>
<link href="/2022/11/01/rust%E6%95%99%E7%A8%8B-06/"/>
<url>/2022/11/01/rust%E6%95%99%E7%A8%8B-06/</url>
<content type="html"><![CDATA[<p>rust 教程 06: 枚举</p><span id="more"></span><h2 id="枚举"><a class="markdownIt-Anchor" href="#枚举"></a> 枚举</h2><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Message</span> {</span><br><span class="line"> Quit, <span class="comment">// 可以不指定类型</span></span><br><span class="line"> Move { x: <span class="type">i32</span>, y: <span class="type">i32</span>}, <span class="comment">// 可以是一个结构体</span></span><br><span class="line"> <span class="title function_ invoke__">Write</span> (<span class="type">String</span>), <span class="comment">// 可以是一个 String</span></span><br><span class="line"> <span class="title function_ invoke__">ChangeColor</span> (<span class="type">i32</span>, <span class="type">i32</span>, <span class="type">i32</span>), <span class="comment">// 可以是一个 tuple</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">Message</span> { <span class="comment">// 为枚举类型添加方法</span></span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">call</span>(&<span class="keyword">self</span>) {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{:#?}"</span>, <span class="keyword">self</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">q</span> = Message::Quit;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">m</span> = Message::Move { x: <span class="number">19</span>, y: <span class="number">29</span> };</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">w</span> = Message::<span class="title function_ invoke__">Write</span>(<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"asdasd"</span>));</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">c</span> = Message::<span class="title function_ invoke__">ChangeColor</span>(<span class="number">12</span>, <span class="number">12</span>, <span class="number">12</span>);</span><br><span class="line"> q.<span class="title function_ invoke__">call</span>();</span><br><span class="line"> m.<span class="title function_ invoke__">call</span>();</span><br><span class="line"> w.<span class="title function_ invoke__">call</span>();</span><br><span class="line"> c.<span class="title function_ invoke__">call</span>();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="option-类型"><a class="markdownIt-Anchor" href="#option-类型"></a> Option 类型</h2><p>rust 中没有 null</p><p>在其他语言中,一个变量可以处于两种状态:空值(null)、非空</p><p>但是当你尝试使用非 null 值那样使用 null 值的时候,就会引起某种错误</p><p>rust 中类似 null 的枚举:Option<T>,定义为:</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">enum</span> <span class="title class_">Option</span><T> {</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(T),</span><br><span class="line"> <span class="literal">None</span>,</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>基本的使用方法:</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">some_num</span> = <span class="title function_ invoke__">Some</span>(<span class="number">5</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">some_str</span> = <span class="title function_ invoke__">Some</span>(<span class="string">"asdasd"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">some_none</span>:<span class="type">Option</span><<span class="type">i32</span>> = <span class="literal">None</span>; <span class="comment">// 必须显示的指定类型</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在 rust 中,Option<T> 和 T 是不同的类型,不可以直接相操作</p><h2 id="match"><a class="markdownIt-Anchor" href="#match"></a> match</h2><p>模式匹配,类似于 switch</p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">UsState</span> {</span><br><span class="line"> Washington,</span><br><span class="line"> NewYork,</span><br><span class="line">}</span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Coin</span> {</span><br><span class="line"> Penny,</span><br><span class="line"> Nickel,</span><br><span class="line"> Dime,</span><br><span class="line"> <span class="title function_ invoke__">Quarter</span>(UsState),</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">match_coin</span>(coin: &Coin) <span class="punctuation">-></span> <span class="type">i8</span>{</span><br><span class="line"> <span class="keyword">match</span> coin { <span class="comment">// 必须列出所有可能的值,如果不想列出,必须用 _ 代替</span></span><br><span class="line"> Coin::Penny => { <span class="comment">// 使用 => </span></span><br><span class="line"> <span class="number">10</span></span><br><span class="line"> },</span><br><span class="line"> Coin::Nickel => {</span><br><span class="line"> <span class="number">20</span></span><br><span class="line"> },</span><br><span class="line"> Coin::Dime => <span class="number">5</span>, <span class="comment">// 也可以不跟 {}</span></span><br><span class="line"> Coin::<span class="title function_ invoke__">Quarter</span>(state) => { <span class="comment">// 匹配某种类型的枚举值</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{:#?}"</span>, state);</span><br><span class="line"> <span class="number">100</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="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">coin</span> = Coin::Penny;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">coin2</span> = Coin::<span class="title function_ invoke__">Quarter</span>(UsState::NewYork);</span><br><span class="line"> <span class="title function_ invoke__">match_coin</span>(&coin);</span><br><span class="line"> <span class="title function_ invoke__">match_coin</span>(&coin2);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>用于 Option<T> 的匹配时</p><figure class="highlight rust"><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">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">five</span> = <span class="title function_ invoke__">Some</span>(<span class="number">5</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">six</span> = <span class="literal">None</span>;</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{:#?}"</span>, <span class="title function_ invoke__">inc</span>(five));</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{:#?}"</span>, <span class="title function_ invoke__">inc</span>(six));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">inc</span>(value: <span class="type">Option</span><<span class="type">i32</span>>) <span class="punctuation">-></span> <span class="type">Option</span><<span class="type">i32</span>> {</span><br><span class="line"> <span class="keyword">match</span> value {</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(i)=> {</span><br><span class="line"> <span class="title function_ invoke__">Some</span>(i+<span class="number">1</span>)</span><br><span class="line"> },</span><br><span class="line"> <span class="literal">None</span> => { <span class="comment">// 必须要穷举所有的可能性</span></span><br><span class="line"> <span class="literal">None</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="if-let"><a class="markdownIt-Anchor" href="#if-let"></a> if let</h2><p><code>if let</code> 用于匹配一种情况</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">three</span> = <span class="title function_ invoke__">Some</span>(<span class="number">3</span>);</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">let</span> <span class="variable">Some</span>(<span class="number">3</span>) = three { <span class="comment">// 注意这里用的是一个等号</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{}"</span>, <span class="number">3</span>);</span><br><span class="line"> } <span class="keyword">else</span> { <span class="comment">// 也可以使用 else 来指定其他情况的处理逻辑</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"others"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>screen 基本用法</title>
<link href="/2022/10/30/screen-%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95/"/>
<url>/2022/10/30/screen-%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95/</url>
<content type="html"><![CDATA[<p>screen 的基本用法</p><span id="more"></span><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">yum install screen</span><br><span class="line"></span><br><span class="line">screen -S name python test.py <span class="comment"># screen -S <name> <cmd></span></span><br><span class="line"></span><br><span class="line">Ctrl a+d <span class="comment"># 从 screen 中退出,但是不中断 screen</span></span><br><span class="line"></span><br><span class="line">screen -r name <span class="comment"># 回到名称为 name 的 screen</span></span><br><span class="line"></span><br><span class="line">screen -d name <span class="comment"># 将名称为 name 的 screen 离线</span></span><br><span class="line"></span><br><span class="line">screen -<span class="built_in">ls</span> <span class="comment"># 查看所有的 screen </span></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> linux </category>
</categories>
<tags>
<tag> linux </tag>
<tag> screen </tag>
</tags>
</entry>
<entry>
<title>rust教程-05</title>
<link href="/2022/10/25/rust%E6%95%99%E7%A8%8B-05/"/>
<url>/2022/10/25/rust%E6%95%99%E7%A8%8B-05/</url>
<content type="html"><![CDATA[<p>rust 教程 05: struct</p><span id="more"></span><h2 id="struct-基础内容"><a class="markdownIt-Anchor" href="#struct-基础内容"></a> struct 基础内容</h2><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">User</span> {</span><br><span class="line"> username: <span class="type">String</span>,</span><br><span class="line"> email: <span class="type">String</span>,</span><br><span class="line"> active: <span class="type">bool</span>, <span class="comment">// 最后一个字段也要有逗号</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">build_user</span>(username: <span class="type">String</span>, email: <span class="type">String</span>, active: <span class="type">bool</span>) <span class="punctuation">-></span> User { <span class="comment">// 函数返回结构体</span></span><br><span class="line"> User {</span><br><span class="line"> username, <span class="comment">// 可以使用简写的方式初始化,只要变量名和字段名相同即可</span></span><br><span class="line"> email,</span><br><span class="line"> active</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="comment">// 声明了可变的user,此时 user 的所有变量都是可变的</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">user</span> = User {</span><br><span class="line"> active: <span class="literal">true</span>,</span><br><span class="line"> email: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"[email protected]"</span>),</span><br><span class="line"> username: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"kimroniny"</span>) <span class="comment">// 可以调整赋值顺序,但是不可以不给某个字段赋值</span></span><br><span class="line"> };</span><br><span class="line"> user.active = <span class="literal">false</span>; <span class="comment">// 修改字段的值;</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">user2</span> = User {</span><br><span class="line"> email: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"[email protected]"</span>),</span><br><span class="line"> ..user</span><br><span class="line"> }; <span class="comment">// 使用已有的 user 为新的 user2 赋值</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"Hello, world!"</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="tuple-struct"><a class="markdownIt-Anchor" href="#tuple-struct"></a> tuple struct</h2><p>类似于 tuple 的 struct,整体有个名字,但是字段没有名字,只有类型</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">struct</span> <span class="title class_">Color</span>(<span class="type">i32</span>,<span class="type">i32</span>,<span class="type">i32</span>);</span><br><span class="line"> <span class="keyword">struct</span> <span class="title class_">Point</span>(<span class="type">i32</span>,<span class="type">i32</span>,<span class="type">i32</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">color</span> = <span class="title function_ invoke__">Color</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>); <span class="comment">// 初始化方式和 struct 不一样,用 ()</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">origin</span> = <span class="title function_ invoke__">Point</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="struct-的一个例子"><a class="markdownIt-Anchor" href="#struct-的一个例子"></a> struct 的一个例子</h2><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Rectangle</span> {</span><br><span class="line"> width: <span class="type">u32</span>,</span><br><span class="line"> length: <span class="type">u32</span>,</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">rect</span> = Rectangle {</span><br><span class="line"> width: <span class="number">1</span>,</span><br><span class="line"> length: <span class="number">2</span>,</span><br><span class="line"> };</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"area: {}"</span>, <span class="title function_ invoke__">area</span>(&rect));</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{:?}"</span>, rect); </span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> Rectangle { width: 1, length: 2 }</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{:#?}"</span>, rect);</span><br><span class="line"> <span class="comment">/* </span></span><br><span class="line"><span class="comment"> Rectangle {</span></span><br><span class="line"><span class="comment"> width: 1,</span></span><br><span class="line"><span class="comment"> length: 2,</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><br><span class="line"><span class="keyword">fn</span> <span class="title function_">area</span>(rect: &Rectangle) <span class="punctuation">-></span> <span class="type">u32</span> {</span><br><span class="line"> rect.width * rect.length</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="struct-的方法"><a class="markdownIt-Anchor" href="#struct-的方法"></a> struct 的方法</h2><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Rectangle</span> {</span><br><span class="line"> width: <span class="type">u32</span>,</span><br><span class="line"> length: <span class="type">u32</span>,</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">Rectangle</span> { <span class="comment">// 使用 impl 实现 struct 的方法</span></span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">area</span>(&<span class="keyword">self</span>) <span class="punctuation">-></span> <span class="type">u32</span> { </span><br><span class="line"> <span class="keyword">self</span>.width * <span class="keyword">self</span>.length</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 关联函数,第一个参数不是 self</span></span><br><span class="line"> <span class="comment">// 多用于实例化</span></span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">square</span>(size: <span class="type">u32</span>) <span class="punctuation">-></span> Rectangle {</span><br><span class="line"> Rectangle { width: size, length: size }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span> <span class="title class_">Rectangle</span> {</span><br><span class="line"> <span class="comment">// 可以放置多个 impl 块</span></span><br><span class="line"> <span class="comment">// 相当于综合在一起</span></span><br><span class="line"> <span class="keyword">fn</span> <span class="title function_">area2</span>(&<span class="keyword">self</span>) <span class="punctuation">-></span> <span class="type">u32</span> { </span><br><span class="line"> <span class="keyword">self</span>.width * <span class="keyword">self</span>.length</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">rect</span> = Rectangle {</span><br><span class="line"> width: <span class="number">1</span>,</span><br><span class="line"> length: <span class="number">2</span>,</span><br><span class="line"> };</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"area: {}"</span>, rect.<span class="title function_ invoke__">area</span>()); <span class="comment">// 直接调用</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">rect2</span> = Rectangle::<span class="title function_ invoke__">square</span>(<span class="number">10</span>); <span class="comment">// 使用双冒号来调用关联函数</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考</h2><ol><li><a href="https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s">https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s</a></li><li>《rust权威指南(The Rust Programming Language)》</li></ol>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>rust教程-04</title>
<link href="/2022/10/24/rust%E6%95%99%E7%A8%8B-04/"/>
<url>/2022/10/24/rust%E6%95%99%E7%A8%8B-04/</url>
<content type="html"><![CDATA[<p>rust 教程 04: 所有权</p><span id="more"></span><h2 id="什么是所有权"><a class="markdownIt-Anchor" href="#什么是所有权"></a> 什么是所有权?</h2><p>rust 的核心特性就是<strong>所有权</strong></p><p>所有程序在运行时都必须管理它们使用计算机内存的方式</p><ul><li>垃圾收集机制,即程序运行时,会不断地寻找不再使用的内存</li><li>程序员必须显示地分配和释放内存</li></ul><p>rust 则采用<strong>所有权系统</strong>来管理内存,包含一组编译器在编译时检查的规则,因为是编译时检查,所以所有权特性不会影响运行时速度</p><h2 id="stack-vs-heap"><a class="markdownIt-Anchor" href="#stack-vs-heap"></a> stack VS heap</h2><p>rust 这样的系统级编程语言,受到 stack 和 heap 的影响非常大</p><p>stack 和 heap 都是代码运行时可用的内存,但是结构不同</p><h3 id="存储数据"><a class="markdownIt-Anchor" href="#存储数据"></a> 存储数据</h3><p>stack 执行 LIFO 原则,即先进后出</p><p>所有存储在 stack 上的数据必须拥有已知的固定的大小</p><p>而编译时大小未知的数据或运行时大小可能发生变化的数据必须存放在 heap 上</p><p>heap 的内存组织性较差</p><ul><li>当把数据放入 heap 时,会请求一定数量的空间</li><li>操作系统在 heap 里找到一块足够大的空间,并标记为在用,返回一个指针,即该空间的地址</li><li>该过程称作在 heap 上进行分配</li></ul><p>把值压在 stack 上不叫分配,但是可以把指针存放在 stack 上</p><p>把数据压到 stack 上要比在 heap 上分配快得多,因为操作系统不需要寻找用来存储新数据的空间,只要往 stack 的顶端压入数据即可</p><p>在 heap 上分配空间需要做更多的工作,需要找到足够大的空间,并且要做好记录</p><h3 id="访问数据"><a class="markdownIt-Anchor" href="#访问数据"></a> 访问数据</h3><p>访问 heap 上的数据要比访问 stack 上的数据慢,因为需要通过指针才能找到 heap 中的数据。</p><p>对于现代处理器而言,由于缓存的缘故,如果指令在内存中跳转的次数越少,那么速度就越快</p><p>如果数据存放的距离比较近,则处理器处理速度更快(stack),反之更慢</p><p>在 heap 上分配大量空间也会消耗事件</p><h3 id="函数调用"><a class="markdownIt-Anchor" href="#函数调用"></a> 函数调用</h3><p>当代码调用函数时,值被传入到函数(也包括指向 heap 的指针),函数本地的变量被压到 stack 上,函数结束时,这些值也会从 stack 上弹出</p><h2 id="所有权存在的原因"><a class="markdownIt-Anchor" href="#所有权存在的原因"></a> 所有权存在的原因</h2><p>所有权要解决的问题:</p><ul><li>跟踪代码的哪些部分正在使用 heap 的哪些数据</li><li>最小化 heap 上的重复数据量</li><li>清理 heap 上未使用的数据以避免空间不足</li></ul><p>管理 heap 数据是所有权存在的原因</p><h2 id="所有权规则"><a class="markdownIt-Anchor" href="#所有权规则"></a> 所有权规则</h2><p>每个值都有一个变量,这个变量是该值的所有者</p><p>每个值同时只能有一个所有者</p><p>当所有者超出作用域(scope)时,该值将被删除</p><h3 id="以-string-类型解释所有权规则"><a class="markdownIt-Anchor" href="#以-string-类型解释所有权规则"></a> 以 String 类型解释所有权规则</h3><p>String 类型的字符串内容是可变的,而字符串字面值是不可变的。因为 String 是在 heap 上分配内存,而字符串字面值是在 stack 上压入字符串</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="comment">// 声明 string 类型的变量</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello"</span>);</span><br><span class="line"> s.<span class="title function_ invoke__">push_str</span>(<span class="string">" world!"</span>);</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"{}"</span>, s);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>当用完 String 之后,需要使用某种方式将内存返还给操作系统</p><ul><li>在拥有 GC 的语言中,GC 会跟踪并清理不再使用的内存</li><li>没有 GC,就需要识别何时不再使用内存;</li><li><ul><li>如果忘了,就浪费内存</li></ul></li><li><ul><li>如果提前做了,变量就会非法</li></ul></li><li><ul><li>如果做了两次,也是 bug,一次分配对应一次释放,要求每次分配对应一次释放</li></ul></li></ul><p>当超出作用域时,系统会执行 <code>drop()</code> 函数,将变量 s 所指向的内存释放</p><h3 id="变量和数据交互的方式移动move"><a class="markdownIt-Anchor" href="#变量和数据交互的方式移动move"></a> 变量和数据交互的方式:移动(Move)</h3><p>在下面的这种情况下,x 和 y 所代表的两个 6 都被压入 stack 中</p><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> <span class="variable">x</span> = <span class="number">6</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">y</span> = x;</span><br></pre></td></tr></table></figure><p>而在下面的这种情况中,针对 String 类型的变量,执行 <code>s2 = s</code> 之后,s 便将字符串的所有权交给了 s2,而 s 不再拥有值</p><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> <span class="keyword">mut </span><span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello world!"</span>);</span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s2</span> = s;</span><br></pre></td></tr></table></figure><p>一个 String 由 3 部分组成:一个指向存放字符串内容的内存指针,一个长度,一个容量。这些内容存放在 stack 上,而字符串则存放在 heap 上</p><p>当执行 <code>s2 = s</code>,在 stack 会赋值一份 String 的数据(指针、长度、容量),但是并不会赋值指针所指向的 heap 上的数据,也就是两个指针指向同一个 heap 内存中的位置</p><p>当变量离开作用域时,rust 会自动调用 <code>drop()</code> 函数,将变量使用的 heap 自动释放,当 s 和 s2 都离开作用域时,rust 会释放两者的内存,也就是释放相同的内存,从而造成“二次释放 bug”</p><p>为了保证内存安全:</p><ul><li>rust 没有复制被分配的内存</li><li>在执行 <code>s = s2</code> 之后,rust 是让 s 失效,所以当 s 离开作用域时,rust 不会释放任何东西</li></ul><p>rust 不会自动创建数据的深拷贝</p><p>如果想要深度拷贝 heap 上面的 String 数据,而不仅仅是拷贝 stack 上的数据,可以使用 clone 方法,这种方法比较消耗资源</p><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> <span class="keyword">mut </span><span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello world!"</span>);</span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s2</span> = s.<span class="title function_ invoke__">clone</span>();</span><br></pre></td></tr></table></figure><p>在 stack 上的数据复制叫 copy,比如整数类型的移动,就是在 stack 上进行复制。如果一个类型实现了 copy 这个特性(trait),那么旧的变量在赋值后仍然可用;但是,如果一个类型或者该类型的一部分实现了 drop 这个特性(trait),那么 rust 不允许让它再去实现 copy 了</p><p>一些拥有 copy trait 的类型:</p><ul><li>任何简单标量的组合类型都可以是 copy 的,如:u32, bool, char, f64, tuple(标量1,标量2…)</li><li>任何需要分配内存或者资源的都不是 copy 得到</li></ul><h2 id="所有权与函数"><a class="markdownIt-Anchor" href="#所有权与函数"></a> 所有权与函数</h2><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s1</span> = <span class="title function_ invoke__">get_ownership</span>(); <span class="comment">// 获得 “some” 的所有权</span></span><br><span class="line"> <span class="title function_ invoke__">take_ownership</span>(s1); <span class="comment">// 所有权交给了 s,s1则失效</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s2</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello_world"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s3</span> = <span class="title function_ invoke__">take_and_give_back</span>(s2); <span class="comment">// s2 转移到了 s3 身上</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">take_ownership</span>(s:Srting) {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"s:{}"</span>, s);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">get_ownership</span>() <span class="punctuation">-></span> <span class="type">String</span> {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">some</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"some"</span>);</span><br><span class="line"> some;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">take_and_give_back</span>(a_string: <span class="type">String</span>) <span class="punctuation">-></span> <span class="type">String</span> {</span><br><span class="line"> a_string; <span class="comment">// 返回值也会发生所有权的转移</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>一个变量的所有权总是遵循同样的模式:</p><ul><li>把一个值赋给其他变量时就会发生移动</li><li>当一个包含 heap 数据的变量离开作用域时,它的值就会被 drop 函数清理掉,除非数据的所有权移动到另一个变量上了</li></ul><h2 id="引用与借用"><a class="markdownIt-Anchor" href="#引用与借用"></a> 引用与借用</h2><p>引用本质上是一个指针,指向这个变量在 stack 中的位置</p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">len</span> = <span class="title function_ invoke__">calc_length</span>(&s); <span class="comment">// 引用到 s,但是并不用 s</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"the length of s({}) is {}"</span>, s, len);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 把引用作为函数参数这个行为叫做 “借用”</span></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">calc_length</span>(s: &<span class="type">String</span>) <span class="punctuation">-></span> <span class="type">usize</span> {</span><br><span class="line"> s.<span class="title function_ invoke__">len</span>()</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="可变引用-不可变引用"><a class="markdownIt-Anchor" href="#可变引用-不可变引用"></a> 可变引用、不可变引用</h3><p>不可以修改借用的东西,默认也是不可变的</p><p>如果需要可变,需要加上 <code>mut</code></p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">len</span> = <span class="title function_ invoke__">calc_length</span>(&<span class="keyword">mut</span> s); <span class="comment">// 引用到 s,但是并不用 s</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"the length of s({}) is {}"</span>, s, len);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 把引用作为函数参数这个行为叫做 “借用”</span></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">calc_length</span>(s: &<span class="keyword">mut</span> <span class="type">String</span>) <span class="punctuation">-></span> <span class="type">usize</span> {</span><br><span class="line"> s.<span class="title function_ invoke__">len</span>()</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>可变引用</strong>有一个重要的限制:在特定作用域内,对某一块数据,<strong>只能有一个可变的引用</strong>。好处是在编译时可以防止数据竞争</p><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> <span class="variable">s1</span> = &<span class="keyword">mut</span> s;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">s2</span> = &<span class="keyword">mut</span> s; <span class="comment">// 会报错</span></span><br></pre></td></tr></table></figure><p>数据竞争的几种行为:</p><ul><li>两个或多个指针同时访问同一个数据;</li><li>至少有一个指针用于写入数据;</li><li>没有使用任何机制来同步对数据的访问;</li></ul><p>可以通过<strong>创建新的作用域</strong>,来允许非同时的创建多个可变引用</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s1</span> = &<span class="keyword">mut</span> s;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">let</span> <span class="variable">s2</span> = &<span class="keyword">mut</span> s; <span class="comment">// 不会报错</span></span><br></pre></td></tr></table></figure><p>另外一个限制:<strong>不可以同时拥有一个可变引用和一个不可变引用</strong>。因为可变应用修改了引用内容之后,不可变引用就失效了。但是多个不可变引用是可以同时存在的</p><h3 id="悬空引用"><a class="markdownIt-Anchor" href="#悬空引用"></a> 悬空引用</h3><p>Dangling References</p><p>即一个指针引用了内存中的某个地址,而这块内存可能已经释放并分配给其他人使用了</p><p>在 rust 里,编译器可以检查代码从而保证引用永远都不是悬空引用</p><h3 id="引用的规则"><a class="markdownIt-Anchor" href="#引用的规则"></a> 引用的规则</h3><p>在任何给定的时刻,只能满足下列条件之一:</p><ol><li>一个可变的引用</li><li>人以数量不可变的引用</li></ol><p>引用必须一直有效</p><h2 id="切片slice"><a class="markdownIt-Anchor" href="#切片slice"></a> 切片(slice)</h2><p>rust 中的另外一种不持有所有权的数据类型</p><p>指向字符串中一部分内容的引用</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello world"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">hello</span> = &s[<span class="number">0</span>..<span class="number">5</span>]; <span class="comment">// 不包括右边界</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">hello2</span> = &s[..<span class="number">5</span>]; <span class="comment">// 不包括右边界</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">world</span> = &s[<span class="number">5</span>..<span class="number">11</span>];</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">world2</span> = &s[<span class="number">5</span>..];</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">whole</span> = &s[..];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><img data-src="slice.png" alt="切片内存" /></p><p>字符串切片的类型 <code>&str</code>,函数返回值就用这个</p><p>字符串字面值的就是个切片</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">s</span>:&<span class="type">str</span> = <span class="string">"hello world"</span>;</span><br></pre></td></tr></table></figure><p>将字符串切片作为参数传递,从而兼容字符串字面值和 String 类型的参数</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">first_world</span>(s: &<span class="type">String</span>) <span class="punctuation">-></span>&<span class="type">str</span> {}</span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">first_world</span>(s: &<span class="type">str</span>) <span class="punctuation">-></span>&<span class="type">str</span> {}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="variable">s1</span> = <span class="type">String</span>:<span class="title function_ invoke__">from</span>(<span class="string">"sss"</span>);</span><br><span class="line"><span class="title function_ invoke__">first_world</span>(&s[..]);</span><br></pre></td></tr></table></figure><p>定义函数时使用字符串切片来代替字符串引用会使我们的 API 更加通用,且不会损失任何功能</p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s</span> = <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">"hello world"</span>);</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">s2</span> = <span class="string">"hello world"</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"the first word of s is: {}"</span>, <span class="title function_ invoke__">first_word</span>(&s[..]));</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"the first word of s2 is: {}"</span>, <span class="title function_ invoke__">first_word</span>(s2));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">first_word</span>(s: &<span class="type">str</span>) <span class="punctuation">-></span> &<span class="type">str</span> {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">bytes</span> = s.<span class="title function_ invoke__">as_bytes</span>();</span><br><span class="line"> <span class="title function_ invoke__">for</span> (idx, &item) <span class="keyword">in</span> bytes.<span class="title function_ invoke__">iter</span>().<span class="title function_ invoke__">enumerate</span>() {</span><br><span class="line"> <span class="keyword">if</span> item == <span class="string">b' '</span> {</span><br><span class="line"> <span class="keyword">return</span> &s[..idx];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> &s[..]</span><br><span class="line">}</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>其他类型的切片</p><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> <span class="variable">a</span> = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"><span class="keyword">let</span> <span class="variable">b</span>:&[<span class="type">i32</span>] = &a[<span class="number">1</span>..<span class="number">3</span>]; <span class="comment">// b 的类型是 &[i32]</span></span><br></pre></td></tr></table></figure><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考</h2><ol><li><a href="https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s">https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s</a></li><li>《rust权威指南(The Rust Programming Language)》</li></ol>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>serverless基础</title>
<link href="/2022/10/21/serverless%E5%9F%BA%E7%A1%80/"/>
<url>/2022/10/21/serverless%E5%9F%BA%E7%A1%80/</url>
<content type="html"><![CDATA[<p>serverless 的基础内容</p><span id="more"></span><h2 id="概念"><a class="markdownIt-Anchor" href="#概念"></a> 概念</h2><p>Serverless computing 无服务器运算,又称为函数即服务(Function as a service,即 FaaS)</p><p>我们不再需要关心服务(如 mysql、redis等)的申请机器、资源部署、资源碎片、弹性扩缩容问题,不再需要日夜值守关心各个依赖组件各项指标出现的问题,我们只需要聚焦在自己的上层业务逻辑上进行实现和优化,并且再也不会有闲置资源或者碎片资源问题 (按需使用),这个就是 Serverless 想要构建的架构体系。</p><h2 id="架构演进"><a class="markdownIt-Anchor" href="#架构演进"></a> 架构演进</h2><p>从整个演进过程来看,一直都在朝着资源切分粒度越来越细(<strong>物理机 -> 操作系统 -> 进程 -> function</strong>),资源利用率越来越高,运维工作越来越少,开发更聚焦业务方向。</p><p>物理机时代</p><p>虚拟化时代(重量级 VM),将物理机切分成一个个 VM 实例</p><p>云时代,云服务提供商,还是采用重量级 VM</p><p>虚拟化时代(轻量级容器 docker),devOps 开始火热,强制运维转开发,但是开发还是要关心运维</p><p>Serverless,去运维,开发人员只关注业务逻辑开发</p><h2 id="如何影响微服务"><a class="markdownIt-Anchor" href="#如何影响微服务"></a> 如何影响微服务</h2><p>serverless 是技术架构,微服务是业务架构,经济基础决定上层建筑,底层技术架构形式影响上层业务</p><p>以前的微服务以应用形式来组织,很多服务可能用到相同的功能,但是这些功能并没有达到可以分解为一个微服务的程度,此时,各个服务都会开发这一功能,从而导致代码重复。虽然可以使用共享库来解决,但是多语言环境下不一定行得通</p><p>而 serverless 架构中以 function 为最小粒度组织,业务分隔粒度可以无限小,任何一个模块功能甚至方法都可以独立存在,不需要通过共享库或者共享组件来复用。所以,在 Serverless 架构中,微服务组件的相互隔离和模块松耦合可以做的更好,应用甚至可以以独立函数的形式存在</p><h2 id="和云原生的关系"><a class="markdownIt-Anchor" href="#和云原生的关系"></a> 和云原生的关系</h2><p>serverless 就是为云而生的东西,天生具有云的基因(免运维弹性伸缩按量计费)</p><p>只需要聚焦业务逻辑不需要去关心和管理资源问题,是对容器技术的封装,代表了云原生的高级阶段</p><h2 id="serverless-要解决的问题"><a class="markdownIt-Anchor" href="#serverless-要解决的问题"></a> serverless 要解决的问题</h2><ol><li>机器资源分布不均</li></ol><p>一个大型系统包括多种业务,通过拆分集群来进行业务隔离,不同集群由于不同的特性,会出现差距较大的资源利用率</p><ol start="2"><li>错峰问题</li></ol><p>如果就为了一天 1 个小时的高峰流量来准备全天的机器,那剩下来的那 23 小时也是一种资源的浪费</p><ol start="3"><li>碎片化问题</li></ol><p>微服务之间的数据交互主要是 RPC 和 MQ,常见的 RPC 框架本身就有比较完善的探活和负载均衡机制能够保证流量在不同机器的的均衡性,而 MQ 受限于顺序消费、失败重发、消息分区等特性没有办法很好的保证消费端负载均衡,比如我们常用的 RocketMQ 默认使用了一种分页的算法,即在客户端将消费者和分区分别按照字典序排好,再按照平均分配的原则每个消费者分 “一页” 的分区,所以这里就会引申出碎片的问题,当一个集群中消费的 Metaq 消息都是小分区的消息,所有的消息都会被流入集群中的前几个机器中,造成集群整体流量不均,带来集群资源碎片。</p><ol start="4"><li>资源问题</li></ol><p>对于新接入的用户和业务,我们常见的做法是评估峰值业务量然后为其开启新集群预先分配一批机器,这里就有两个问题,一个是对于资源的预先评估是否能够准确而不造成浪费,另一个是成本结算方式,如果使用机器数来给用户或者业务方结算成本,对于有明显波峰波谷的使用者来说也是一种很大的成本资源浪费。</p><ol start="5"><li>运维问题</li></ol><p>在每次大促或者压测之前都需要提前扩缩容准备资源、修改集群配置,随着各种大促小促和压测次数越来越密集,这种运维开销成本也变得越来越大。</p><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考</h2><ol><li><a href="https://my.oschina.net/u/5783135/blog/5584238">Serverless 架构演进与实践</a></li></ol>]]></content>
<categories>
<category> serverless </category>
</categories>
<tags>
<tag> serverless </tag>
</tags>
</entry>
<entry>
<title>rust教程-03</title>
<link href="/2022/10/20/rust%E6%95%99%E7%A8%8B-03/"/>
<url>/2022/10/20/rust%E6%95%99%E7%A8%8B-03/</url>
<content type="html"><![CDATA[<p>rust 教程 03: 基本内容</p><span id="more"></span><h2 id="变量-常量-隐藏"><a class="markdownIt-Anchor" href="#变量-常量-隐藏"></a> 变量、常量、隐藏</h2><h3 id="变量"><a class="markdownIt-Anchor" href="#变量"></a> 变量</h3><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> <span class="variable">x</span> = <span class="number">5</span>; <span class="comment">// 不可变变量</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">mul</span> x = <span class="number">3</span>; <span class="comment">// 可变变量,通过 mut 修饰符</span></span><br></pre></td></tr></table></figure><h3 id="常量"><a class="markdownIt-Anchor" href="#常量"></a> 常量</h3><p>常量 constant,绑定值以后也是不可变的,但是与不可变变量有很多区别</p><ol><li>不可以使用 mut 修饰符,常量永远不可变</li><li>声明常量使用 const,且必须标注类型</li><li>可以在任何作用域内声明,包括全局作用域</li><li>只可以绑定到常量表达式,无法绑定到函数的调用结果或者运行时才能计算出的值<br />命名规范:使用全大写字母,用下划线分开单词</li></ol><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> MAX_POINTS: <span class="type">u32</span> = <span class="number">100</span>;</span><br></pre></td></tr></table></figure><h3 id="隐藏"><a class="markdownIt-Anchor" href="#隐藏"></a> 隐藏</h3><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">y</span> = <span class="number">1</span>;</span><br><span class="line"><span class="comment">// y = y + 1; // error: 不可变变量</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">y</span> = y + <span class="number">1</span>; <span class="comment">// ok: 隐藏了上一个 y</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">y</span> = <span class="string">"hello"</span>; <span class="comment">// ok: 可以改变 y 的类型</span></span><br></pre></td></tr></table></figure><h2 id="强类型语言"><a class="markdownIt-Anchor" href="#强类型语言"></a> 强类型语言</h2><p>rust 是静态编译语言,在编译时必须直到所有变量的类型,即:</p><ul><li>基于使用的值,编译器可以推断出它的具体类型</li><li>如果类型比较多,必须添加类型标注,否则编译报错</li></ul><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="comment">// 变量 x 必须指明类型 u32,因为 parse() 的结果产生的类型可能有很多,比如 i32,i64,u64 等等</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">x</span>: <span class="type">u32</span> = <span class="string">"43"</span>.<span class="title function_ invoke__">parse</span>().<span class="title function_ invoke__">expect</span>(<span class="string">"pls input a number"</span>); </span><br></pre></td></tr></table></figure><h2 id="标量类型"><a class="markdownIt-Anchor" href="#标量类型"></a> 标量类型</h2><p>一个标量类型代表一个单个的值</p><p>四个标量类型:整数、浮点、布尔、字符</p><h3 id="整数类型"><a class="markdownIt-Anchor" href="#整数类型"></a> 整数类型</h3><ul><li>十进制:97_88 可以加下划线</li><li>十六进制:0xff 可以加下划线</li><li>八进制:0o99 可以加下划线</li><li>二进制:0b01_0101 可以加下划线</li><li>字节(u8):b’A’</li></ul><p>整数溢出:</p><ul><li>debug模式下,会 panic</li><li>release 模式下,会发生“环绕”操作,不会 panic</li></ul><h3 id="浮点类型"><a class="markdownIt-Anchor" href="#浮点类型"></a> 浮点类型</h3><ul><li>f32,32位,单精度</li><li>f64,64位,双精度,默认类型,精度更高,和 f32 的速度在现代 CPU 上差不多</li></ul><h3 id="布尔类型"><a class="markdownIt-Anchor" href="#布尔类型"></a> 布尔类型</h3><p>bool</p><ul><li>true</li><li>false</li></ul><h3 id="字符类型"><a class="markdownIt-Anchor" href="#字符类型"></a> 字符类型</h3><p>char</p><p>单引号</p><p>占用 4 个字节</p><p>Unicode 标量值,可以表示比 ASCII 多得多的字符内容</p><ul><li>U+0000 到 U+D7FF</li><li>U+E000 到 U+10FFFF</li></ul><h2 id="复合类型"><a class="markdownIt-Anchor" href="#复合类型"></a> 复合类型</h2><p>复合类型:可以将多个值放在一个类型里</p><p>两种基础的复合类型:元组(Tuple)、数组</p><h3 id="tuple"><a class="markdownIt-Anchor" href="#tuple"></a> Tuple</h3><p>可以将多个类型的值放在一个类型里,每个位置对应一个类型</p><p>长度固定,一旦声明无法改变</p><figure class="highlight rust"><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">let</span> <span class="variable">tup</span>:(<span class="type">i32</span>, <span class="type">f64</span>, <span class="type">u8</span>) = (<span class="number">400</span>, <span class="number">4.6</span>, <span class="number">1</span>); </span><br><span class="line"><span class="keyword">let</span> (x, y, z) = tup;</span><br><span class="line"><span class="built_in">println!</span>(<span class="string">"{}, {}, {}"</span>, tup.<span class="number">0</span>, tup.<span class="number">1</span>, tup.<span class="number">2</span>); <span class="comment">// 通过 .index 的方式来取值</span></span><br></pre></td></tr></table></figure><h3 id="数组"><a class="markdownIt-Anchor" href="#数组"></a> 数组</h3><p>如果想要保存数据在栈而不是堆上,或者保证有固定数量的元素,就可以使用数组</p><p>数组没有 vector 灵活,vector 由标准库提供</p><p>优先使用 vector</p><p>访问越界的话,在编译期间不会报错,但是在运行时会 panic,rust 不允许访问越界地址的内存</p><figure class="highlight rust"><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">let</span> <span class="variable">a</span> = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];</span><br><span class="line"><span class="keyword">let</span> <span class="variable">a</span>: [<span class="type">i32</span>: <span class="number">5</span>] = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]; <span class="comment">// [类型:长度]</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">a</span> = [<span class="number">3</span>; <span class="number">5</span>]; <span class="comment">// 等同于 let a = [3,3,3,3,3],即 a = [初始值;长度]</span></span><br></pre></td></tr></table></figure><h2 id="函数"><a class="markdownIt-Anchor" href="#函数"></a> 函数</h2><p>针对函数和变量名,使用 snake case 命名规范,所有字母小写</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="title function_ invoke__">add</span>(<span class="number">34</span>,<span class="number">5</span>); <span class="comment">// argument</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// parameter, 必须声明每个参数的类型</span></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">add</span>(x: <span class="type">i32</span>, y: <span class="type">i32</span>) <span class="punctuation">-></span> <span class="type">i32</span>{ <span class="comment">// 只有返回值的类型,不可以为返回值命名</span></span><br><span class="line"> x + y <span class="comment">// 最后一个表达式即为返回值,也可以使用 return 提前返回</span></span><br><span class="line"> <span class="comment">// x + y; // 不可以加分号,如果加了分号,就是语句,语句的返回值是空的 tuple,即 () </span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="控制流-条件表达式"><a class="markdownIt-Anchor" href="#控制流-条件表达式"></a> 控制流: 条件表达式</h2><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">x</span> = <span class="number">3</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> x % <span class="number">10</span> == <span class="number">0</span> {</span><br><span class="line"></span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> x % <span class="number">3</span> == <span class="number">0</span> {</span><br><span class="line"></span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> x % <span class="number">7</span> == <span class="number">0</span> {</span><br><span class="line"></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">y</span> = <span class="keyword">if</span> x % <span class="number">10</span> == <span class="number">0</span> { <span class="number">5</span> } <span class="keyword">else</span> { <span class="number">6</span> }; <span class="comment">// 返回值类型必须是统一的,即编译期间能够确定类型</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="控制流-循环"><a class="markdownIt-Anchor" href="#控制流-循环"></a> 控制流: 循环</h2><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"></span><br><span class="line"> <span class="comment">// loop 循环</span></span><br><span class="line"> <span class="keyword">loop</span> {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"loop..."</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// loop 循环返回一个结果</span></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">counter</span> = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> <span class="variable">result</span> = <span class="keyword">loop</span> {</span><br><span class="line"> counter += <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> counter == <span class="number">10</span> {</span><br><span class="line"> <span class="keyword">break</span> counter; <span class="comment">// 通过 break 返回当前 loop 的值</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// while 循环</span></span><br><span class="line"> <span class="keyword">while</span> counter != <span class="number">100</span> {</span><br><span class="line"> counter += <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// for 循环</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">a</span> = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"> <span class="keyword">for</span> <span class="variable">element</span> <span class="keyword">in</span> a.<span class="title function_ invoke__">iter</span>() {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"element is {}"</span>, element);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// for range</span></span><br><span class="line"> <span class="keyword">for</span> <span class="variable">element</span> <span class="keyword">in</span> (<span class="number">1</span>..<span class="number">4</span>).<span class="title function_ invoke__">rev</span>() { <span class="comment">// (1..4) 只有 1,2,3 不包括 4,rev 就是反转一下</span></span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"element is {}"</span>, element);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考</h2><ol><li><a href="https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s">https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s</a></li><li>《rust权威指南(The Rust Programming Language)》</li></ol>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>rust教程-02</title>
<link href="/2022/10/18/rust%E6%95%99%E7%A8%8B-02/"/>
<url>/2022/10/18/rust%E6%95%99%E7%A8%8B-02/</url>
<content type="html"><![CDATA[<p>rust 教程 02: 例子</p><span id="more"></span><p>一个简单的猜数小游戏。</p><figure class="highlight rust"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 导入包的方式</span></span><br><span class="line"><span class="keyword">use</span> rand::Rng; <span class="comment">// 为什么导入 rng,但是下面没有用 rng,而是直接用 rand::thread_rng().gen_range();</span></span><br><span class="line"><span class="keyword">use</span> std::{cmp::Ordering, io};</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() {</span><br><span class="line"> <span class="comment">// let x = String::new(); 不加 mut 修饰词,则默认为 immut</span></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">secret_number</span> = rand::<span class="title function_ invoke__">thread_rng</span>().<span class="title function_ invoke__">gen_range</span>(<span class="number">1</span>, <span class="number">101</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">loop</span> {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"please input a number:"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">guess</span> = <span class="type">String</span>::<span class="title function_ invoke__">new</span>();</span><br><span class="line"> io::<span class="title function_ invoke__">stdin</span>().<span class="title function_ invoke__">read_line</span>(&<span class="keyword">mut</span> guess).<span class="title function_ invoke__">expect</span>(<span class="string">"input error!"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// let guess: u32 = guess.trim().parse().expect("pls input an interger...");</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">let</span> <span class="variable">guess</span>: <span class="type">u32</span> = <span class="keyword">match</span> guess.<span class="title function_ invoke__">trim</span>().<span class="title function_ invoke__">parse</span>() {</span><br><span class="line"> <span class="title function_ invoke__">Ok</span>(num) => num,</span><br><span class="line"> <span class="title function_ invoke__">Err</span>(_) => <span class="keyword">continue</span>,</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">match</span> guess.<span class="title function_ invoke__">cmp</span>(&secret_number) {</span><br><span class="line"> Ordering::Equal => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"win!!!"</span>);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> Ordering::Less => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"less~"</span>);</span><br><span class="line"> }</span><br><span class="line"> Ordering::Greater => {</span><br><span class="line"> <span class="built_in">println!</span>(<span class="string">"greater~"</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><br></pre></td></tr></table></figure><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考</h2><ol><li><a href="https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s">https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s</a></li><li>《rust权威指南(The Rust Programming Language)》</li></ol>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>wsl 数据迁移</title>
<link href="/2022/10/18/wsl-%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB/"/>
<url>/2022/10/18/wsl-%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB/</url>
<content type="html"><![CDATA[<p>wsl 数据迁移到其他硬盘</p><span id="more"></span><p>wsl 的默认目录 <code>C:\Users\kimroniny\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看所有的 wsl</span></span><br><span class="line">wsl -l -v </span><br><span class="line"><span class="comment"># 导出想要迁移的 wsl 到 tar</span></span><br><span class="line">wsl --<span class="built_in">export</span> Ubuntu-18.04 D:\wsl\Ubuntu.tar</span><br><span class="line"><span class="comment"># 注销想要迁移的 wsl, 此时原目录下的数据 ./LocalState 就消失了</span></span><br><span class="line">wsl --unregister Ubuntu-18.04</span><br><span class="line"><span class="comment"># 导入到指定目录</span></span><br><span class="line">wsl --import Ubuntu-18.04 D:\wsl\wsl2 D:\wsl\Ubuntu.tar --version 2</span><br><span class="line"><span class="comment"># 设置默认登录用户为指定用户</span></span><br><span class="line">ubuntu1804 config --default-user kimroniny</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> wsl </category>
</categories>
<tags>
<tag> wsl </tag>
</tags>
</entry>
<entry>
<title>ssh 登录到 wsl</title>
<link href="/2022/10/18/ssh-%E7%99%BB%E5%BD%95%E5%88%B0-wsl/"/>
<url>/2022/10/18/ssh-%E7%99%BB%E5%BD%95%E5%88%B0-wsl/</url>
<content type="html"><![CDATA[<p>局域网内主机登录到其他主机的 wsl</p><span id="more"></span><h2 id="wsl-到-windows-的端口映射"><a class="markdownIt-Anchor" href="#wsl-到-windows-的端口映射"></a> wsl 到 windows 的端口映射</h2><p>在 wsl 中通过 ifconfig 查看 ip,一定要使用该 ip,不要使用 windows 网络设置中 vEthernet switch 或者 vEthernet wsl 的 ip 地址。</p><p>假设该 ip 为 192.168.186.222</p><figure class="highlight bash"><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="comment"># listenport: 对外开放的端口</span></span><br><span class="line"><span class="comment"># connectaddress: wsl 的内部 ip</span></span><br><span class="line"><span class="comment"># connectport: wsl 的 ssh 端口</span></span><br><span class="line">netsh interface portproxy add v4tov4 listenport=50022 connectaddress=192.168.186.222 connectport=22 listenaddress=* protocol=tcp </span><br><span class="line"></span><br><span class="line"><span class="comment"># 删除端口转发</span></span><br><span class="line">netsh interface portproxy delete v4tov4 listenport=80 protocol=tcp</span><br></pre></td></tr></table></figure><p>在 windows 的防火墙高级设置中,在入规则中开放 50022 端口。</p><h2 id="配置-ssh"><a class="markdownIt-Anchor" href="#配置-ssh"></a> 配置 ssh</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 重新安装 ssh</span></span><br><span class="line">apt uninstall openssh-server</span><br><span class="line">apt update <span class="comment"># 有的 ubuntu 内核已经很旧了,会导致 install 时出现 url 失效的问题</span></span><br><span class="line">apt install openssh-server</span><br><span class="line"></span><br><span class="line"><span class="comment"># ssh 的配置文件</span></span><br><span class="line">/etc/ssh/sshd_config</span><br><span class="line"><span class="comment"># 本地用户的 ssh 目录</span></span><br><span class="line"><span class="built_in">chmod</span> 700 -R ~/.ssh </span><br><span class="line"><span class="built_in">chmod</span> 600 ~/.ssh/authorized_keys</span><br><span class="line"><span class="built_in">chown</span> user:user -R ~/.ssh</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> wsl </category>
</categories>
<tags>
<tag> wsl </tag>
<tag> ssh </tag>
</tags>
</entry>
<entry>
<title>rust教程-01</title>
<link href="/2022/10/17/rust%E6%95%99%E7%A8%8B-01/"/>
<url>/2022/10/17/rust%E6%95%99%E7%A8%8B-01/</url>
<content type="html"><![CDATA[<p>rust 教程 01: 环境部署</p><span id="more"></span><h2 id="基础知识"><a class="markdownIt-Anchor" href="#基础知识"></a> 基础知识</h2><p>rust 擅长的领域:</p><ul><li>高性能 web service</li><li>WebAssembly</li><li>命令行工具</li><li>网络编程</li><li>嵌入式设备</li><li>系统编程</li></ul><p>rust 的优点:</p><ul><li>性能(媲美 c/c++)</li><li>安全性(内存)</li><li>无所畏惧的并发</li></ul><h2 id="安装"><a class="markdownIt-Anchor" href="#安装"></a> 安装</h2><p>官网:<a href="https://www.rust-lang.org/">https://www.rust-lang.org/</a></p><figure class="highlight bash"><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">rustup update <span class="comment"># 更新</span></span><br><span class="line">rustup self uninstall <span class="comment"># 卸载</span></span><br><span class="line">rustc --version <span class="comment"># 版本</span></span><br></pre></td></tr></table></figure><p>安装的时候可能会出现 openssl 的问题, 此时需要设置</p><figure class="highlight bash"><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="built_in">export</span> RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static</span><br><span class="line"><span class="built_in">export</span> RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup</span><br></pre></td></tr></table></figure><p>开发工具:<code>vscode</code></p><p>插件:<code>rust</code></p><h2 id="基本程序"><a class="markdownIt-Anchor" href="#基本程序"></a> 基本程序</h2><p>后缀名:<code>.rs</code></p><p>文件命名规范:<code>hello_world.rs</code></p><p>编译:<code>rustc main.rs</code>,产生可执行文件</p><p>编译需要服务器安装 <code>gcc</code></p><p>rust 是 ahead-of-time 编译的语言,可以先编译,然后把可执行文件交给别人运行(无需安装 rust)。</p><h2 id="cargo"><a class="markdownIt-Anchor" href="#cargo"></a> cargo</h2><p>cargo 是 rust 的构建系统和包管理工具,即:构建代码、下载依赖的库、构建这些库…</p><p>安装 rust 的时候会安装 cargo。<code>cargo --version</code></p><p>包 packages 在 cargo 中叫做 <code>crate</code></p><p>cargo 生成的 <a href="http://main.rs">main.rs</a> 放在 src/ 目录下, cargo.toml 在项目顶层下,源代码都在 src/ 目录下,顶层目录可以放 readme、许可信息、配置文件、说明文档等与程序源码无关的文件</p><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line">cargo --version</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建项目 hello_cargo</span></span><br><span class="line"><span class="comment"># 包括文件:</span></span><br><span class="line"><span class="comment"># # cargo.toml 配置文件</span></span><br><span class="line"><span class="comment"># # src/ 源代码</span></span><br><span class="line"><span class="comment"># # .gitignore </span></span><br><span class="line">cargo new hello_cargo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 编译,创建可执行文件</span></span><br><span class="line"><span class="comment"># target/build/hello_cargo.exe</span></span><br><span class="line"><span class="comment"># cargo.lock文件,负责追踪项目依赖的精确版本</span></span><br><span class="line">cargo build</span><br><span class="line"></span><br><span class="line"><span class="comment"># 编译 + 执行</span></span><br><span class="line"><span class="comment"># 如果已经编译过且代码未修改,则直接执行</span></span><br><span class="line">cargo run</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查代码是否可以通过编译,不产生可执行文件</span></span><br><span class="line"><span class="comment"># 可以连续反复使用</span></span><br><span class="line">cargo check</span><br><span class="line"></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"># target/release</span></span><br><span class="line">cargo build --release</span><br></pre></td></tr></table></figure><blockquote><p>第一次执行的时候, 可能出现缺少 <code>cc</code> 的问题.<br />可以通过 <code>apt install build-essential</code> 解决</p></blockquote><p>cargo 更换国内源,在 <code>~/.cargo/config</code> 文件中填写下面内容,网络上提供了很多国内源,但是好像只有中科大的能用。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[source.crates-io]</span><br><span class="line">registry = "https://github.com/rust-lang/crates.io-index"</span><br><span class="line"># 指定镜像</span><br><span class="line">replace-with = 'ustc'</span><br><span class="line"></span><br><span class="line"># 中国科学技术大学</span><br><span class="line">[source.ustc]</span><br><span class="line">registry = "git://mirrors.ustc.edu.cn/crates.io-index"</span><br></pre></td></tr></table></figure><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考</h2><ol><li><a href="https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s">https://www.youtube.com/watch?v=e3-2uxHhbzs&list=PL3azK8C0kje1DUJbaOqce19j3R_-tIc4_&index=1&t=140s</a></li><li>《rust权威指南(The Rust Programming Language)》</li></ol>]]></content>
<categories>
<category> rust </category>
</categories>
<tags>
<tag> rust </tag>
</tags>
</entry>
<entry>
<title>软件架构模式演进</title>
<link href="/2022/10/17/%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E6%A8%A1%E5%BC%8F%E6%BC%94%E8%BF%9B/"/>
<url>/2022/10/17/%E8%BD%AF%E4%BB%B6%E6%9E%B6%E6%9E%84%E6%A8%A1%E5%BC%8F%E6%BC%94%E8%BF%9B/</url>
<content type="html"><![CDATA[<p>软件架构模式基本演进过程。</p><span id="more"></span><p><strong>软件的架构模式总的说经历了三个阶段的演进:从单机、集中式到分布式微服务架构。</strong></p><h2 id="单机架构"><a class="markdownIt-Anchor" href="#单机架构"></a> 单机架构</h2><p>通常采用面向过程的设计方法。采用 C/S 架构。</p><h2 id="集中式架构"><a class="markdownIt-Anchor" href="#集中式架构"></a> 集中式架构</h2><p>通常采用面向对象的设计方法。采用三层架构 MVC,系统包括业务接入层、业务逻辑层和数据库层。</p><h2 id="分布式微服务架构"><a class="markdownIt-Anchor" href="#分布式微服务架构"></a> 分布式微服务架构</h2><p>可以实现业务和应用之间的解耦,解决单体应用扩展性差、弹性伸缩能力不足的问题,适合在云环境下部署运营。</p><p><strong>三种设计模式的演进:页面驱动设计,数据驱动设计,领域驱动设计。</strong></p><h2 id="页面驱动设计"><a class="markdownIt-Anchor" href="#页面驱动设计"></a> 页面驱动设计</h2><p>主要集中在客户端开发过程。</p><p>以设计稿为标准进行开发的,每位客户端开发的同学要开展工作都离不开 UI 设计师的设计稿。</p><h2 id="数据驱动设计"><a class="markdownIt-Anchor" href="#数据驱动设计"></a> 数据驱动设计</h2><p>主要集中在服务端开发过程。</p><p>设计数据库表结构是最重要的环节:对业务的理解程度,对可扩展性的考虑程度都直接影响到了我们会“如何设计数据库表结构”;数据库表结构设计是否合理,也直接影响了我们后续开发业务逻辑是否顺利</p><h2 id="领域驱动设计-ddddomain-driven-design"><a class="markdownIt-Anchor" href="#领域驱动设计-ddddomain-driven-design"></a> 领域驱动设计 DDD(Domain Driven Design)</h2><p>核心思想是避免<strong>业务逻辑的复杂性</strong>和<strong>技术实现的复杂性</strong>耦合在一起。</p><p>最大的价值在于梳理业务需求,抽象出一个个“领域”,并形成各个领域之间的交互接口。</p><p>“模型”是 DDD 中的重要概念:模型是对领域的抽象和模拟。</p><p>“建模”是 DDD 中重要的手段:建模时针对特定问题建立该领域的合理模型。</p><p>观点:不以用户为中心。DDD 认为:以用户为中心是表层需求,真正的需求是基于领域的,领域之所以有意义,一定是和人有关系。</p><p><strong>转变编程语言到 golang 的制胜法宝:三刷官方文档</strong></p><ul><li>一刷:从头看到尾,扫清知识盲点和概念;</li><li>二刷:手敲,注释和总结;</li><li>三刷:写注释,不看文档实现功能,遇到问题再和文档比较,加深理解。</li></ul><hr /><p>参考:</p><ol><li><a href="https://xie.infoq.cn/article/70fc253b683d5a7eaac833617">给想转 Go 或者 Go 进阶同学的一些建议</a></li></ol>]]></content>
<categories>
<category> architect </category>
<category> software design </category>
</categories>
<tags>
<tag> architect </tag>
<tag> software design </tag>
</tags>
</entry>
<entry>
<title>软件开发模式</title>
<link href="/2022/10/15/%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E6%A8%A1%E5%BC%8F/"/>
<url>/2022/10/15/%E8%BD%AF%E4%BB%B6%E5%BC%80%E5%8F%91%E6%A8%A1%E5%BC%8F/</url>
<content type="html"><![CDATA[<p>四种软件开发模式。</p><span id="more"></span><h2 id="瀑布开发模式"><a class="markdownIt-Anchor" href="#瀑布开发模式"></a> 瀑布开发模式</h2><p>一种传统的软件开发模式。</p><p>包括五个顺序阶段:需求,设计,实现,测试,维护。</p><p>如果软件项目对稳定要求比较高,则可以选择瀑布开发模式。但是该模式开发事件久,成本高。</p><h2 id="快速应用开发模式"><a class="markdownIt-Anchor" href="#快速应用开发模式"></a> 快速应用开发模式</h2><p>比较精简的软件开发流程,可以低成本生产高质量的软件。需要开发人员快速适应不断变化的市场需求。</p><p>包括四个阶段:需求设计,用户设计,构建,切换。重复用户设计和施工阶段,直到满足用户所有要求。</p><p>适合中小型软件开发项目,需要开发人员具有丰富的开发经验,非常了解用户的核心需求。</p><h2 id="敏捷开发模式"><a class="markdownIt-Anchor" href="#敏捷开发模式"></a> 敏捷开发模式</h2><p>拥有多种不同的形式,包括:Scrum,Crystal,XP 和 FDD 等。</p><p>通过迭代开发,互动沟通等方法来降低软件开发过程中的风险,通过早期发现和修复缺陷来提高开发的效率,比较依赖用户的信息反馈。</p><p>适用于小规模的软件开发公司。</p><h2 id="devops部署模式"><a class="markdownIt-Anchor" href="#devops部署模式"></a> DevOps部署模式</h2><p>增强了软件开发部门之间的协作(开发、测试、运营等)。着重于改进软件的上市时间,降低新版本的故障率,缩短 BUG 修复时间,优先考虑最小的中断以及最大的可靠性等。</p><p>对提高客户满意度,提高产品质量,提高员工的生产力和效率得益等方面非常有用。</p><p><strong>参考:</strong><br />1.<a href="https://blog.csdn.net/qq_19970313/article/details/124783524">https://blog.csdn.net/qq_19970313/article/details/124783524</a></p>]]></content>
<categories>
<category> architect </category>
<category> software design </category>
</categories>
<tags>
<tag> architect </tag>
<tag> software design </tag>
</tags>
</entry>
<entry>
<title>自我安慰 - 吧</title>
<link href="/2022/10/13/%E8%87%AA%E6%88%91%E5%AE%89%E6%85%B0-%E5%90%A7/"/>
<url>/2022/10/13/%E8%87%AA%E6%88%91%E5%AE%89%E6%85%B0-%E5%90%A7/</url>
<content type="html"><![CDATA[<p>去 TMD 条条框框吧,洒脱一点!</p><span id="more"></span><p>要学会控制自己的关注点,在研究讨论的过程中,只考虑别人的文字,不考虑别人的情绪,不考虑情绪的目的是为了不被情绪所影响,也就是不要被别人的挤眉弄眼或者反问的语气所影响,可以把别人带有情绪的语言用自己的陈述句复述一遍,去思考其中的道理,多问自己几遍内容。</p><p>如果要解决“无法给老师讲清楚 idea ”的问题,就要多和老师讨论。这个问题的关键不在于我们讲的多么清楚、细致,而在于是否讲到了老师所关注的方向和粒度上。因此,必须要经常和老师交流,才能更加清晰的明白他们的关注点的维度,不能只靠自己闭门造车,要对全局范围内的各个对象有清楚的把握。</p>]]></content>
<tags>
<tag> fuck life </tag>
</tags>
</entry>
<entry>
<title>NAT简介</title>
<link href="/2022/10/12/NAT%E7%AE%80%E4%BB%8B/"/>
<url>/2022/10/12/NAT%E7%AE%80%E4%BB%8B/</url>
<content type="html"><![CDATA[<p>NAT 的相关知识</p><span id="more"></span><p>NAT(Network Address Translator,网络地址转换)是用于在本地网络中使用私有地址,在连接互联网时转而使用全局 IP 地址的技术。NAT实际上是为解决IPv4地址短缺而开发的技术。</p><p>即私有地址转换为公有地址(加端口)。</p><p>NAT 的特点:</p><ul><li>NAT 存在于私网到公网的路由出口位置,双向流量都必须经过 NAT 网关。</li><li>网络访问只能由私网向公网发起,公网无法访问私网。</li><li>NAT 需要维护一张关联表,保存会话信息,从而实现翻译功能。</li></ul><p>NAT 的类型:</p><ul><li>静态 NAT。一对一绑定转换。</li><li>动态 NAT。从空闲的地址池中选择一个进行转换。</li><li>端口复用 NATP。当私网内主机数量太多时,面临端口数量不足从而无法翻译的问题,此时,需要根据传输层或者其他上层协议去区分不同的会话,比如 TCP、UDP 端口号,从而实现公网 ip 的复用和解复用,</li></ul><p>NAT 的缺点:</p><ul><li>一旦 NAT 路由器重启,所有的 TCP 连接都会被重置断开。</li><li>关联表的生成和转换操作会产生一定的开销。</li><li>无法从 NAT 外部向内部服务器建立连接。</li></ul><p>参考:</p><ul><li><a href="https://blog.csdn.net/yingshuanglu2564/article/details/111830114">详解什么是NAT?</a></li></ul>]]></content>
<categories>
<category> network </category>
<category> nat </category>
</categories>
<tags>
<tag> network </tag>
<tag> nat </tag>
</tags>
</entry>
<entry>
<title>局域网间消息传递</title>
<link href="/2022/10/12/%E5%B1%80%E5%9F%9F%E7%BD%91%E9%97%B4%E6%B6%88%E6%81%AF%E4%BC%A0%E9%80%92/"/>
<url>/2022/10/12/%E5%B1%80%E5%9F%9F%E7%BD%91%E9%97%B4%E6%B6%88%E6%81%AF%E4%BC%A0%E9%80%92/</url>
<content type="html"><![CDATA[<p>局域网 IP 之间如何传递消息?</p><span id="more"></span><p>假设:</p><ul><li>腾讯服务器IP为118.89.97.19(当然实际会用域名,但经过DNS解析后还是IP,并且会又很多集群和部署在不同城市的机房)</li><li>家里的路由器拨号后有公网IP,不像校园网,分配的还是内网IP;</li><li>两个路由器公网IP分别为101.45.251.154、218.80.220.124;</li><li>登录时成功时,小明在自己电脑查看建立的TCP连接:<br />192.168.1.101:2099 118.89.97.19:80 establish</li><li>这只是一个假象,在腾讯服务器端查看到的连接是(端上IP和端口从192.168.1.101:2099变换成了路由器公网IP101.45.251.154和10000):<br />118.89.97.19:80 101.45.251.154:10000 establish</li><li>同理小明女朋友登录后也是同样的情况。<br />源IP 192.168.1.101|源端口2099|收件人、消息内容|目标IP 118.89.97.19|目标端口80</li></ul><p>数据包到达家里路由器,源IP地址会被NAT(了解更多请自己百度)更换成101.45.251.154,端口会被换成10000,然后经过层层转发到腾讯服务器,会得到“收件人、消息内容”的数据,然后入库并根据收件人将图片的数据,服务器检测到女朋友的账号又新消息到达时,从数据库读取消息,写入小明女朋友手机跟腾讯服务器之间的长连接通道,这时数据报文格式为:</p><p>源IP 118.89.97.19|源端口80|图片消息内容|目标IP 218.80.220.124|目标端口31214(女朋友手机聊天软件跟服务器通信时创建的端口)</p><p>消息同样经过层层转发到达女朋友家里的路由器,路由器根据端口31214,查到这个是需要发到女朋友手机上的,于是NAT把目标IP换成192.168.1.101,端口换成8888,于是手机收到消息并分发给聊天软件。</p><p>参考:</p><ul><li><a href="https://www.zhihu.com/question/64560386/answer/225743007">联网的软件是如何实现将消息从公网发送到内网的?</a></li></ul>]]></content>
</entry>
<entry>
<title>软件设计流程</title>
<link href="/2022/10/12/%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E6%B5%81%E7%A8%8B/"/>
<url>/2022/10/12/%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E6%B5%81%E7%A8%8B/</url>
<content type="html"><![CDATA[<p>软件开发的五个阶段。</p><span id="more"></span><p>分析阶段, 设计阶段, 开发阶段, 测试阶段, 维护阶段。</p><h2 id="1-分析阶段"><a class="markdownIt-Anchor" href="#1-分析阶段"></a> 1. 分析阶段</h2><p>进行需求调研,提炼用户需求,建立完整的分析模式。</p><h2 id="2-设计阶段"><a class="markdownIt-Anchor" href="#2-设计阶段"></a> 2. 设计阶段</h2><p>主要分为:概要设计,详细设计。</p><h3 id="概要设计"><a class="markdownIt-Anchor" href="#概要设计"></a> 概要设计</h3><p>依照结构化设计方法进行设计。按照问题域,将软件逐级细化,分解为<strong>不必再分解的模块</strong>,每个模块完成一定的功能。模块,和子程序或者函数是对应的。</p><p>设计者会大致考虑模块的内部实现,但不用太纠结,聚焦在:确定功能,划分模块,定义调用关系。</p><p>调用关系(接口和参数)非常重要,必须在该阶段确定下来。</p><p>一般不会一次性到位,需要反复迭代调整。</p><p>需要完成的设计内容:</p><ul><li>数据字典。</li><li>数据流图。</li><li>结构图。</li><li>文字说明。</li></ul><h3 id="详细设计"><a class="markdownIt-Anchor" href="#详细设计"></a> 详细设计</h3><p>概要设计结束之后,针对各个模块,其详细设计可以并行执行。</p><p>根据概要设计的模块分解,设计每个模块内的算法、流程,描述模块内的具体功能。</p><p>如果详细设计的过程中有结构调整的必要,必须返还到概要设计阶段进行调整。</p><p>详细设计应该足够细致,能够根据该设计进行编码。</p><p>需要完成的设计内容:</p><ul><li>伪代码。</li><li>流程图。</li><li>PAD图。</li></ul><h2 id="3-开发阶段"><a class="markdownIt-Anchor" href="#3-开发阶段"></a> 3. 开发阶段</h2><p>各个模块根据详细设计进行编码。</p><p>开发过程中,先实现核心代码 demo,确定可以运行后,在模块中进行实现。</p><p>多打日志,能清晰看到各个子过程的中间输出。</p><p>做好注释,秉持着先注释后代码的原则,可以不写代码,但是注释必须要有,不只是诠释当前代码的作用,还要有 TODO BUG 等辅助信息。</p><p>每个功能函数在开发的过程中要为方便单元测试而进行设计。</p><p>善于运用 git 进行代码审核,每周都要进行代码审核,互相了解各模块间的开发进度和开发方式,及时调整不协调的环节。</p><h2 id="4-测试阶段"><a class="markdownIt-Anchor" href="#4-测试阶段"></a> 4. 测试阶段</h2><p>需要对程序进行单元、组装、系统三阶段的测试。</p><h2 id="5-维护阶段"><a class="markdownIt-Anchor" href="#5-维护阶段"></a> 5. 维护阶段</h2><p>软件研发完成并交付使用后,需要做好软件维护工作。</p><hr /><h2 id="参考"><a class="markdownIt-Anchor" href="#参考"></a> 参考:</h2><ol><li><a href="https://36kr.com/p/1508223783276551">软件开发流程五个阶段</a></li></ol>]]></content>
<categories>
<category> architect </category>
<category> software design </category>
</categories>
<tags>
<tag> architect </tag>
<tag> software design </tag>
</tags>
</entry>
<entry>
<title>了解云原生</title>
<link href="/2022/10/09/%E4%BA%86%E8%A7%A3%E4%BA%91%E5%8E%9F%E7%94%9F/"/>
<url>/2022/10/09/%E4%BA%86%E8%A7%A3%E4%BA%91%E5%8E%9F%E7%94%9F/</url>
<content type="html"><![CDATA[<p>什么是云原生?要解决什么关键问题?</p><span id="more"></span><p>技术的变革,一定是思想先行。</p><p>Pivotal公司的Matt Stine于2013年首次提出云原生(CloudNative)的概念。</p><p>云原生是一种构建和运行应用程序的方法,是一套技术体系和方法论。</p><p>云原生(CloudNative)是一个组合词,Cloud+Native。<br />Cloud表示应用程序位于云中,而不是传统的数据中心;<br />Native表示应用程序从设计之初即考虑到云的环境,原生为云而设计,在云上以最佳姿势运行,<strong>充分利用和发挥云平台的弹性+分布式优势</strong>。</p><p>符合云原生架构的应用程序应该是:</p><ul><li>采用开源堆栈(K8S+Docker)进行容器化,</li><li>基于微服务架构提高灵活性和可维护性,</li><li>借助敏捷方法、DevOps支持持续迭代和运维自动化,</li><li>利用云平台设施实现弹性伸缩、动态调度、优化资源利用率</li></ul><p>云原生的四个要素:</p><ul><li><strong>微服务</strong>。几乎每个云原生的定义都包含微服务,跟微服务相对的是单体应用,微服务有理论基础,那就是康威定律。</li><li><strong>容器化</strong>。Docker 和 K8S(容器编排系统)。</li><li><strong>DevOps</strong>。Dev+Ops,就是开发和运维合体。</li><li><strong>持续交付</strong>。不误时开发,不停机更新,小步快跑,反传统瀑布式开发模型</li></ul><p>云计算是云原生的基础。</p><p>随着<strong>虚拟化技术的成熟和分布式框架的普及</strong>,在容器技术、可持续交付、编排系统等开源社区的推动下,以及微服务等开发理念的带动下,应用上云已经是不可逆转的趋势。</p><p>云计算三层:基础设施即服务(IaaS)、平台即服务(PaaS)、软件即服务(SaaS)。</p><p>真正的云化不仅仅是基础设施和平台的变化,应用也需要做出改变,摈弃传统的土方法,在<strong>架构设计、开发方式、部署维护等各个阶段和方面</strong>都基于云的特点,重新设计,从而建设全新的云化的应用,即云原生应用。</p><p>云的特点:</p><ul><li>编程语言。由传统的 c/c++、java 转换为<strong>以网络为中心</strong>的 go、nodejs 语言。</li><li>不停机更新。传统应用可能需要停机更新,但是<strong>云支持频繁变更</strong>,持续交付,蓝绿部署。</li><li>弹性资源。传统应用需要冗余资源以抵抗流量高峰,而云原生应用<strong>利用云的弹性自动伸缩</strong>,通过共享降本增效。</li><li>网络资源。传统应用对网络资源,比如ip、端口等有依赖,甚至是硬编码,而云原生应用对网络和存储都没有这种限制</li><li>运维。传统应用通常人肉部署手工运维,而云原生应用这一切都是<strong>自动化</strong>的。</li><li>系统环境。传统应用通常依赖系统环境,而云原生应用不会硬连接到任何系统环境,而是<strong>依赖抽象的基础架构</strong>,从而获得良好移植性</li><li>微服务。基于微服务架构的云原生应用,纵向划分服务,模块化更合理。</li></ul><p>软件设计有两个关键目标:<strong>高内聚、低耦合</strong>。</p><p>纵观近二十年的科技互联网发展历程,<strong>大的趋势是技术下沉</strong>,<br />特别是近些年,随着云计算的发展和普及,基础设施越来越厚实,<strong>业务开发变得越来越容易,也越来越没有技术含量</strong>,<br />而之前困扰小团队的性能、负载、安全性、扩展性问题都不复存在。</p><p>虽然不可否认技术的重要性在降低,但也还不至于那么悲观。<br />遥想PC时代,当VB、Delphi、MFC出现的时候,也有类似论调,所见即所得,点点鼠标,就可以开发PC桌面程序,是不是很高端?<br />那时候码农的担心相比现在恐怕是只多不少吧,<br />但后来随着互联网兴起,出现了后端开发这个工种,<br />码农很快找到了新的战场,网络、分布式、数据库、海量服务、容灾防错,<br />于是又玩出一堆新花样。</p><p>如果说PC时代的基础设施是控件库,互联网时代的基础实施是云,那AI时代基础设施是什么?又会有什么高端玩法?</p><p><a href="https://juejin.cn/post/6844904197859590151">原文链接</a></p>]]></content>
<categories>
<category> 云计算 </category>
<category> 云原生 </category>
</categories>
<tags>
<tag> 云原生 </tag>
<tag> 云计算 </tag>
</tags>
</entry>
<entry>
<title>如何成为一名架构师</title>
<link href="/2022/10/08/%E5%A6%82%E4%BD%95%E6%88%90%E4%B8%BA%E4%B8%80%E5%90%8D%E6%9E%B6%E6%9E%84%E5%B8%88/"/>
<url>/2022/10/08/%E5%A6%82%E4%BD%95%E6%88%90%E4%B8%BA%E4%B8%80%E5%90%8D%E6%9E%B6%E6%9E%84%E5%B8%88/</url>
<content type="html"><![CDATA[<p>在成为一名架构师的道路上,所见所学所得。</p><span id="more"></span><p>对于一名架构师而言,写代码是最不重要的事情,摆在第一位的应该是设计。<br />但是“设计”并不是单纯的天马行空地去描绘一个系统,<br />需要对主流的设计模式有深入的理解,需要了解主流技术的优缺点以及所适应的场景,更重要的是,能够满足用户的需求。</p><p>设计模式,主流技术的特性,这些都是内功,<br />外功则是设计图的展现能力,能够将想法通过很好的形式展现给用户并使之感受到自己的需求被很好的满足的能力。<br />这就要求会使用主流的设计软件和设计图的绘制方式,如时序图、流程图等等。</p>]]></content>
<categories>
<category> dao </category>
<category> architect </category>
</categories>
<tags>
<tag> architect </tag>
</tags>
</entry>
<entry>
<title>xshell破解版</title>
<link href="/2020/10/02/xshell%E7%A0%B4%E8%A7%A3%E7%89%88/"/>
<url>/2020/10/02/xshell%E7%A0%B4%E8%A7%A3%E7%89%88/</url>
<content type="html"><![CDATA[<p>xshell 破解版的一些东西(文件,缺失ddl等)</p><span id="more"></span><h2 id="破解版"><a class="markdownIt-Anchor" href="#破解版"></a> 破解版</h2><p>在百度云里,<code>软件/xshell6</code></p><h2 id="缺失ddl"><a class="markdownIt-Anchor" href="#缺失ddl"></a> 缺失ddl</h2><p>下载地址: <a href="!https://www.microsoft.com/zh-CN/download/details.aspx?id=30679">https://www.microsoft.com/zh-CN/download/details.aspx?id=30679</a></p><p>对于64位的机器,一定要下载把32位和64位的安装包都下载下来安装</p>]]></content>
<categories>
<category> xshell </category>
</categories>
<tags>
<tag> xshell </tag>
</tags>
</entry>
<entry>
<title>ubuntu更新下载源</title>
<link href="/2020/10/02/ubuntu%E6%9B%B4%E6%96%B0%E4%B8%8B%E8%BD%BD%E6%BA%90/"/>
<url>/2020/10/02/ubuntu%E6%9B%B4%E6%96%B0%E4%B8%8B%E8%BD%BD%E6%BA%90/</url>
<content type="html"><![CDATA[<p>更新ubuntu的apt下载源</p><span id="more"></span><p>在文件 <code>/etc/apt/sources.list</code> 开头添加源(见末尾)。</p><p>然后执行以下操作:</p><figure class="highlight bash"><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">sudo apt update</span><br><span class="line">sudo apt upgrade</span><br><span class="line">sudo apt-get install build-essential</span><br></pre></td></tr></table></figure><h2 id="aliyun下载源"><a class="markdownIt-Anchor" href="#aliyun下载源"></a> aliyun下载源</h2><p>不同的ubuntu版本,下载源也不相同,不能用一套。</p><h3 id="ubuntu-1404"><a class="markdownIt-Anchor" href="#ubuntu-1404"></a> ubuntu 14.04</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">deb https://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse</span><br><span class="line">deb https://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb https://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb https://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse</span><br></pre></td></tr></table></figure><h3 id="ubuntu-1604"><a class="markdownIt-Anchor" href="#ubuntu-1604"></a> ubuntu 16.04</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial main</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial main</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial universe</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial universe</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates universe</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-security main</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security universe</span><br></pre></td></tr></table></figure><h3 id="ubuntu-1804"><a class="markdownIt-Anchor" href="#ubuntu-1804"></a> ubuntu 18.04</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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">deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse</span><br></pre></td></tr></table></figure><h3 id="ubuntu-2004"><a class="markdownIt-Anchor" href="#ubuntu-2004"></a> ubuntu 20.04</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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">deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line"></span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> linux </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux查看系统配置</title>
<link href="/2020/08/17/linux%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E9%85%8D%E7%BD%AE/"/>
<url>/2020/08/17/linux%E6%9F%A5%E7%9C%8B%E7%B3%BB%E7%BB%9F%E9%85%8D%E7%BD%AE/</url>
<content type="html"><![CDATA[<p>从命令行查看系统配置</p><span id="more"></span><h2 id="ubuntu"><a class="markdownIt-Anchor" href="#ubuntu"></a> Ubuntu</h2><p>命令: lshw</p><p>linux查看设备命令</p><p>系统</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">uname -a # 查看内核/操作系统/CPU信息</span><br><span class="line">head -n 1 /etc/issue # 查看操作系统版本 </span><br><span class="line">cat /proc/cpuinfo # 查看CPU信息</span><br><span class="line">hostname # 查看计算机名 </span><br><span class="line">lspci -tv # 列出所有PCI设备</span><br><span class="line">lsusb -tv # 列出所有USB设备 </span><br><span class="line">lsmod # 列出加载的内核模块</span><br><span class="line">env # 查看环境变量</span><br></pre></td></tr></table></figure><p>资源</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">free -m # 查看内存使用量和交换区使用量 </span><br><span class="line">df -h # 查看各分区使用情况 </span><br><span class="line">du -sh <目录名> # 查看指定目录的大小 </span><br><span class="line">grep MemTotal /proc/meminfo # 查看内存总量</span><br><span class="line">grep MemFree /proc/meminfo # 查看空闲内存量</span><br><span class="line">uptime # 查看系统运行时间、用户数、负载 </span><br><span class="line">cat /proc/loadavg # 查看系统负载</span><br></pre></td></tr></table></figure><p>磁盘和分区</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">mount | column -t # 查看挂接的分区状态 </span><br><span class="line">fdisk -l # 查看所有分区 </span><br><span class="line">swapon -s # 查看所有交换分区</span><br><span class="line">hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备) </span><br><span class="line">dmesg | grep IDE # 查看启动时IDE设备检测状况</span><br></pre></td></tr></table></figure><p>网络</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">ifconfig # 查看所有网络接口的属性</span><br><span class="line">iptables -L # 查看防火墙设置 </span><br><span class="line">route -n # 查看路由表 </span><br><span class="line">netstat -lntp # 查看所有监听端口 </span><br><span class="line">netstat -antp # 查看所有已经建立的连接</span><br><span class="line">netstat -s # 查看网络统计信息</span><br></pre></td></tr></table></figure><p>进程</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ps -ef # 查看所有进程 </span><br><span class="line">ps -ux # 查看当前用户进程</span><br><span class="line">top # 实时显示进程状态</span><br></pre></td></tr></table></figure><p>用户</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">w # 查看活动用户 </span><br><span class="line">id <用户名> # 查看指定用户信息 </span><br><span class="line">last # 查看用户登录日志 </span><br><span class="line">cut -d: -f1 /etc/passwd # 查看系统所有用户 </span><br><span class="line">cut -d: -f1 /etc/group # 查看系统所有组 </span><br><span class="line">crontab -l # 查看当前用户的计划任务</span><br></pre></td></tr></table></figure><p>服务</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">首先安装chkconfig</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">apt-get install sysv-rc-conf</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">cp</span> /usr/sbin/sysv-rc-conf /usr/sbin/chkconfig</span></span><br><span class="line">chkconfig --list # 列出所有系统服务 </span><br><span class="line">chkconfig --list | grep on # 列出所有启动的系统服务</span><br></pre></td></tr></table></figure><p>程序</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -qa # 查看所有安装的软件包</span><br></pre></td></tr></table></figure><p>常用命令整理如下:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">dmidecode | grep -i ’serial number’ # 查看主板的序列号</span><br><span class="line">service kudzu start ( or restart) # 用硬件检测程序kuduz探测新硬件</span><br><span class="line">cat /proc/cpuinfo, dmesg | grep -i 'cpu', dmidecode -t processor # 查看CPU信息</span><br><span class="line">cat /proc/meminfo, free -m, vmstat # 查看内存信息</span><br><span class="line">cat /proc/pci # 查看板卡信息</span><br><span class="line">lspci |grep -i 'VGA', dmesg | grep -i 'VGA' # 查看显卡/声卡信息</span><br><span class="line">dmesg | grep -i 'eth', cat /etc/sysconfig/hwconf | grep -i eth, lspci | grep -i 'eth' # 查看网卡信息</span><br><span class="line">lspci (相比cat /proc/pci更直观)# 查看PCI信息</span><br><span class="line">cat /proc/bus/usb/devices # 查看USB设备</span><br><span class="line">cat /proc/bus/input/devices # 查看键盘和鼠标</span><br><span class="line">fdisk & disk – l & df # 查看系统硬盘信息和使用情况</span><br><span class="line">cat /proc/interrupts # 查看各设备的中断请求(IRQ)</span><br><span class="line">uname -a # 查看系统体系结构</span><br><span class="line">isalist –v, isainfo –v, isainfo –b # 查看及启动系统的32位或64位内核模式</span><br></pre></td></tr></table></figure><p>测定当前的显示器刷新频率:/usr/sbin/ffbconfig –rev ?</p><p>查看系统配置:/usr/platform/sun4u/sbin/prtdiag –v</p><p>查看当前系统中已经应用的补丁:showrev –p</p><p>显示当前的运行级别:who –rH</p><p>查看当前的bind版本信息:nslookup –class=chaos –q=txt version.bind</p><p>dmesg | more 查看硬件信息<br />lspci 显示外设信息, 如usb,网卡等信息<br />lsnod 查看已加载的驱动<br />lshw<br />psrinfo -v 查看当前处理器的类型和速度(主频)<br />prtconf -v 打印当前的OBP版本号<br />iostat –E 查看硬盘物理信息(vendor, RPM, Capacity)<br />prtvtoc /dev/rdsk/c0t0d0s 查看磁盘的几何参数和分区信息<br />df –F ufs –o i 显示已经使用和未使用的i-node数目<br />isalist –v</p><p>对于“/proc”中文件可使用文件查看命令浏览其内容,文件中包含系统特定信息:<br />Cpuinfo 主机CPU信息<br />Dma 主机DMA通道信息<br />Filesystems 文件系统信息<br />Interrupts 主机中断信息<br />Ioprots 主机I/O端口号信息<br />Meninfo 主机内存信息<br />Version Linux内存版本信息</p><p>备注: proc – process information pseudo-filesystem 进程信息伪装文件系统</p><p>RPM</p><pre><code>在Linux 操作系统中,有一个系统软件包,它的功能类似于Windows里面的“添加/删除程序”,但是功能又比“添加/删除程序”强很多,它就是 Red Hat Package Manager(简称RPM)。此工具包最先是由Red Hat公司推出的,后来被其他Linux开发商所借用。由于它为Linux使用者省去了很多时间,所以被广泛应用于在Linux下安装、删除软件。下面就 给大家介绍一下它的具体使用方法。</code></pre><p>1.我们得到一个新软件,在安装之前,一般都要先查看一下这个软件包里有什么内容,假设这个文件是:Linux-1.4-6.i368.rpm,我们可以用这条命令查看:</p><p>rpm -qpi Linux-1.4-6.i368.rpm</p><p>系统将会列出这个软件包的详细资料,包括含有多少个文件、各文件名称、文件大小、创建时间、编译日期等信息。</p><p>2.上面列出的所有文件在安装时不一定全部安装,就像Windows下程序的安装方式分为典型、完全、自定义一样,Linux也会让你选择安装方式,此时我们可以用下面这条命令查看软件包将会在系统里安装哪些部分,以方便我们的选择:</p><p>rpm -qpl Linux-1.4-6.i368.rpm</p><ol><li>选择安装方式后,开始安装。我们可以用rpm-ivh Linux-1.4-6.i368.rpm命令安装此软件。在安装过程中,若系统提示此软件已安装过或因其他原因无法继续安装,但若我们确实想执行安装命 令,可以在 -ivh后加一参数“-replacepkgs”:</li></ol><p>rpm -ivh -replacepkgs Linux-1.4-6.i368.rpm</p><p>4.有时我们卸载某个安装过的软件,只需执行rpm-e <文件名>;命令即可。</p><p>5.对低版本软件进行升级是提高其功能的好办法,这样可以省去我们卸载后再安装新软件的麻烦,要升级某个软件,只须执行如下命令:rpm -uvh <文件名>;,注意:此时的文件名必须是要升级软件的升级补丁</p><ol start="6"><li>另外一个安装软件的方法可谓是Linux的独到之处,同时也是RMP强大功能的一个表现:通过FTP站点直接在线安装软件。当找到含有你所需软件的站点并 与此网站连接后,执行下面的命令即可实现在线安装,譬如在线安装Linux-1.4-6.i368.rpm,可以用命令: <a href="http://www.it165.net">www.it165.net</a></li></ol><p>rpm -i <a href="ftp://ftp.pht.com/pub/linux/redhat/">ftp://ftp.pht.com/pub/linux/redhat/</a>…-1.4-6.i368.rpm</p><ol start="7"><li>在我们使用电脑过程中,难免会有误操作,若我们误删了几个文件而影响了系统的性能时,怎样查找到底少了哪些文件呢?RPM软件包提供了一个查找损坏文件的 功能,执行此命令:rpm -Va即可,Linux将为你列出所有损坏的文件。你可以通过Linux的安装光盘进行修复。</li></ol><p>8.Linux系统中文件繁多,在使用过程中,难免会碰到我们不认识的文件,在Windows下我们可以用“开始/查找”菜单快速判断某个文件属于哪个文件夹,在Linux中,下面这条命令行可以帮助我们快速判定某个文件属于哪个软件包:</p><p>rpm -qf <文件名>;</p><p>9.当每个软件包安装在Linux系统后,安装文件都会到RPM数据库中“报到”,所以,我们要查询某个已安装软件的属性时,只需到此数据库中查找即可。注意:此时的查询命令不同于1和8介绍的查询,这种方法只适用于已安装过的软件包!命令格式:</p><p>rpm -参数 <文件名>;</p><p>APT-GET</p><p>apt-get update——在修改/etc/apt/sources.list或者/etc/apt/preferences之后运行该命令。此外您需要定期运行这一命令以确保您的软件包列表是最新的。<br />apt-get install packagename——安装一个新软件包(参见下文的aptitude)<br />apt-get remove packagename——卸载一个已安装的软件包(保留配置文件)<br />apt-get --purge remove packagename——卸载一个已安装的软件包(删除配置文件)<br />dpkg --force-all --purge packagename 有些软件很难卸载,而且还阻止了别的软件的应用,就可以用这个,不过有点冒险。<br />apt-get autoclean apt会把已装或已卸的软件都备份在硬盘上,所以如果需要空间的话,可以让这个命令来删除你已经删掉的软件<br />apt-get clean 这个命令会把安装的软件的备份也删除,不过这样不会影响软件的使用的。<br />apt-get upgrade——更新所有已安装的软件包<br />apt-get dist-upgrade——将系统升级到新版本<br />apt-cache search string——在软件包列表中搜索字符串<br />dpkg -l package-name-pattern——列出所有与模式相匹配的软件包。如果您不知道软件包的全名,您可以使用“<em>package-name-pattern</em>”。<br />aptitude——详细查看已安装或可用的软件包。与apt-get类似,aptitude可以通过命令行方式调用,但仅限于某些命令——最常见的有安装和卸载命令。由于aptitude比apt-get了解更多信息,可以说它更适合用来进行安装和卸载。<br />apt-cache showpkg pkgs——显示软件包信息。<br />apt-cache dumpavail——打印可用软件包列表。<br />apt-cache show pkgs——显示软件包记录,类似于dpkg –print-avail。<br />apt-cache pkgnames——打印软件包列表中所有软件包的名称。<br />dpkg -S file——这个文件属于哪个已安装软件包。<br />dpkg -L package——列出软件包中的所有文件。<br />apt-file search filename——查找包含特定文件的软件包(不一定是已安装的),这些文件的文件名中含有指定的字符串。apt-file是一个独立的软件包。您必须 先使用apt-get install来安装它,然后运行apt-file update。如果apt-file search filename输出的内容太多,您可以尝试使用apt-file search filename | grep -w filename(只显示指定字符串作为完整的单词出现在其中的那些文件名)或者类似方法,例如:apt-file search filename | grep /bin/(只显示位于诸如/bin或/usr/bin这些文件夹中的文件,如果您要查找的是某个特定的执行文件的话,这样做是有帮助的)。</p><p><span class=“wp_key<a href=” http:=“” www.it165.net=“” edu=“” ebg=“” “=”" target=“_blank”>wordlink_affiliate">ubuntu查看版本命令<br />方法一:<br />在终端中执行下列指令: cat /etc/issue<br />方法二:<br />使用 lsb_release 命令也可以查看 Ubuntu 的版本号,与方法一相比,内容更为详细。<br />执行指令如下: sudo lsb_release -a<br />方法三:<br />打开“系统监视器”,选择“系统”<br />Ubuntu查看版本命令</p><ol><li>lshw<br />lshw命令显示详细硬件信息。<br />如果要用概要方式显示,可以加上short参数:lshw-short<br />要显示指定硬件信息,加上class(或C)参数:lshw -classmemory</li><li>sysstat<br />监测系统性能及效率的一组工具,这些工具对于我们收集系统性能数据,<br />比如CPU使用率、硬盘和网络吞吐数据。</li><li>lspci -v (相比cat/proc/pci更直观)<br />查看PCI信息,lspci 是读取 hwdata 数据库。</li><li>uname -a<br />查看系统体系结构。</li><li>dmidecode<br />查看硬件信息,包括bios、cpu、内存等信息</li><li>dmesg<br />显示内核缓冲区系统控制信息,如系统启动时的信息会写到/var/log/。<br />注:dmesg 工具并不是专门用来查看硬件芯片组标识的工具,<br />但通过这个工具能让我们知道机器中的硬件的一些参数;因为系统在启动的时候,<br />会写一些硬件相关的日志到 /var/log/message* 或/var/log/boot* 文件中。</li><li>lshal 和hal-device-manager</li><li>查看 /proc<br />对于“/proc”中文件可使用文件查看命令浏览其内容,文件中包含系统特定信息:<br />Cpuinfo 主机CPU信息<br />Dma 主机DMA通道信息<br />Filesystems 文件系统信息<br />Interrupts 主机中断信息<br />Ioprots 主机I/O端口号信息<br />Meninfo 主机内存信息<br />Version Linux内存版本信息<br />查看CPU信息:cat /proc/cpuinfo 查看板卡信息:cat /proc/pci 查看内存信息:cat/proc/meminfo 查看USB设备:cat /proc/bus/usb/devices 查看键盘和鼠标:cat/proc/bus/input/devices 查看各设备的中断请求(IRQ):cat/proc/interrupts<br />主板信息:<br />sudo demidecode | grep -i ‘serial number’</li></ol><p>CPU信息:<br />cat /proc/cpuinfo<br />dmesg | grep -i ‘cpu’<br />sudo dmidecode -t processor</p><p>硬盘信息:<br />查看分区情况:<br />sudo fdisk -l</p><p>查看大小情况:<br />df -h</p><p>查看使用情况:<br />du -h<br />sudo hdparm -I /dev/sda<br />dmesg | grep sda</p><p>内存信息:<br />cat /proc/meminfo<br />dmesg | grep mem<br />free -m<br />vmstat<br />sudo dmidecode | grep -i mem</p><p>网卡信息:<br />dmesg | grep -i ‘eth’<br />lspci | grep -i ‘eth’</p><p>ethtool -i eht0<br />ethhool -k eth0<br />ethtool -g eth0</p><p>查看鼠标和键盘:<br />cat /proc/bus/input/devices</p><p>查看各设备的中断请求(IRQ):<br />cat /proc/interrupts</p><p>显卡信息:<br />lspci | grep -i ‘VGA’<br />dmesg | grep -i ‘VGA’</p><p>声卡信息:<br />查看声卡型号:<br />lspci | grep -i audio</p><p>查看型号ac97的声卡驱动模块:<br />modprobe -l | grep ac97</p><p>查看声卡信息:<br />cat /proc/asound/cards</p><p>查看alsa-utils本:<br />alsactl -v</p><p>查看内核alsa版本:<br />cat /proc/asound/version</p><p>声卡信息:<br />aplay -l</p><p>硬件信息之声卡:<br />sudo lshw -C sound</p><p>模块状态之声音:<br />lsmod | grep -i snd</p><p>alsa音频配置:<br />alsamixer</p><p>其他命令:<br />dmesg<br />lspci<br />mpstat(先安装sysstat: sudo spt-get install sysstat)</p><p><a href="https://blog.csdn.net/chuanyu/article/details/46611793">参考链接</a></p>]]></content>
<categories>
<category> linux </category>
<category> system </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux修改时区</title>
<link href="/2020/08/17/linux%E4%BF%AE%E6%94%B9%E6%97%B6%E5%8C%BA/"/>
<url>/2020/08/17/linux%E4%BF%AE%E6%94%B9%E6%97%B6%E5%8C%BA/</url>
<content type="html"><![CDATA[<p>在Linux系统中修改时区。</p><span id="more"></span><h2 id="ubuntu"><a class="markdownIt-Anchor" href="#ubuntu"></a> Ubuntu</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">date -R # 查看时区,结尾+8000是中国北京时区</span><br></pre></td></tr></table></figure><h3 id="tzselect"><a class="markdownIt-Anchor" href="#tzselect"></a> tzselect</h3><p>修改时区使用 <code>tzselect</code> 命令。</p><p>修改完之后,执行如下命令复制文件。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime</span><br></pre></td></tr></table></figure><h3 id="timedatectl"><a class="markdownIt-Anchor" href="#timedatectl"></a> timedatectl</h3><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">timedatectl set-timezone Asia/Shanghai</span><br></pre></td></tr></table></figure><h3 id="修改日期和时间"><a class="markdownIt-Anchor" href="#修改日期和时间"></a> 修改日期和时间</h3><figure class="highlight plaintext"><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">sudo date -s MM/DD/YY //修改日期</span><br><span class="line">sudo date -s hh:mm:ss //修改时间</span><br></pre></td></tr></table></figure><p>修改时间以后,修改硬件CMOS的时间</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo hwclock --systohc</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> linux </category>
<category> timezone </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux开启ftp服务</title>
<link href="/2020/08/16/linux%E5%BC%80%E5%90%AFftp%E6%9C%8D%E5%8A%A1/"/>
<url>/2020/08/16/linux%E5%BC%80%E5%90%AFftp%E6%9C%8D%E5%8A%A1/</url>
<content type="html"><![CDATA[<p>在linux服务器上开启ftp服务。</p><span id="more"></span><h2 id="ubuntu"><a class="markdownIt-Anchor" href="#ubuntu"></a> Ubuntu</h2><p>使用的软件: vsftpd</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install vsftpd</span><br></pre></td></tr></table></figure><p>需要配置的文件: <code>/etc/vsftpd.conf</code></p><p>首先备份一下该文件,然后创建新配置文件,并输入以下内容。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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></pre></td><td class="code"><pre><span class="line">listen=NO</span><br><span class="line">listen_ipv6=YES</span><br><span class="line">anonymous_enable=NO</span><br><span class="line">local_enable=YES</span><br><span class="line">write_enable=YES</span><br><span class="line">local_umask=022</span><br><span class="line">dirmessage_enable=YES</span><br><span class="line">use_localtime=YES</span><br><span class="line">xferlog_enable=YES</span><br><span class="line">connect_from_port_20=YES</span><br><span class="line">chroot_local_user=YES</span><br><span class="line">secure_chroot_dir=/var/run/vsftpd/empty</span><br><span class="line">pam_service_name=vsftpd</span><br><span class="line">rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem</span><br><span class="line">rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key</span><br><span class="line">ssl_enable=NO</span><br><span class="line">pasv_enable=Yes # 打开被动模式</span><br><span class="line">pasv_min_port=10000 # 被动模式的端口</span><br><span class="line">pasv_max_port=10100 # 被动模式的端口</span><br><span class="line">allow_writeable_chroot=YES # 必须要有</span><br></pre></td></tr></table></figure><p>操作服务</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo service vsftpd start/restart/stop</span><br></pre></td></tr></table></figure><p>使用该机器上的任意帐户登录即可,登录即到自己的用户帐户下。</p><p>关于ftp的两种工作模式:被动模式(PASV方式,passive)和主动模式(PORT方式)。</p><p><strong>必须用被动模式!!!</strong></p><p>FTP是仅基于TCP的服务,不支持UDP。默认情况下FTP协议使用TCP端口中的 20和21这两个端口,一个数据端口和一个命令端口(也可叫做控制端口),也就是20号端口用于传输数据,21号端口用于传输控制信息。但是,是否使用20作为传输数据的端口与FTP使用的传输模式有关,如果采用主动模式,那么数据传输端口就是20;如果采用被动模式,则具体最终使用哪个端口要服务器端和客户端协商决定。这就是主动与被动FTP的最大不同之处。</p><ul><li>命令连接:当FTP客户端需要登陆到FTP服务器上的时候,服务器与客户端需要进行一系列的身份验证过程,这个过程就叫做命令连接。</li><li>数据连接:如果此时客户端需要往FTP服务器上上传或者下载文件的话,就需要在客户端与服务器端再建立一条额外的数据传输连接。</li></ul><ol><li>主动模式。FTP客户端从任意的非特殊的端口(N >1024)连入到FTP服务器的命令端口——21端口。然后客户端在N+1端口监听,并且通过该N+1端口发送PORT命令给FTP服务器,接着服务器会从它自己的数据端口(20)连接到客户端指定的数据端口(N+1)。在主动传输模式下,FTP的数据连接和控制连接的方向是相反的,也就是说:是客户端向服务器建立控制连接,服务器向客户端建立数据连接,其中,客户端的控制连接和数据连接的端口号是大于1024的两个端口号(临时端口),而FTP服务器的数据端口为20,控制端口为21。</br></br>主动方式FTP的主要问题实际上在于客户端。FTP的客户端并没有实际建立一个到服务器数据端口的连接,它只是简单地告诉服务器自己监听的端口号,服务器再回来连接客户端这个指定的端口。<strong>对于客户端的防火墙来说,这是从外部系统建立到内部客户端的连接,这是通常会被阻塞的。</strong></li></ol><ul><li>C:N -> S:21</li><li>connection success</li><li>C open port N+1</li><li>C:N+1 -> CMD: PORT -> S:21</li><li>S:20 -> C:N+1</li></ul><ol start="2"><li>被动模式。在被动方式FTP中,命令连接和数据连接都由客户端发起,只要求服务器端产生一个监听相应端口的进程,这样就可以解决从服务器到客户端的数据端口的入方向连接被防火墙过滤掉的问题。<br /></br></br>当开启一个FTP连接时,客户端随机打开一个大于1024的本地端口N向服务器的21号端口发起连接,同时会开启N+1号端口。然后向服务器提交 PASV命令,通知服务器自己处于被动模式。那么服务器收到命令后就会开启一个任意的非特权端口(P > 1024)监听,并发送PORT P命令给客户端通知自己的数据端口是P。然后客户端通过本地端口N+1连接到服务器的端口P的连接用来传送数据。在被动模式下,FTP的数据连接和控制连接的方向都是一致的,也就是说:是客户端向服务器发起一个用于数据传输的连接,客户端的连接端口是发起这个数据连接请求时使用的端口。客户端的控制连接和数据连接的端口号是大于1024的两个端口号(临时端口),而服务器端的数据端口是临时端口,而不一定是常规的20。</li></ol><ul><li>C:N -> S:21</li><li>connection success</li><li>C open port N+1</li><li>C:N -> CMD: PASV -> S:21</li><li>S open random port P(P>1024)</li><li>S:21 -> port P -> C:N</li><li>C:N+1 -> S:P</li></ul><p><a href="https://www.linuxidc.com/Linux/2018-08/153491.htm">参考链接 - 配置</a></p><p><a href="https://blog.csdn.net/qq_16038125/article/details/72851142">参考链接 - 被动与主动</a></p><p><a href="https://blog.csdn.net/wumenglu1018/article/details/54233826">参考链接 - 被动与主动</a></p><p><a href="https://blog.csdn.net/u010154760/article/details/45458219">参考链接 - 被动与主动</a></p>]]></content>
<categories>
<category> linux </category>
<category> ftp </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux配置wifi</title>
<link href="/2020/08/16/linux%E9%85%8D%E7%BD%AEwifi/"/>
<url>/2020/08/16/linux%E9%85%8D%E7%BD%AEwifi/</url>
<content type="html"><![CDATA[<p>linux系统中配置wifi上网。</p><span id="more"></span><h2 id="ubuntu"><a class="markdownIt-Anchor" href="#ubuntu"></a> Ubuntu</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">首先安装这俩东西</span></span><br><span class="line">sudo apt-get install wpasupplicant</span><br><span class="line">sudo apt-get install network-manager</span><br></pre></td></tr></table></figure><p>使用 <code>ifconfig</code> 命令查看wifi网卡是否存在,不存在的话,执行下面命令</p><figure class="highlight shell"><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">sudo apt-get update # 尽可能使用Ubuntu的原始软件源</span><br><span class="line">sudo apt install broadcom-sta-dkms</span><br></pre></td></tr></table></figure><p>安装wifi网卡之后,重启电脑,使用 <code>ifconfig</code> 命令查看wifi网卡名称。</p><p>修改文件 <code>/etc/netplan/50-cloud-init.yaml</code> ,如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><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></pre></td><td class="code"><pre><span class="line">network:</span><br><span class="line"> renderer: NetworkManager // 网络管理渲染器</span><br><span class="line"> ethernets:</span><br><span class="line"> enp2s0:</span><br><span class="line"> addresses:</span><br><span class="line"> - 192.168.2.9/24</span><br><span class="line"> dhcp4: false</span><br><span class="line"> gateway4: 192.168.2.1</span><br><span class="line"> nameservers:</span><br><span class="line"> addresses: []</span><br><span class="line"> search: []</span><br><span class="line"> wifis: // 这里是wifi网卡的配置</span><br><span class="line"> wlp3s0:</span><br><span class="line"> addresses:</span><br><span class="line"> - 192.168.2.10/24</span><br><span class="line"> dhcp4: false</span><br><span class="line"> gateway4: 192.168.2.1</span><br><span class="line"> nameservers:</span><br><span class="line"> addresses: []</span><br><span class="line"> search: []</span><br><span class="line"> access-points:</span><br><span class="line"> "无线网络名称":</span><br><span class="line"> password: '无线网络密码'</span><br><span class="line"> wlp3s1:</span><br><span class="line"> dhcp4: true</span><br><span class="line"> access-points:</span><br><span class="line"> "feixun_458BB5": // 第一行是wifi名称</span><br><span class="line"> password: "987654321" // 第二行是wifi密码</span><br><span class="line"> "4G_CPE_39E1":</span><br><span class="line"> password: "sscz090619"</span><br><span class="line"> "kr's samsung":</span><br><span class="line"> password: "45880222" </span><br><span class="line"> version: 2</span><br></pre></td></tr></table></figure><p>修改文件之后,执行如下命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo netplan try # Try to apply a new netplan config to running system, with automatic rollback</span><br><span class="line">sudo netplan generate # Generate backend specific configuration files from</span><br><span class="line">sudo netplan apply # Apply current netplan config to running system</span><br></pre></td></tr></table></figure><p><a href="https://www.cnblogs.com/free-ys/p/10162388.html">参考链接-wifi</a></p><p><a href="https://netplan.io/examples/">参考链接-netplan</a></p>]]></content>
<categories>
<category> linux </category>
<category> wifi </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux压缩文件</title>
<link href="/2020/08/16/linux%E5%8E%8B%E7%BC%A9%E6%96%87%E4%BB%B6/"/>
<url>/2020/08/16/linux%E5%8E%8B%E7%BC%A9%E6%96%87%E4%BB%B6/</url>
<content type="html"><![CDATA[<p>linux中的压缩和解压缩</p><span id="more"></span><table><thead><tr><th>后缀</th><th>压缩</th><th>解压缩</th></tr></thead><tbody><tr><td>.rar</td><td><code>rar a FileName.rar DirName</code></td><td><code>rar x FileName.rar</code></td></tr><tr><td>.zip</td><td><code>zip FileName.zip DirName</code></td><td><code>unzip FileName.zip</code></td></tr><tr><td>.tar.bz</td><td></td><td><code>tar jxvf FileName.tar.bz</code></td></tr><tr><td>.tar.gz & .tgs</td><td><code>tar zcvf FileName.tar.gz DirName</code></td><td><code>tar zxvf FileName.tar.gz</code></td></tr><tr><td>.gz</td><td><code>gzip FileName</code></td><td><code>gzip -d FileName.gz</code></td></tr></tbody></table>]]></content>
<categories>
<category> linux </category>
<category> compress </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux挂载U盘</title>
<link href="/2020/08/16/linux%E6%8C%82%E8%BD%BDU%E7%9B%98/"/>
<url>/2020/08/16/linux%E6%8C%82%E8%BD%BDU%E7%9B%98/</url>
<content type="html"><![CDATA[<p>在linux服务器上使用命令挂载和卸载U盘</p><span id="more"></span><h2 id="ubuntu"><a class="markdownIt-Anchor" href="#ubuntu"></a> Ubuntu</h2><h3 id="mount"><a class="markdownIt-Anchor" href="#mount"></a> mount</h3><p>命令</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mount [-t vfstype] [-o options] device dir</span><br></pre></td></tr></table></figure><table><thead><tr><th>cmd</th><th>描述</th><th>详细</th></tr></thead><tbody><tr><td>-t vfstype</td><td>指定文件系统的类型,通常不必指定。mount 会自动选择正确的类型。</td><td>常用类型有:光盘或光盘镜像:iso9660;</br>DOS fat16文件系统:msdos;</br>Windows 9x fat32文件系统:vfat;</br>Windows NT ntfs文件系统:ntfs;</br>Mount Windows文件网络共享:smbfs;</br>UNIX(LINUX) 文件网络共享:nfs;</td></tr><tr><td>-o options</td><td>描述设备或档案的挂接方式</td><td>常用的参数有: loop:用来把一个文件当成硬盘分区挂接上系统;</br>ro:采用只读方式挂接设备;</br>rw:采用读写方式挂接设备;</br>iocharset:指定访问文件系统所用字符集;</td></tr><tr><td>device</td><td>要挂接(mount)的设备</td><td>使用<code>fdisk -l</code>来查询</td></tr><tr><td>dir</td><td>设备在系统上的挂接点</td><td></td></tr></tbody></table><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">sudo fdisk -l # 查看硬盘分区情况,根据硬盘大小找到U盘</span><br><span class="line"></span><br><span class="line">mkdir -p /mnt/usb # 创建挂载点,挂载完成后,U盘里面的内容在这里显示</span><br><span class="line"></span><br><span class="line">mount -t vfat /dev/sdd1 /mnt/usb # 把U盘设备 /dev/sdd1 挂载到挂载点上</span><br><span class="line"></span><br><span class="line">mount -t vfat -o iocharset=cp936 /dev/sdd1 /mnt/usb # 如果中文名不显示或者为乱码</span><br></pre></td></tr></table></figure><p><a href="https://www.jb51.net/os/RedHat/1109.html">参考链接</a></p><h3 id="umount"><a class="markdownIt-Anchor" href="#umount"></a> umount</h3><p>命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">umount [-ahnrvV][-t <文件系统类型>][文件系统]</span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>说明</th><th>详细</th></tr></thead><tbody><tr><td>-r</td><td>若无法成功卸除,则尝试以只读的方式重新挂入文件系统。</td><td></td></tr><tr><td>-v</td><td>执行时显示详细的信息。</td><td></td></tr><tr><td>-l</td><td>执行延迟卸载</td><td>延迟卸载(lazy unmount)会立即卸载目录树里的文件系统,等到设备不再繁忙时才清理所有相关资源</td></tr></tbody></table><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><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">umount -v /mnt/mymount/ # 通过挂载点卸载 </span><br><span class="line">umount -v /dev/sda1 # 通过设备名卸载 </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">如果遇到设备繁忙的问题</span></span><br><span class="line">lsof | grep mymount # 查找mymount分区里打开的文件 </span><br><span class="line">umount -vl /mnt/mymount/ # 执行延迟卸载 </span><br></pre></td></tr></table></figure><p><a href="http://www.linuxso.com/command/umount.html">参考链接</a></p>]]></content>
<categories>
<category> linux </category>
<category> mount </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>linux合盖电源设置</title>
<link href="/2020/08/16/linux%E5%90%88%E7%9B%96%E7%94%B5%E6%BA%90%E8%AE%BE%E7%BD%AE/"/>
<url>/2020/08/16/linux%E5%90%88%E7%9B%96%E7%94%B5%E6%BA%90%E8%AE%BE%E7%BD%AE/</url>
<content type="html"><![CDATA[<p>笔记本安装linux服务器关闭盖子不休眠。</p><span id="more"></span><h2 id="ubuntu"><a class="markdownIt-Anchor" href="#ubuntu"></a> Ubuntu</h2><p>配置文件: <code>/etc/systemd/logind.conf</code></p><p>配置说明:</p><ul><li>#HandlePowerKey按下电源键后的行为,默认power off</li><li>#HandleSleepKey 按下挂起键后的行为,默认suspend</li><li>#HandleHibernateKey按下休眠键后的行为,默认hibernate</li><li>#HandleLidSwitch合上笔记本盖后的行为,默认suspend(改为ignore;即合盖不休眠)在原文件中,还要去掉前面的#</li></ul><p>我的做法是,把以上内容全部修改为 <code>ignore</code></p>]]></content>
<categories>
<category> linux </category>
<category> power </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>leetcode0030</title>
<link href="/2020/08/11/leetcode0030/"/>
<url>/2020/08/11/leetcode0030/</url>
<content type="html"><![CDATA[<p>leetcode 0030 串联所有单词的子串:滑动窗口</p><span id="more"></span><ol><li>unordered_map<string, int><ul><li>判断是否存在某个key,unodr_map.find(key) != unodr_map.end()</li></ul></li><li>auto 类型推导<ul><li>遍历vector: for (auto x:words) {}</li></ul></li><li>vector<ul><li>初始化<ul><li>vector<int> f(n, 1);</li><li>vector<int> f(n);</li><li>vector<int> f = {1, 2, 3};</li><li>vector<int> f(v.begin(), v.end());</li><li>vector<int> f; f = vector<int>(n, 10); // 先声明再初始化</li><li>vector<int> f; f.resize(10); // 先声明再初始化</li><li>vector<vector<int>> f(n, vector<int>(n, 10)); // 先声明再初始化</li></ul></li><li>去重<ul><li>#include<set> set<int>s(v.begin(), v.end()); v.assign(s.begin(), s.end());</li></ul></li></ul></li><li>滑动窗口<ul><li>如果当前子串在words中不存在,则将窗口 head 和 tail 指向新的位置,继续匹配。</li><li>如果当前子串在words中存在(可能已经匹配完一个,也可能没有匹配完,因为子串的出现次数超过了words中存在的数量),则将窗口 head 往后移动一个单词长度,继续匹配。</li><li>外部总循环,只需要循环一个单词长度即可,因为只需要以第一个单词长度内的位置作为起始位置,然后后面的循环中会按照上面两步执行</li></ul></li></ol><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function">vector<<span class="type">int</span>> <span class="title">findSubstring</span><span class="params">(string s, vector<string>& words)</span> </span>{</span><br><span class="line"> vector<<span class="type">int</span>> result;</span><br><span class="line"> <span class="type">int</span> ls = s.<span class="built_in">length</span>();</span><br><span class="line"> <span class="keyword">if</span> (!words.<span class="built_in">size</span>() || !ls) <span class="keyword">return</span> result;</span><br><span class="line"> <span class="type">int</span> lw = words[<span class="number">0</span>].<span class="built_in">length</span>();</span><br><span class="line"> unordered_map<string, <span class="type">int</span>> map, tempmap;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">auto</span> &s:words) map[s]++;</span><br><span class="line"> tempmap = map;</span><br><span class="line"> <span class="function">vector<<span class="type">bool</span>> <span class="title">flag</span><span class="params">(ls, <span class="literal">false</span>)</span></span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < lw; i++){ <span class="comment">// 这里最开始我写的是 ls,结果总是超时,改成 lw ok。</span></span><br><span class="line"> <span class="keyword">if</span>(lw*words.<span class="built_in">size</span>() > ls-i) <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">if</span>(flag[i]) <span class="keyword">continue</span>;</span><br><span class="line"> string word = s.<span class="built_in">substr</span>(i, lw);</span><br><span class="line"> tempmap = map;</span><br><span class="line"> <span class="type">int</span> count = <span class="number">0</span>, j = i, k = i;</span><br><span class="line"> <span class="keyword">while</span> (k+words.<span class="built_in">size</span>()*lw <= ls && !flag[k]){</span><br><span class="line"> <span class="keyword">while</span> (tempmap[word]><span class="number">0</span>) {</span><br><span class="line"> tempmap[word]--;</span><br><span class="line"> count++;</span><br><span class="line"> j+=lw;</span><br><span class="line"> <span class="keyword">if</span> (j > ls) <span class="keyword">break</span>;</span><br><span class="line"> word = s.<span class="built_in">substr</span>(j, lw);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (count == words.<span class="built_in">size</span>()) {</span><br><span class="line"> result.<span class="built_in">push_back</span>(k);</span><br><span class="line"> flag[k] = <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (tempmap.<span class="built_in">find</span>(word) != tempmap.<span class="built_in">end</span>()){</span><br><span class="line"> tempmap[s.<span class="built_in">substr</span>(k, lw)]++;</span><br><span class="line"> count--;</span><br><span class="line"> k += lw;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> flag[k] = <span class="literal">true</span>;</span><br><span class="line"> k = j = j+lw;</span><br><span class="line"> tempmap = map;</span><br><span class="line"> word = s.<span class="built_in">substr</span>(k, lw);</span><br><span class="line"> count = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> leetcode </category>
</categories>
<tags>
<tag> leetcode </tag>
</tags>
</entry>
<entry>
<title>linux server 挂载U盘</title>
<link href="/2020/08/10/linux-server-%E6%8C%82%E8%BD%BDU%E7%9B%98/"/>
<url>/2020/08/10/linux-server-%E6%8C%82%E8%BD%BDU%E7%9B%98/</url>
<content type="html"><![CDATA[<span id="more"></span>]]></content>
</entry>
<entry>
<title>ssh登陆密钥警告</title>
<link href="/2020/08/09/ssh%E7%99%BB%E9%99%86%E5%AF%86%E9%92%A5%E8%AD%A6%E5%91%8A/"/>
<url>/2020/08/09/ssh%E7%99%BB%E9%99%86%E5%AF%86%E9%92%A5%E8%AD%A6%E5%91%8A/</url>
<content type="html"><![CDATA[<p>使用ssh时出现警告: <em>WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!</em></p><p>警告信息中会有公钥文件的位置信息,打开之后,删除掉对应ip和port的条目,再重新ssh</p>]]></content>
<categories>
<category> ssh </category>
</categories>
<tags>
<tag> ssh </tag>
</tags>
</entry>
<entry>
<title>linux网络操作</title>
<link href="/2020/08/04/linux%E7%BD%91%E7%BB%9C%E6%93%8D%E4%BD%9C/"/>
<url>/2020/08/04/linux%E7%BD%91%E7%BB%9C%E6%93%8D%E4%BD%9C/</url>
<content type="html"><![CDATA[<p>关于 linux 的一些网络操作。</p><span id="more"></span><p>下面是几个常用的命令来查看网络信息</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">ifconfig <span class="comment"># 查看网卡</span></span><br><span class="line"></span><br><span class="line">netstat -rn <span class="comment"># 查看路由表,可以看到网关和子网掩码</span></span><br><span class="line"></span><br><span class="line">arp -n <span class="comment"># 查看近期的网络链接缓存,如果最近有其他ip访问你这台机器,那执行该命令的输出结果中就包含该ip的相关信息</span></span><br><span class="line"></span><br><span class="line">ifquery -a --list <span class="comment"># 列出所有的网卡名称</span></span><br><span class="line"></span><br><span class="line">traceroute IP地址 <span class="comment"># 连接到ip地址,需要经过的路由。</span></span><br></pre></td></tr></table></figure><p>关于Ubuntu桌面版进行网络配置的注意事项:</p><ol><li>因为是桌面版,所以增加了network-manager来执行可视化的网络管理(就是在桌面UI中管理网络配置),配置文件是那个 <code>/etc/NetworkManager/NetworkManager.conf</code>,操作服务是 <code>service network-manager restart</code>;</li><li>同时在命令行中依旧存在着管理网络的方式,配置文件是<code>/etc/network/interfaces</code>,操作服务是<code>service networking retart</code>。</li><li>所以说,如果两个类型的网络管理服务出现了冲突,那么Ubuntu采用的处理方式是,以network-manager的配置为准,在network-manager一直负责网络配置的过程中,修改<code>/etc/network/interfaces</code>是没有意义的,所以如果想使用<code>/etc/network/interfaces</code>的配置,就需要让network-manager摆脱对网络配置的管理(直接stop掉network-manager,或者修改network-manager的配置文件managed子项为false,在下面有详细命令)。</li></ol><p>以下是对网络进行配置的相关操作(适用于ubuntu 16,ubuntu 18)</p><figure class="highlight bash"><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></pre></td><td class="code"><pre><span class="line">/etc/NetworkManager/NetworkManager.conf <span class="comment"># network-manager服务的配置文件,修改managed子项,从true改为false,可以关闭网络桌面管理工具对网络配置管理</span></span><br><span class="line"><span class="comment"># managed=false</span></span><br><span class="line"></span><br><span class="line">sudo service network-manager restart <span class="comment"># 重启网络桌面管理工具,会发现右上角的网络链接出现了问题。</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 以上两步也可以不做,可以直接关闭 network-manager</span></span><br><span class="line"><span class="comment"># sudo service network-manager stop</span></span><br><span class="line"><span class="comment"># 然后再使用下面的interfaces从命令行配置网络</span></span><br><span class="line"></span><br><span class="line">/etc/network/interfaces <span class="comment"># 网络配置文件</span></span><br><span class="line"><span class="comment"># auto lo</span></span><br><span class="line"><span class="comment"># iface lo inet loopback</span></span><br><span class="line"><span class="comment"># 上面的是文件本身自带的,下面的是自己添加的</span></span><br><span class="line"><span class="comment"># auto ens33</span></span><br><span class="line"><span class="comment"># iface ens33 inet static</span></span><br><span class="line"><span class="comment"># address 192.168.5.133 地址</span></span><br><span class="line"><span class="comment"># netmask 255.255.255.0 子网掩码</span></span><br><span class="line"><span class="comment"># gateway 192.168.5.1 网关</span></span><br><span class="line"></span><br><span class="line">sudo ip addr flush dev 网卡名 <span class="comment"># 刷新ip地址</span></span><br><span class="line"></span><br><span class="line">sudo service networking restart <span class="comment"># 重启所有网卡,看下service文件就是使用的 ifup 命令</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>刷新ip地址的时候必须要注意,修改网络配置文件之后或者恢复network-manager接管必须执行这个,否则不会生效,需要重启才能使修改后的网络配置文件生效。</strong></p><p>查看一下<code>networking.service</code>的源码,可以发现本质上<code>networking</code>命令就是调用了<code>if up/down 网卡名</code>。</p><p><img data-src="network-service.jpg" alt="networking.service" /></p>]]></content>
<categories>
<category> linux </category>
<category> network </category>
</categories>
<tags>
<tag> network </tag>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>ubuntu18部署gitlab</title>
<link href="/2020/08/04/ubuntu18%E9%83%A8%E7%BD%B2gitlab/"/>
<url>/2020/08/04/ubuntu18%E9%83%A8%E7%BD%B2gitlab/</url>
<content type="html"><![CDATA[<p>部署私人git服务器</p><span id="more"></span><ol><li><p>安装gitlab还挺占存储空间的,主要是 <code>/</code> 目录下的空间,大概要允出 2 个多G的空间。</p></li><li><p>另外一个就是找个网络不错的地方,要下载 800+M 的archives。</p></li><li><p>服务器内存要足够大,大概要8个G左右(之前虚拟机配置了4个G内存,依旧不能运行成功)。</p></li></ol><h2 id="安装"><a class="markdownIt-Anchor" href="#安装"></a> 安装</h2><figure class="highlight bash"><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">sudo apt-get update</span><br><span class="line">sudo apt-get install -y curl openssh-server ca-certificates</span><br><span class="line">sudo apt-get install -y postfix</span><br><span class="line">curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash</span><br><span class="line"><span class="built_in">export</span> EXTERNAL_URL=<span class="string">"http://本机IP地址"</span> </span><br><span class="line">sudo apt-get install gitlab-ee</span><br><span class="line"><span class="comment"># 指定版本</span></span><br><span class="line"><span class="comment"># sudo apt-get install gitlab-ee=版本</span></span><br></pre></td></tr></table></figure><blockquote><p>具体版本查看: <a href="!https://packages.gitlab.com/gitlab/gitlab-ee">https://packages.gitlab.com/gitlab/gitlab-ee</a></p></blockquote><p>如果EXTERNAL_URL配置错误,就修改文件 <code>/etc/gitlab/gitlab.rb</code> 中的EXTERNAL_URL,然后执行下面的命令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitlab-ctl reconfigure</span><br></pre></td></tr></table></figure><h2 id="gitlab-ctl基本操作"><a class="markdownIt-Anchor" href="#gitlab-ctl基本操作"></a> gitlab-ctl基本操作</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gitlab-ctl start/stop/restart/status/reconfigure</span><br></pre></td></tr></table></figure><h2 id="查看gitlab版本"><a class="markdownIt-Anchor" href="#查看gitlab版本"></a> 查看gitlab版本</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> /opt/gitlab/embedded/service/gitlab-rails/VERSION</span><br></pre></td></tr></table></figure><h2 id="卸载gitlab"><a class="markdownIt-Anchor" href="#卸载gitlab"></a> 卸载gitlab</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo apt remove gitlab-ee</span><br><span class="line">sudo pkill -f gitlab</span><br><span class="line">sudo <span class="built_in">rm</span> -rf /etc/gitlab</span><br><span class="line">sudo <span class="built_in">rm</span> -rf /var/opt/gitlab</span><br><span class="line">sudo <span class="built_in">rm</span> -rf /opt/gitlab</span><br></pre></td></tr></table></figure><h2 id="迁移服务器内容"><a class="markdownIt-Anchor" href="#迁移服务器内容"></a> 迁移服务器内容</h2><p>直接参考官网链接来弄: <a href="!https://docs.gitlab.com/ee/raketasks/backup_restore.html">https://docs.gitlab.com/ee/raketasks/backup_restore.html</a></p><h2 id="tips"><a class="markdownIt-Anchor" href="#tips"></a> Tips</h2><ol><li>clone的时候,如果使用<code>git@****</code>,那么链接的是服务器的22端口,所以服务器防火墙要开放22端口</li><li>同样是clone的时候,当然不限于clone操作,都会要求密码,所以说需要在你的git账户里添加ssh_key,<code>ssh-keygen -t rsa -b 2048 -C "[email protected]" </code></li></ol>]]></content>
<categories>
<category> gitlab </category>
</categories>
<tags>
<tag> gitlab </tag>
</tags>
</entry>
<entry>
<title>leetcode0114</title>
<link href="/2020/08/02/leetcode0114/"/>
<url>/2020/08/02/leetcode0114/</url>
<content type="html"><![CDATA[<p>leetcode 0114 心得</p><span id="more"></span><p>自己的做法:先调换顺序,再把右子树搞成链,并获取链尾指针,然后把左子树添加到链尾,再返回新的链尾</p><figure class="highlight c++"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">flatten</span><span class="params">(TreeNode* root)</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"> <span class="function">TreeNode* <span class="title">deal</span><span class="params">(TreeNode* root)</span></span>;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Solution::flatten</span><span class="params">(TreeNode* root)</span></span>{</span><br><span class="line"> <span class="keyword">this</span>-><span class="built_in">deal</span>(root);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function">TreeNode* <span class="title">Solution::deal</span><span class="params">(TreeNode* root)</span></span>{</span><br><span class="line"> <span class="keyword">if</span> (!root) <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"> <span class="comment">// swap left and right</span></span><br><span class="line"> <span class="keyword">if</span> (root->left){ <span class="comment">// 如果左边没有子树,那就不需要调整;只有有左子树的时候,才需要和右子树上交换,然后把右子树调整到它的下面去,从而保证顺序顺序</span></span><br><span class="line"> TreeNode *temp = root->right;</span><br><span class="line"> root->right = root->left;</span><br><span class="line"> root->left = temp;</span><br><span class="line"> }</span><br><span class="line"> TreeNode *righttail = <span class="keyword">this</span>-><span class="built_in">deal</span>(root->right); <span class="comment">// 先处理右子树,搞成一条链,并返回链的末尾,然后把左子树连接到末尾。</span></span><br><span class="line"> <span class="keyword">if</span> (!righttail) <span class="keyword">return</span> root; <span class="comment">// 最终找到的末尾是NULL,所以要返回NULL的父节点。</span></span><br><span class="line"> righttail->right = root->left;</span><br><span class="line"> root->left = <span class="literal">NULL</span>; <span class="comment">// 把左子树连接到右子树链的末尾之后,左子树要置空。</span></span><br><span class="line"> TreeNode *lefttail = <span class="keyword">this</span>-><span class="built_in">deal</span>(righttail->right); <span class="comment">//把左子树也搞成一条链。</span></span><br><span class="line"> <span class="keyword">if</span> (!lefttail) <span class="keyword">return</span> righttail; <span class="comment">// 最终找到的末尾是NULL,所以要返回NULL的父节点</span></span><br><span class="line"> <span class="keyword">return</span> lefttail; <span class="comment">// 返回tail节点</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>在题解里面看到了更简洁的做法。</p><figure class="highlight c++"><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="keyword">class</span> <span class="title class_">Solution</span> {</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">flatten</span><span class="params">(TreeNode* root)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(!root || (!root->left && !root->right)) <span class="keyword">return</span>; <span class="comment">// 到达叶子节点</span></span><br><span class="line"> <span class="built_in">flatten</span>(root->left);</span><br><span class="line"> <span class="built_in">flatten</span>(root->right);</span><br><span class="line"> TreeNode *right = root->right; <span class="comment">// 先保存原右子树</span></span><br><span class="line"> root->right = root->left; <span class="comment">// 把原左子树移到右边</span></span><br><span class="line"> root->left = <span class="literal">nullptr</span>; <span class="comment">// 把现左子树置空</span></span><br><span class="line"> TreeNode *cur = root;</span><br><span class="line"> <span class="keyword">while</span>(cur->right) cur = cur->right; <span class="comment">// 找到现右子树的末尾</span></span><br><span class="line"> cur->right = right; <span class="comment">// 因为左右子树在递归的过程中,都已经成为链,所以只需要简单的添加到现右子树末尾即可。</span></span><br><span class="line"> }</span><br><span class="line">};</span><br></pre></td></tr></table></figure><p>比较了一下两种解法,我的是属于先调换顺序(其实调换顺序这里可以直接把左子树放到右边,右子树放到temp存着,而不用放到),把右子树搞成链,然后把左子树添加到右子树末尾,再把左子树搞成链;而题解里的做法是先把左右子树都搞成链,然后调换顺序,找到右子树的末尾,把左子树拼接上去。</p><p>从题解里面又深入理解了递归的意义:每一部分的递归都是求解子问题,然后对于当前的问题,考虑如何把已经求解成功的子问题拼接在一起,考虑如何处理叶子节点(也就是边界)。</p>]]></content>
<categories>
<category> ACM </category>
<category> leetcode </category>
</categories>
<tags>
<tag> leetcode </tag>
<tag> ACM </tag>
</tags>
</entry>
<entry>
<title>python生成器与迭代器</title>
<link href="/2020/08/01/python%E7%94%9F%E6%88%90%E5%99%A8%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8/"/>
<url>/2020/08/01/python%E7%94%9F%E6%88%90%E5%99%A8%E4%B8%8E%E8%BF%AD%E4%BB%A3%E5%99%A8/</url>
<content type="html"><![CDATA[<p>区分python中生成器与迭代器</p><span id="more"></span><p>可迭代对象(Iterable)不是迭代器(Iterator)。</p><p>生成器(generator)。</p><p>可用于for循环的数据类型:</p><ol><li>for, list, str, dict等</li><li>generator</li></ol><p>统称为 Iterable(可迭代的对象),实现了__iter__()函数</p><p>迭代器既实现了__iter__(),有实现了__next__()的对象被称作迭代器</p><p>把Iterable对象变成Iterator,可以使用iter([1, 2, 3])函数</p><p>yield的典例:</p><figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">实现斐波那契数。</span></span><br><span class="line"><span class="string">若想获得generator函数的返回值,必须抛异常,用e.value获取返回值</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">fib</span>(<span class="params"><span class="built_in">max</span></span>):</span><br><span class="line"> n,a,b =<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span></span><br><span class="line"> <span class="keyword">while</span> n < <span class="built_in">max</span>:</span><br><span class="line"> <span class="keyword">yield</span> b</span><br><span class="line"> a,b =b,a+b</span><br><span class="line"> n = n+<span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> <span class="string">'done'</span></span><br><span class="line">g = fib(<span class="number">6</span>)</span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> x = <span class="built_in">next</span>(g)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">'generator: '</span>,x)</span><br><span class="line"> <span class="keyword">except</span> StopIteration <span class="keyword">as</span> e:</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"生成器返回值:"</span>,e.value)</span><br><span class="line"> <span class="keyword">break</span></span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="string">生产者消费者模式。</span></span><br><span class="line"><span class="string">只有调用next()函数的时候,才执行generator函数</span></span><br><span class="line"><span class="string">"""</span></span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">def</span> <span class="title function_">consumer</span>(<span class="params">name</span>):</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"%s 准备学习啦!"</span> %name)</span><br><span class="line"> <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"> lesson = <span class="keyword">yield</span></span><br><span class="line"> </span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"开始[%s]了,[%s]老师来讲课了!"</span> %(lesson,name))</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">producer</span>(<span class="params">name</span>):</span><br><span class="line"> c = consumer(<span class="string">'A'</span>)</span><br><span class="line"> c2 = consumer(<span class="string">'B'</span>)</span><br><span class="line"> c.__next__()</span><br><span class="line"> c2.__next__()</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"同学们开始上课 了!"</span>)</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">10</span>):</span><br><span class="line"> time.sleep(<span class="number">1</span>)</span><br><span class="line"> <span class="built_in">print</span>(<span class="string">"到了两个同学!"</span>)</span><br><span class="line"> c.send(i)</span><br><span class="line"> c2.send(i)</span><br></pre></td></tr></table></figure>]]></content>
</entry>
<entry>
<title>restful与传统接口的区别</title>
<link href="/2020/08/01/restful%E4%B8%8E%E4%BC%A0%E7%BB%9F%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%8C%BA%E5%88%AB/"/>
<url>/2020/08/01/restful%E4%B8%8E%E4%BC%A0%E7%BB%9F%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%8C%BA%E5%88%AB/</url>
<content type="html"><![CDATA[<p>restful与传统api接口的区别</p><span id="more"></span><p>示例:一个状态数据操作接口</p><p><strong>传统模式:</strong></p><p>api/getstate.aspx - 获取状态信息</p><p>api/updatestate.aspx - 更新状态信息</p><p>api/deletestate.aspx - 删除该状态的数据</p><p><strong>RESTful模式:</strong></p><p>api/state 只需要这一个接口</p><p>GET 方式请求 api/state - 获取该状态的数据</p><p>POST 方式请求 api/state - 更新该状态的数据</p><p>DELETE 方式请求 api/state - 删除该状态的数据</p>]]></content>
</entry>
<entry>
<title>linux自定义服务</title>
<link href="/2020/08/01/linux%E8%87%AA%E5%AE%9A%E4%B9%89%E6%9C%8D%E5%8A%A1/"/>
<url>/2020/08/01/linux%E8%87%AA%E5%AE%9A%E4%B9%89%E6%9C%8D%E5%8A%A1/</url>
<content type="html"><![CDATA[<p>在linux系统中自定义 service 并设置开机启动。</p><span id="more"></span><blockquote><p><em><strong>Tip:</strong></em> SELinux prevents you from running a system service where the binary is in a user’s home directory, or in your case, the root user’s home directory. To fix the problem, copy the binary to a proper directory such as /usr/local/bin and call it from there.<br /><br/><br /><em><strong>Source</strong>: <a href="https://serverfault.com/questions/957084/failed-at-step-exec-spawning-permission-denied">https://serverfault.com/questions/957084/failed-at-step-exec-spawning-permission-denied</a></em></p></blockquote><p>service 文件存放在 <code>/usr/lib/systemd/system/</code> 文件夹下</p><p>示例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line">Description=Frp Server Service</span><br><span class="line">After=network.target</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line">Type=simple</span><br><span class="line">User=nobody</span><br><span class="line">Restart=on-failure</span><br><span class="line">RestartSec=5s</span><br><span class="line">ExecStart=/usr/bin/frps_start.sh</span><br><span class="line">ExecReload=/usr/bin/frps_reload.sh</span><br><span class="line">ExecStop=/usr/bin/frps_stop.sh</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line">WantedBy=multi-user.target</span><br></pre></td></tr></table></figure><p>关于开机启动</p><figure class="highlight bash"><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">systemctl <span class="built_in">enable</span> servicename <span class="comment"># 开机启动</span></span><br><span class="line">systemctl <span class="built_in">disable</span> servicename <span class="comment"># 关闭开机启动</span></span><br><span class="line">systemctl list-units --<span class="built_in">type</span>=service <span class="comment"># 列出已经启动的服务</span></span><br></pre></td></tr></table></figure><p>详细参考: <a href="https://www.cnblogs.com/wutao666/p/9781567.html">https://www.cnblogs.com/wutao666/p/9781567.html</a></p>]]></content>
<categories>
<category> linux </category>
<category> service </category>
</categories>
<tags>
<tag> linux </tag>
</tags>
</entry>
<entry>
<title>物理机安装操作系统</title>
<link href="/2020/08/01/%E7%89%A9%E7%90%86%E6%9C%BA%E5%AE%89%E8%A3%85%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/"/>
<url>/2020/08/01/%E7%89%A9%E7%90%86%E6%9C%BA%E5%AE%89%E8%A3%85%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/</url>
<content type="html"><![CDATA[<p>在物理机上安装win10和linux(ubuntu, centos)操作系统</p><span id="more"></span><h2 id="linux"><a class="markdownIt-Anchor" href="#linux"></a> linux</h2><p>对于linux系统,使用 <code>ultraIso</code> 烧录到U盘中进行安装,分四个区</p><table><thead><tr><th style="text-align:center">分区</th><th style="text-align:left">大小</th><th style="text-align:left">备注</th></tr></thead><tbody><tr><td style="text-align:center">/</td><td style="text-align:left">/home区的一半吧</td><td style="text-align:left">安装系统软件的地方</td></tr><tr><td style="text-align:center">/boot</td><td style="text-align:left">几百兆就行,我一般用一两个G</td><td style="text-align:left">用于启动</td></tr><tr><td style="text-align:center">/swap</td><td style="text-align:left">和内存一样大</td><td style="text-align:left">内存交换</td></tr><tr><td style="text-align:center">/home</td><td style="text-align:left">剩下的</td><td style="text-align:left">用户分区,存储用户的内容</td></tr></tbody></table><h2 id="win10"><a class="markdownIt-Anchor" href="#win10"></a> win10</h2><p>对于win10系统,微软官方给出了安装工具,<a href="https://www.microsoft.com/zh-cn/software-download/windows10">点击这里</a></p><p>打开开发者工具,打开手机模式,可以看到win10 iso镜像文件的选择项</p><p>使用鲁大师安装驱动。</p><p>比较糟心的是office和visio的安装类型要保持一致。</p><p>使用kms来破解win10和office。</p>]]></content>
<categories>
<category> linux </category>
<category> win10 </category>
</categories>
<tags>
<tag> linux </tag>
<tag> win10 </tag>
</tags>