-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1666 lines (1272 loc) · 221 KB
/
index.html
File metadata and controls
1666 lines (1272 loc) · 221 KB
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- PACE Progress Bar START -->
<script src="/js/pace.min.js"></script>
<link rel="stylesheet" href="https://github.com/HubSpot/pace/raw/master/themes/orange/pace-theme-flash.css">
<!-- PACE Progress Bar START -->
<title>Hexo</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:type" content="website">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:locale" content="zh-CN">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Hexo">
<link rel="alternate" href="/atom.xml" title="Hexo" type="application/atom+xml">
<link rel="icon" href="/css/images/favicon.ico">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Montserrat:700" rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic" rel="stylesheet" type="text/css">
<link href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
<style type="text/css">
@font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/9749f0/00000000000000000001008f/27/l?subset_id=2&fvd=n5) format("woff2");font-weight:500;font-style:normal;}
@font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/90cf9f/000000000000000000010091/27/l?subset_id=2&fvd=n7) format("woff2");font-weight:500;font-style:normal;}
@font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/8a5494/000000000000000000013365/27/l?subset_id=2&fvd=n4) format("woff2");font-weight:lighter;font-style:normal;}
@font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/d337d8/000000000000000000010095/27/l?subset_id=2&fvd=i4) format("woff2");font-weight:400;font-style:italic;}</style>
<link rel="stylesheet" id="athemes-headings-fonts-css" href="//fonts.googleapis.com/css?family=Yanone+Kaffeesatz%3A200%2C300%2C400%2C700&ver=4.6.1" type="text/css" media="all">
<link rel="stylesheet" href="/css/style.css">
<script src="/js/jquery-3.1.1.min.js"></script>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="/css/bootstrap.css" >
<link rel="stylesheet" href="/css/hiero.css" >
<link rel="stylesheet" href="/css/glyphs.css" >
<link rel="stylesheet" href="/css/vdonate.css" >
<!-- Custom CSS -->
<link rel="stylesheet" href="/css/my.css">
<!-- Google Adsense -->
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<script>
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: "ca-pub-0123456789ABCDEF",
enable_page_level_ads: true
});
</script>
</head>
<script>
var themeMenus = {};
themeMenus["/"] = "首页";
themeMenus["/archives"] = "归档";
themeMenus["/categories"] = "分类";
themeMenus["/tags"] = "标签";
themeMenus["/about"] = "关于";
</script>
<body>
<header id="allheader" class="site-header" role="banner">
<div class="clearfix container">
<div class="site-branding">
<h1 class="site-title">
<a href="/" title="Hexo" rel="home"> Hexo </a>
</h1>
<nav id="main-navigation" class="main-navigation" role="navigation">
<a class="nav-open">Menu</a>
<a class="nav-close">Close</a>
<div class="clearfix sf-menu">
<ul id="main-nav" class="nmenu sf-js-enabled">
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/">首页</a> </li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/archives">归档</a> </li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/categories">分类</a> </li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/tags">标签</a> </li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/about">关于</a> </li>
</ul>
</div>
</nav>
</div>
</div>
</header>
<div id="originBgDiv" style="background: #fff; width: 100%;">
<div style="max-height:600px; overflow: hidden; display: flex; display: -webkit-flex; align-items: center;">
<img id="originBg" width="100%" alt="" src="">
</div>
</div>
<script>
function setAboutIMG(){
var imgUrls = "css/images/pose.jpg,https://source.unsplash.com/collection/954550/1920x1080".split(",");
var random = Math.floor((Math.random() * imgUrls.length ));
if (imgUrls[random].startsWith('http') || imgUrls[random].indexOf('://') >= 0) {
document.getElementById("originBg").src=imgUrls[random];
} else {
document.getElementById("originBg").src='/' + imgUrls[random];
}
}
bgDiv=document.getElementById("originBgDiv");
if(location.pathname.match('about')){
setAboutIMG();
bgDiv.style.display='block';
}else{
bgDiv.style.display='none';
}
</script>
<div id="container">
<div id="wrap">
<div id="content" class="outer">
<section id="main">
<article id="post-虚拟货币的认识" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/06/11/虚拟货币的认识/" class="article-date">
<time datetime="2018-06-11T09:21:56.696Z" itemprop="datePublished">六月 11, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="虚拟货币的认识"><a href="#虚拟货币的认识" class="headerlink" title="虚拟货币的认识"></a>虚拟货币的认识</h1><p>##初识比特币</p>
<p> 比特币的出现确实是一个挑战时代底线的一个新鲜事物,它几乎颠覆了人民的传统观念,我刚开始接触它的时候非常抵触,当慢慢地融入到这个圈里,并开始学习真正的区块链,看了很多这方面的书籍和研究比特币及以太坊的源码,了解了大家常说的“去中心化”,“分布式”,“P2P交易”,“数据加密”,”数字签名”,“公链”,“私链”等等,以及炒币词汇,如“割韭菜”,“梭哈”,“割肉”,“代币”,“法币”,“庄家”,“挖矿”等等。更是通过炒币巨亏,使自己变得更加强大了,而且自己已经变成了一个虚拟货币的信仰者。</p>
<p>##简单介绍学习和研究的东西</p>
<p>1.去中心化:存储数据到足够多的节点上,而且这些存储的数据是一样的,这样就保证了数据的一致性。如果想更改数据,那么理论上你需要更改超过51%的节点上的数据,那么所有节点将会改变原来的数据,更改成功。可是你想改变超过51%的节点数据根本不可能,成本不可估算。这就是区块链数据的不可篡改性,也就是去中心化。</p>
<p>2.挖矿:挖矿的共识算法主要有pow,pos,dpos。现在大部分挖矿算法是pow。按比特币分析:比特币的总量是2100万个。原理是每隔大约10分钟产生一个区块,也就是每次产生一个区块需要耗时10分钟左右。在这个产生新区块的10分钟时间内。这个10分钟的来源就是挖矿的时间。现在挖矿难度是生成的有效hash值前面满足19个0,当然这个难度值是变化的,总体保证挖矿时间维持在10分钟左右。同时挖矿的奖励每隔4年减半1次。在这挖矿的10分中内有很多笔交易需要打包,这些交易有之前的也有现在正在产生的。通过一些算法考量这些打包好的数据哪些先被放到区块里,哪些继续留在交易池里。挖矿时间开始,那么数据将停止存储,运用sha256加密方法给当前区块进行hash运算,一直得到有效hash值,标志着该区块成为有效的区块,也就是挖矿出来的新的区块。将该区块存储到区块链上。</p>
<p> 3.P2P交易:这个很容易理解,就是用户之间进行的交易,不存在什么中介,中间转移。1对1交易。</p>
<p> 4.数据加密:类型有对称加密和非对称加密。对称加密就是可以对明文加密成密文,也可以将密文解密成明文,也就是公钥加密,私钥解密。往往用在数据签名验签,传输文件,存储数据等。非对称加密主要用在生成钱包上面,如下边解析:<br> 创建一个钱包地址<br> 1)生成一对公钥和私钥<br> 2)想要获取地址,可以通过公钥进行Base58编码<br> 3)想要别人给我转账,把地址给别人,对地址进行反编码,变成公钥。将公钥和数据进行签名<br> 4)通过私钥进行解密,解密是单方向的,只有拥有私钥的人才能解密</p>
<p>5.分布式账本:目前eos拥有21个超级节点,目的是更快的存储和同步数据。这21个超级节点谁成为主节点的顺序是随机的,为的是防止他们篡改数据。每个超级节点自己本身是自己覆盖区域的主节点,其他节点向其递交数据,当递交的数据超过51%的节点都有存储后,该数据才有效,那么主节点存储该数据,同时不断给那些没存储该数据的节点发送信号,让它更新数据,保证和主节点数据一致。</p>
<p>6.公链,私链,联盟链:公有链是指全世界任何人都可读取的、任何人都能发送交易且交易能获得有效确认的、任何人都能参与其中共识过程的区块链——共识过程决定哪个区块可被添加到区块链中和明确当前状态。公有链通常被认为是“完全去中心化”的。私有链是公司内部或者社团内部使用的区块链。联盟链也就是约定好的几家公司或社团内部使用的区块链。<br> 公有链:对所有人开放,任何人都可以参与;<br> 联盟链:对特定的组织团体开放;<br> 私有链:对单独的个人或实体开放。</p>
<p>7.区块链层级结构:整体结构包括有6个,包括数据层,网络层,共识层,激励层,合约层,应用层。其中数据层,网络层,共识层是构建区块链技术的必要元素,这三个缺少任何一层,都不能成为真正意义上的区块链技术。另外三层则在不同项目,可以各不相同。激励层就是设计激励政策,鼓励用户参与到区块链生态中;合约层一般指“智能合约”,它是一套可以自动执行,随意编写的合约体系。应用层就是区块链上的应用程序,与手机系统上的app类似。</p>
<p>##对初链的了解</p>
<p>通过浏览初链白皮书和黄皮书,感觉项目整体很不错,深入运用区块链技术,将部分应用部署在平台上。初链团队是一个靠谱的团队,通过这次活动集结区块链人才,集思广益,定有很好的未来。</p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-分布式终端与go编程添加和删除节点" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/29/分布式终端与go编程添加和删除节点/" class="article-date">
<time datetime="2018-05-29T12:38:20.142Z" itemprop="datePublished">五月 29, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="分布式终端与go编程添加和删除节点"><a href="#分布式终端与go编程添加和删除节点" class="headerlink" title="分布式终端与go编程添加和删除节点"></a>分布式终端与go编程添加和删除节点</h1><p>##1.首先在终端执行起来一个节点<br>./etcd –name htcd0 –initial-advertise-peer-urls <a href="http://127.0.0.1:2380" target="_blank" rel="noopener">http://127.0.0.1:2380</a> –listen-peer-urls <a href="http://127.0.0.1:2380" target="_blank" rel="noopener">http://127.0.0.1:2380</a> –listen-client-urls tp://127.0.0.1:2379 –advertise-client-urls <a href="http://127.0.0.1:2379" target="_blank" rel="noopener">http://127.0.0.1:2379</a> –initial-cluster-token etcd-cluster-1 –initial-cluster cd0=<a href="http://127.0.0.1:2380,cd1=http://127.0.0.1:2480,cd2=http://127.0.0.1:2580" target="_blank" rel="noopener">http://127.0.0.1:2380,cd1=http://127.0.0.1:2480,cd2=http://127.0.0.1:2580</a> –initial-cluster-state new<br>上边的127.0.0.1:2380是终端执行的节点url<br>而127.0.0.1:2379的节点是2380端口节点要监听的节点。</p>
<p>为上边的执行命令做个解析:<br>–name<br>etcd集群中的节点名,这里可以随意,可区分且不重复就行<br>–listen-peer-urls<br>监听的用于节点之间通信的url,可监听多个,集群内部将通过这些url进行数据交互(如选举,数据同步等)<br>–initial-advertise-peer-urls<br>建议用于节点之间通信的url,节点间将以该值进行通信。<br>–listen-client-urls<br>监听的用于客户端通信的url,同样可以监听多个。<br>–advertise-client-urls<br>建议使用的客户端通信url,该值用于etcd代理或etcd成员与etcd节点通信。<br>–initial-cluster-token etcd-cluster-1<br>节点的token值,设置该值后集群将生成唯一id,并为每个节点也生成唯一id,当使用相同配置文件再启动一个集群时,只要该token值不一样,etcd集群就不会相互影响。<br>–initial-cluster<br>也就是集群中所有的initial-advertise-peer-urls 的合集<br>–initial-cluster-state new<br>新建集群的标志,初始化状态使用 new,建立之后改此值为 existing</p>
<p>##2.再在终端开启2个节点,组成一个集群<br>./etcd –name cd1 –initial-advertise-peer-urls <a href="http://127.0.0.1:2480" target="_blank" rel="noopener">http://127.0.0.1:2480</a> –listen-peer-urls <a href="http://127.0.0.1:2480" target="_blank" rel="noopener">http://127.0.0.1:2480</a> –listen-client-urls <a href="http://127.0.0.1:2479" target="_blank" rel="noopener">http://127.0.0.1:2479</a> –advertise-client-urls <a href="http://127.0.0.1:2479" target="_blank" rel="noopener">http://127.0.0.1:2479</a> –initial-cluster-token etcd-cluster-1 –initial-cluster cd0=<a href="http://127.0.0.1:2380,cd1=http://127.0.0.1:2480,cd2=http://127.0.0.1:2580" target="_blank" rel="noopener">http://127.0.0.1:2380,cd1=http://127.0.0.1:2480,cd2=http://127.0.0.1:2580</a> –initial-cluster-state new<br>这段命令是添加第二个节点,也可以通过go编程添加节点,只不过要用2479这个url通讯<br>./etcd –name cd2 –initial-advertise-peer-urls <a href="http://127.0.0.1:2580" target="_blank" rel="noopener">http://127.0.0.1:2580</a> –listen-peer-urls <a href="http://127.0.0.1:2580" target="_blank" rel="noopener">http://127.0.0.1:2580</a> –listen-client-urls <a href="http://127.0.0.1:2579" target="_blank" rel="noopener">http://127.0.0.1:2579</a> –advertise-client-urls <a href="http://127.0.0.1:2579" target="_blank" rel="noopener">http://127.0.0.1:2579</a> –initial-cluster-token etcd-cluster-1 –initial-cluster cd0=<a href="http://127.0.0.1:2380,cd1=http://127.0.0.1:2480,cd2=http://127.0.0.1:2580" target="_blank" rel="noopener">http://127.0.0.1:2380,cd1=http://127.0.0.1:2480,cd2=http://127.0.0.1:2580</a> –initial-cluster-state new<br>执行第三个节点,用2579通讯</p>
<p>##3.查询 member 列表</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">export ETCDCTL_API=3</span><br><span class="line">ENDPOINTS=127.0.0.1:2379,127.0.0.1:2479,127.0.0.1:2579</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<p>##4.添加 member 节点</p>
<p><strong>member add</strong> 添加节点</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member add cd3 --peer-urls=http://127.0.0.1:2180</span><br><span class="line">Member b9057cfdc8ff17ce added to cluster 9da8cd75487bd6dc</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ETCD_NAME="cd3"</span><br><span class="line">ETCD_INITIAL_CLUSTER="cd2=http://127.0.0.1:2580,cd3=http://127.0.0.1:2180,cd0=http://127.0.0.1:2380,cd1=http://127.0.0.1:2480"</span><br><span class="line">ETCD_INITIAL_ADVERTISE_PEER_URLS="http://127.0.0.1:2180"</span><br><span class="line">ETCD_INITIAL_CLUSTER_STATE="existing"</span><br></pre></td></tr></table></figure>
<p><strong>查询 member 节点列表信息</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">b9057cfdc8ff17ce, unstarted, , http://127.0.0.1:2180, </span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<p>通过查询结果可以发现:<code>http://127.0.0.1:2180</code> 显示状态为:<code>unstarted</code> </p>
<p><strong>启动新节点</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcd --name cd3 --listen-client-urls http://127.0.0.1:2179 --advertise-client-urls http://127.0.0.1:2179 --listen-peer-urls http://127.0.0.1:2180 --initial-advertise-peer-urls http://127.0.0.1:2180 --initial-cluster-state existing --initial-cluster cd2=http://127.0.0.1:2580,cd0=http://127.0.0.1:2380,cd3=http://127.0.0.1:2180,cd1=http://127.0.0.1:2480 --initial-cluster-token etcd-cluster-1</span><br></pre></td></tr></table></figure>
<p><strong>查询 member 节点列表信息</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">b9057cfdc8ff17ce, started, cd3, http://127.0.0.1:2180, http://127.0.0.1:2179</span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<p>##5.删除 member</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member remove 21a304d74d267837</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Member b9057cfdc8ff17ce removed from cluster 9da8cd75487bd6dc</span><br></pre></td></tr></table></figure>
<p><strong>查询 member 节点列表信息</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<p>##6.</p>
<h2 id="添加-member-节点"><a href="#添加-member-节点" class="headerlink" title="添加 member 节点"></a>添加 member 节点</h2><p><strong>member add</strong> 添加节点</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member add cd3 --peer-urls=http://127.0.0.1:2180</span><br><span class="line">Member b9057cfdc8ff17ce added to cluster 9da8cd75487bd6dc</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ETCD_NAME="cd3"</span><br><span class="line">ETCD_INITIAL_CLUSTER="cd2=http://127.0.0.1:2580,cd3=http://127.0.0.1:2180,cd0=http://127.0.0.1:2380,cd1=http://127.0.0.1:2480"</span><br><span class="line">ETCD_INITIAL_ADVERTISE_PEER_URLS="http://127.0.0.1:2180"</span><br><span class="line">ETCD_INITIAL_CLUSTER_STATE="existing"</span><br></pre></td></tr></table></figure>
<p><strong>查询 member 节点列表信息</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">b9057cfdc8ff17ce, unstarted, , http://127.0.0.1:2180, </span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<p>通过查询结果可以发现:<code>http://127.0.0.1:2180</code> 显示状态为:<code>unstarted</code> </p>
<p><strong>启动新节点</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcd --name cd3 --listen-client-urls http://127.0.0.1:2179 --advertise-client-urls http://127.0.0.1:2179 --listen-peer-urls http://127.0.0.1:2180 --initial-advertise-peer-urls http://127.0.0.1:2180 --initial-cluster-state existing --initial-cluster cd2=http://127.0.0.1:2580,cd0=http://127.0.0.1:2380,cd3=http://127.0.0.1:2180,cd1=http://127.0.0.1:2480 --initial-cluster-token etcd-cluster-1</span><br></pre></td></tr></table></figure>
<p><strong>查询 member 节点列表信息</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">b9057cfdc8ff17ce, started, cd3, http://127.0.0.1:2180, http://127.0.0.1:2179</span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<h2 id="删除-member"><a href="#删除-member" class="headerlink" title="删除 member"></a>删除 member</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member remove 21a304d74d267837</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Member b9057cfdc8ff17ce removed from cluster 9da8cd75487bd6dc</span><br></pre></td></tr></table></figure>
<p><strong>查询 member 节点列表信息</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">98f0c6bf64240842, started, cd2, http://127.0.0.1:2580, http://127.0.0.1:2579</span><br><span class="line">bf9071f4639c75cc, started, cd0, http://127.0.0.1:2380, http://127.0.0.1:2379</span><br><span class="line">e3ba87c3b4858ef1, started, cd1, http://127.0.0.1:2480, http://127.0.0.1:2479</span><br></pre></td></tr></table></figure>
<p>##7.执行go程序代码,增加或者删除节点<br>package main</p>
<p>import (<br> “github.com/coreos/etcd/clientv3”<br> “context”<br> “fmt”<br> “time”<br>)</p>
<p>//通过代码向网络添加和删除节点,配置这台电脑的url和超时保护<br>var (<br> dialTimeout=5<em>time.Second<br> requestTimeout=2</em>time.Second<br> endPoints=[]string{“127.0.0.1:2379”}<br>)</p>
<p>//添加节点<br>func addMember(cli *clientv3.Client,url string) {<br> peerURLs:=[]string {url}<br> //向系统中插入节点<br> _,err:=cli.MemberAdd(context.Background(),peerURLs)<br> if err!=nil{<br> fmt.Println(“memberadd”,err)<br> }<br> //显示插入的节点<br> resp,err:=cli.MemberList(context.Background())<br> if err!=nil{<br> fmt.Println(“memberlist”,err)<br> }<br> fmt.Println(“添加后的members为”,resp.Members)</p>
<p>}<br>func main() {<br> //运行之前终端先开启一个节点,再执行下边的代码,来链接终端那侧的节点,链接后这个cli其实就是个中介的角色,下边再进行给创建及删除节点,<br> //新建的节点与终端执行的节点组成集群。<br> cli,err:=clientv3.New(clientv3.Config{<br> Endpoints:endPoints,<br> DialTimeout:dialTimeout,<br> })<br> if err!=nil{<br> fmt.Println(“clientv3 new”,err)<br> }</p>
<pre><code>fmt.Println("cli.Cluster:",cli)
defer cli.Close()
//添加新节点
addMember(cli,"127.0.0.1:2180")
addMember(cli,"127.0.0.1:2181")
addMember(cli,"127.0.0.1:2182")
//删除节点
//delMember(cli,0xe32088547caa8215)
</code></pre><p>}<br>//删除节点<br>func delMember(cli *clientv3.Client,memberId uint64) {<br> _,err:=cli.MemberRemove(context.Background(),memberId)<br> if err!=nil{<br> fmt.Println(“delMember”,err)<br> }else {<br> fmt.Printf(“删除节点%s成功了\n”,memberId)<br> }<br>}</p>
<p>执行go编程创建的节点连接到集群,但是处于unstarted的状态<br>执行完 添加节点,需要打开终端启动节点服务器<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./etcd --name cd3 --listen-client-urls http://127.0.0.1:2179 --advertise-client-urls http://127.0.0.1:2179 --listen-peer-urls http://127.0.0.1:2180 --initial-advertise-peer-urls http://127.0.0.1:2180 --initial-cluster-state existing --initial-cluster cd2=http://127.0.0.1:2580,cd0=http://127.0.0.1:2380,cd3=http://127.0.0.1:2180,cd1=http://127.0.0.1:2480 --initial-cluster-token etcd-cluster-1</span><br></pre></td></tr></table></figure></p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-分布式" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/29/分布式/" class="article-date">
<time datetime="2018-05-29T01:37:01.622Z" itemprop="datePublished">五月 29, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="分布式"><a href="#分布式" class="headerlink" title="分布式"></a>分布式</h1><p>##etcd - 一个分布式一致性键值存储系统</p>
<p>etcd是一个分布式一致性键值存储系统,用于共享配置和服务发现,专注于:</p>
<ul>
<li><p>简单:良好定义的,面向用户的API (gRPC)</p>
</li>
<li><p>安全: 带有可选客户端证书认证的自动TLS</p>
</li>
<li><p>快速:测试验证,每秒10000写入</p>
</li>
<li><p>可靠:使用Raft适当分布</p>
</li>
</ul>
<p>etcd是Go编写,并使用Raft一致性算法来管理高可用复制日志,架构如下图所示:</p>
<h3 id="下载安装"><a href="#下载安装" class="headerlink" title="下载安装"></a>下载安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">//新建文件coreos</span><br><span class="line">$ mkdir -p $GOPATH/src/github.com/coreos</span><br><span class="line">//进到coreos目录下</span><br><span class="line">$ cd coreos</span><br><span class="line">$ git clone https://github.com/coreos/etcd.git</span><br><span class="line">$ cd etcd</span><br><span class="line">$ ./build</span><br><span class="line">$ ./bin/etcd</span><br></pre></td></tr></table></figure>
<p>另外一种下载安装的方法:</p>
<p>直接下载etcd二进制 (包含etcd、etcdctl)<br><a href="https://github.com/coreos/etcd/releases" target="_blank" rel="noopener">https://github.com/coreos/etcd/releases</a></p>
<h3 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">//进入到coreos下的etcd目录下</span><br><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd</span><br><span class="line">//执行之前编译的etcd</span><br><span class="line">$ ./bin/etcd</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//新开一个终端</span><br><span class="line">//进入etcd目录下</span><br><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd</span><br><span class="line">$ ETCDCTL_API=3 ./bin/etcdctl put foo bar</span><br><span class="line"></span><br><span class="line"># 输出结果显示OK,表示安装成功</span><br><span class="line">OK</span><br></pre></td></tr></table></figure>
<h3 id="搭建本地集群"><a href="#搭建本地集群" class="headerlink" title="搭建本地集群"></a>搭建本地集群</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">//安装多进程管理工具</span><br><span class="line">$ go get github.com/mattn/goreman</span><br><span class="line"></span><br><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd</span><br><span class="line">$ goreman -f Procfile start</span><br></pre></td></tr></table></figure>
<p>查看本地集群的服务器列表</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">$ cd $GOPATH/src/github.com/coreos/etcd</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl member list</span><br><span class="line"></span><br><span class="line"># 显示结果</span><br><span class="line"></span><br><span class="line">8211f1d0f64f3269: name=infra1 peerURLs=http://127.0.0.1:12380 clientURLs=http://127.0.0.1:2379 isLeader=false</span><br><span class="line">91bc3c398fb3c146: name=infra2 peerURLs=http://127.0.0.1:22380 clientURLs=http://127.0.0.1:22379 isLeader=true</span><br><span class="line">fd422379fda50e48: name=infra3 peerURLs=http://127.0.0.1:32380 clientURLs=http://127.0.0.1:32379 isLeader=false</span><br></pre></td></tr></table></figure>
<h3 id="存储数据"><a href="#存储数据" class="headerlink" title="存储数据"></a>存储数据</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">export ETCDCTL_API=3</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl put foo "Hello World"</span><br><span class="line"></span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl get foo</span><br><span class="line"></span><br><span class="line">foo</span><br><span class="line">Hello World!</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl --write-out="json" get foo</span><br><span class="line"></span><br><span class="line">{"header":{"cluster_id":17237436991929493444,"member_id":9372538179322589801,"revision":2,"raft_term":2},"kvs":[{"key":"Zm9v","create_revision":2,"mod_revision":2,"version":1,"value":"SGVsbG8gV29ybGQh"}],"count":1}</span><br></pre></td></tr></table></figure>
<h3 id="根据前缀查询"><a href="#根据前缀查询" class="headerlink" title="根据前缀查询"></a>根据前缀查询</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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><br><span class="line">$ ./bin/etcdctl put web1 value1</span><br><span class="line">$ ./bin/etcdctl put web2 value2</span><br><span class="line">$ ./bin/etcdctl put web3 value3</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl get web --prefix</span><br><span class="line"></span><br><span class="line">web1</span><br><span class="line">value1</span><br><span class="line">web2</span><br><span class="line">value2</span><br><span class="line">web3</span><br><span class="line">value3</span><br></pre></td></tr></table></figure>
<h3 id="删除数据"><a href="#删除数据" class="headerlink" title="删除数据"></a>删除数据</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">$ ./bin/etcdctl put key myvalue</span><br><span class="line">$ ./bin/etcdctl del key</span><br><span class="line">1</span><br><span class="line">$ ./bin/etcdctl get key</span><br><span class="line">// 查询结果为空</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl put k1 value1</span><br><span class="line">$ ./bin/etcdctl put k2 value2</span><br><span class="line">$ ./bin/etcdctl del k --prefix</span><br><span class="line">2</span><br><span class="line">$ ./bin/etcdctl get k --prefix</span><br><span class="line">// 查询结果为空</span><br></pre></td></tr></table></figure>
<h3 id="事务写入"><a href="#事务写入" class="headerlink" title="事务写入"></a>事务写入</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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></pre></td><td class="code"><pre><span class="line">$ ./bin/etcdctl put user1 bad</span><br><span class="line">OK</span><br><span class="line">$ ./bin/etcdctl txn --interactive//进行事物交互</span><br><span class="line"></span><br><span class="line">compares:</span><br><span class="line">// 输入以下内容,输入结束按 两次回车</span><br><span class="line">value("user1") = "bad" </span><br><span class="line"></span><br><span class="line">//如果 user1 = bad,则执行 get user1 </span><br><span class="line">success requests (get, put, del):</span><br><span class="line">get user1</span><br><span class="line"></span><br><span class="line">//如果 user1 != bad,则执行 put user1 good</span><br><span class="line">failure requests (get, put, del):</span><br><span class="line">put user1 good</span><br><span class="line"></span><br><span class="line">// 运行结果,执行 success</span><br><span class="line">SUCCESS</span><br><span class="line"></span><br><span class="line">user1</span><br><span class="line">bad</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl txn --interactive</span><br><span class="line">compares:</span><br><span class="line">value("user1") = "111" </span><br><span class="line"></span><br><span class="line">// 如果 user1 = 111,则执行 get user1 </span><br><span class="line">success requests (get, put, del):</span><br><span class="line">get user1</span><br><span class="line"></span><br><span class="line">//如果 user1 != 111,则执行 put user1 2222</span><br><span class="line">failure requests (get, put, del):</span><br><span class="line">put user1 2222</span><br><span class="line"></span><br><span class="line">// 运行结果,执行 failure</span><br><span class="line">FAILURE</span><br><span class="line"></span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl get user1</span><br><span class="line">user1</span><br><span class="line">2222</span><br></pre></td></tr></table></figure>
<h3 id="watch"><a href="#watch" class="headerlink" title="watch"></a>watch</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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></pre></td><td class="code"><pre><span class="line">// 当 stock1 的数值改变( put 方法)的时候,watch 会收到通知</span><br><span class="line">$ ./bin/etcdctl watch stock1</span><br><span class="line"></span><br><span class="line">// 新打开终端</span><br><span class="line">$ export ETCDCTL_API=3</span><br><span class="line">$ ./bin/etcdctl put stock1 1000</span><br><span class="line"></span><br><span class="line">//在watch 终端显示</span><br><span class="line">PUT</span><br><span class="line">stock1</span><br><span class="line">1000</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl watch stock --prefix</span><br><span class="line">$ ./bin/etcdctl put stock1 10</span><br><span class="line">$ ./bin/etcdctl put stock2 20</span><br></pre></td></tr></table></figure>
<h3 id="lease-租期"><a href="#lease-租期" class="headerlink" title="lease//租期"></a>lease//租期</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">在bin目录下./bin</span><br><span class="line">$ ./etcdctl lease grant 300</span><br><span class="line"># lease 326963a02758b527 granted with TTL(300s)</span><br><span class="line"></span><br><span class="line">$ ./etcdctl put sample value -- lease=326963a02758b527</span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">$ ./etcdctl get sample</span><br><span class="line"></span><br><span class="line">$ ./etcdctl lease keep-alive 326963a02758b520</span><br><span class="line">$ ./etcdctl lease revoke 326963a02758b527//撤权</span><br><span class="line">lease 326963a02758b527 revoked</span><br><span class="line"></span><br><span class="line"># or after 300 seconds</span><br><span class="line">$ ./etcdctl get sample</span><br></pre></td></tr></table></figure>
<h3 id="Distributed-locks"><a href="#Distributed-locks" class="headerlink" title="Distributed locks"></a>Distributed locks</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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><br><span class="line">$ ./etcdctl lock mutex1</span><br><span class="line">mutex1/326963a02758b52d</span><br><span class="line"></span><br><span class="line"># 第二终端</span><br><span class="line">$ ./etcdctl lock mutex1</span><br><span class="line"></span><br><span class="line">// 当第一个终端结束了用命令control C停止,第二个终端会显示</span><br><span class="line">mutex1/326963a02758b531</span><br></pre></td></tr></table></figure>
<h3 id="Elections"><a href="#Elections" class="headerlink" title="Elections"></a>Elections</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">$ ./bin/etcdctl elect one p1</span><br><span class="line"></span><br><span class="line">one/326963a02758b539</span><br><span class="line">p1</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># another client with the same name blocks</span><br><span class="line">$ ./bin/etcdctl elect one p2</span><br><span class="line"></span><br><span class="line">//结束第一终端,第二终端显示</span><br><span class="line">one/326963a02758b53e</span><br><span class="line">p2</span><br></pre></td></tr></table></figure>
<h3 id="Cluster-status"><a href="#Cluster-status" class="headerlink" title="Cluster status"></a>Cluster status</h3><p>集群状态</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ ./bin/etcdctl --write-out=table endpoint status</span><br><span class="line"></span><br><span class="line">$ ./bin/etcdctl endpoint health</span><br></pre></td></tr></table></figure>
<h3 id="Snapshot"><a href="#Snapshot" class="headerlink" title="Snapshot"></a>Snapshot</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">./bin/etcdctl snapshot save my.db</span><br><span class="line"></span><br><span class="line">Snapshot saved at my.db</span><br><span class="line"></span><br><span class="line">./bin/etcdctl --write-out=table snapshot status my.db</span><br></pre></td></tr></table></figure>
<h3 id="Member"><a href="#Member" class="headerlink" title="Member"></a>Member</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./bin/etcdctl member list -w table</span><br></pre></td></tr></table></figure>
<p>##etcd 多台服务器集群</p>
<p>###去除缓存<br>在etcd目录下在终端执行make clean,清除缓存。</p>
<h3 id="下载安装-etcd"><a href="#下载安装-etcd" class="headerlink" title="下载安装 etcd"></a>下载安装 etcd</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir -p $GOPATH/src/github.com/coreos</span><br><span class="line">$ cd coreos</span><br><span class="line">$ git clone https://github.com/coreos/etcd.git</span><br><span class="line">$ cd etcd</span><br><span class="line">$ ./build</span><br></pre></td></tr></table></figure>
<p>###终端运行export ETCDCTL_API=3</p>
<h3 id="启动服务"><a href="#启动服务" class="headerlink" title="启动服务"></a>启动服务</h3><p>每个节点都要执行以下配置,HOST_1、HOST_2、HOST_3 分别设置为多台服务器的IP</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">TOKEN=token-01</span><br><span class="line">CLUSTER_STATE=new</span><br><span class="line">NAME_1=machine-1</span><br><span class="line">NAME_2=machine-2</span><br><span class="line">NAME_3=machine-3</span><br><span class="line">HOST_1=192.168.1.126</span><br><span class="line">HOST_2=192.168.1.119</span><br><span class="line">HOST_3=192.168.1.103</span><br><span class="line">CLUSTER=${NAME_1}=http://${HOST_1}:2380,${NAME_2}=http://${HOST_2}:2380,${NAME_3}=http://${HOST_3}:2380</span><br></pre></td></tr></table></figure>
<p><strong>machine 1</strong> 执行如下命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd/bin</span><br><span class="line"></span><br><span class="line"># For machine 1</span><br><span class="line">THIS_NAME=${NAME_1}</span><br><span class="line">THIS_IP=${HOST_1}</span><br><span class="line">./etcd --data-dir=data.etcd --name ${THIS_NAME} --initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 --advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 --initial-cluster ${CLUSTER} --initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}</span><br></pre></td></tr></table></figure>
<p><strong>machine 2</strong> 执行如下命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd/bin</span><br><span class="line"></span><br><span class="line"># For machine 2</span><br><span class="line">THIS_NAME=${NAME_2}</span><br><span class="line">THIS_IP=${HOST_2}</span><br><span class="line">./etcd --data-dir=data.etcd --name ${THIS_NAME} --initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 --advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 --initial-cluster ${CLUSTER} --initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}</span><br></pre></td></tr></table></figure>
<p><strong>machine 3</strong> 执行如下命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd/bin</span><br><span class="line"></span><br><span class="line"># For machine 3</span><br><span class="line">THIS_NAME=${NAME_3}</span><br><span class="line">THIS_IP=${HOST_3}</span><br><span class="line">./etcd --data-dir=data.etcd --name ${THIS_NAME} --initial-advertise-peer-urls http://${THIS_IP}:2380 --listen-peer-urls http://${THIS_IP}:2380 --advertise-client-urls http://${THIS_IP}:2379 --listen-client-urls http://${THIS_IP}:2379 --initial-cluster ${CLUSTER} --initial-cluster-state ${CLUSTER_STATE} --initial-cluster-token ${TOKEN}</span><br></pre></td></tr></table></figure>
<p>检测服务器运行是否正常,开启新的终端。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">$ cd $GOPATH/src/github.com/coreos/etcd/bin</span><br><span class="line"></span><br><span class="line">export ETCDCTL_API=3</span><br><span class="line">HOST_1=192.168.1.126</span><br><span class="line">HOST_2=192.168.1.119</span><br><span class="line">HOST_3=192.168.1.103</span><br><span class="line">ENDPOINTS=$HOST_1:2379,$HOST_2:2379,$HOST_3:2379</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS member list</span><br></pre></td></tr></table></figure>
<h3 id="存储数据-1"><a href="#存储数据-1" class="headerlink" title="存储数据"></a>存储数据</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS put foo "Hello World"//!号不能存</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS get foo</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS --write-out="json" get foo</span><br></pre></td></tr></table></figure>
<h3 id="根据前缀查询-1"><a href="#根据前缀查询-1" class="headerlink" title="根据前缀查询"></a>根据前缀查询</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">./etcdctl --endpoints=$ENDPOINTS put web1 value1</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put web2 value2</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put web3 value3</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS get web --prefix</span><br><span class="line"></span><br><span class="line">web1</span><br><span class="line">value1</span><br><span class="line">web2</span><br><span class="line">value2</span><br><span class="line">web3</span><br><span class="line">value3</span><br></pre></td></tr></table></figure>
<h3 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">./etcdctl --endpoints=$ENDPOINTS put key myvalue</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS del key</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put k1 value1</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put k2 value2</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS del k --prefix</span><br></pre></td></tr></table></figure>
<h3 id="事务写入-1"><a href="#事务写入-1" class="headerlink" title="事务写入"></a>事务写入</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">$ ./etcdctl --endpoints=$ENDPOINTS put user1 bad</span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">$ ./etcdctl --endpoints=$ENDPOINTS txn --interactive</span><br><span class="line"></span><br><span class="line">compares:</span><br><span class="line">// 输入以下内容,输入结束按 两次回车</span><br><span class="line">value("user1") = "bad" </span><br><span class="line"></span><br><span class="line">//如果 user1 = bad,则执行 get user1 </span><br><span class="line">success requests (get, put, del):</span><br><span class="line">get user1</span><br><span class="line"></span><br><span class="line">//如果 user1 != bad,则执行 put user1 good</span><br><span class="line">failure requests (get, put, del):</span><br><span class="line">put user1 good</span><br><span class="line"></span><br><span class="line">// 运行结果,执行 success</span><br><span class="line">SUCCESS</span><br><span class="line"></span><br><span class="line">user1</span><br><span class="line">bad</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$ ./etcdctl --endpoints=$ENDPOINTS txn --interactive</span><br><span class="line">compares:</span><br><span class="line">value("user1") = "111" </span><br><span class="line"></span><br><span class="line">// 如果 user1 = 111,则执行 get user1 </span><br><span class="line">success requests (get, put, del):</span><br><span class="line">get user1</span><br><span class="line"></span><br><span class="line">//如果 user1 != 111,则执行 put user1 2222</span><br><span class="line">failure requests (get, put, del):</span><br><span class="line">put user1 2222</span><br><span class="line"></span><br><span class="line">// 运行结果,执行 failure</span><br><span class="line">FAILURE</span><br><span class="line"></span><br><span class="line">OK</span><br><span class="line"></span><br><span class="line">$ ./etcdctl --endpoints=$ENDPOINTS get user1</span><br><span class="line">user1</span><br><span class="line">2222</span><br></pre></td></tr></table></figure>
<h3 id="watch-1"><a href="#watch-1" class="headerlink" title="watch"></a>watch</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">// 当 stock1 的数值改变( put 方法)的时候,watch 会收到通知</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS watch stock1</span><br><span class="line"></span><br><span class="line">// 新打开终端</span><br><span class="line">$ cd $GOPATH/src/github.com/coreos/etcd/bin</span><br><span class="line"></span><br><span class="line">export ETCDCTL_API=3</span><br><span class="line">HOST_1=192.168.1.126</span><br><span class="line">HOST_2=192.168.1.119</span><br><span class="line">HOST_3=192.168.1.103</span><br><span class="line">ENDPOINTS=$HOST_1:2379,$HOST_2:2379,$HOST_3:2379</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put stock1 1000</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS watch stock --prefix</span><br><span class="line"></span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put stock1 10</span><br><span class="line">./etcdctl --endpoints=$ENDPOINTS put stock2 20</span><br></pre></td></tr></table></figure>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-Unmarshal及json标签和marshal" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/28/Unmarshal及json标签和marshal/" class="article-date">
<time datetime="2018-05-28T10:11:47.383Z" itemprop="datePublished">五月 28, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="Unmarshal及json标签和marshal"><a href="#Unmarshal及json标签和marshal" class="headerlink" title="Unmarshal及json标签和marshal"></a>Unmarshal及json标签和marshal</h1><p>##Unmarshal<br>package main</p>
<p>import (<br> “encoding/json”<br> “fmt”<br>)</p>
<p>type person struct {<br> First string<br> Last string<br> Age int <code>json:"ageNUM"</code>//标签<br>}</p>
<p>func main() {<br> var p1 person<br> //p1 =person{“zhang”,”heng”,20}<br> fmt.Println(p1.First)<br> fmt.Println(p1.Last)<br> fmt.Println(p1.Age)</p>
<pre><code>bs := []byte(`{"First":"James", "Last":"Bond", "ageNUM":20}`)
json.Unmarshal(bs, &p1)//自己认为是把bs数组映射到p1中,专业解析:unmarshal反序列化,也就是说从前端拿到json字符串,
//然后转成字节数组,映射到p1结构体里。输出
fmt.Println("--------------")
fmt.Println(p1.First)
fmt.Println(p1.Last)
fmt.Println(p1.Age)
fmt.Printf("%T \n", p1)
</code></pre><p>}</p>
<p>##json标签及marshal<br>package main</p>
<p>import (<br> “encoding/json”<br> “fmt”<br>)</p>
<p>type person struct {<br> First string//因为是共有标签所以首字母必须大写,才能被调用,但是后缀跟上json,那么就大小写无所谓,因为标签不再是结构体的key,而是对应json的标签<br> Last string <code>json:"-"</code>//代表忽略<br> Age int <code>json:"wisdom score"</code>//给他添加标签<br>}</p>
<p>func main() {<br> p1 := person{“James”, “Bond”, 20}<br> bs, _ := json.Marshal(p1)<br> fmt.Println(string(bs))<br>}<br>输出{“First”:”James”,”wisdom score”:20}</p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-go语言下的http包" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/26/go语言下的http包/" class="article-date">
<time datetime="2018-05-26T08:15:35.989Z" itemprop="datePublished">五月 26, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<p>#go语言下的http包<br>go web hello world:</p>
<p>package main</p>
<p>import (<br> “io”<br> “net/http”<br>)</p>
<p>func main() {<br> http.HandleFunc(“/“, sayhello)<br> http.ListenAndServe(“:8080”, nil)<br>}</p>
<p>func sayhello(w http.ResponseWriter, r *http.Request) {<br> io.WriteString(w, “hello world”)<br>}</p>
<p>首先注册一个sayhello函数给“/”,当浏览器浏览“/”的时候,会调用sayhello函数<br>其次开始监听和服务,“:8080”表示本机所有的ip地址的8080<br>查询ListenAndServe的文档可知,第2个参数是一个Hander<br>Hander是啥呢,它是一个接口。这个接口很简单,只要某个struct有ServeHTTP(http.ResponseWriter, *http.Request)这个方法,那这个struct就自动实现了Hander接口<br>那就ServeHTTP方法,他需要2个参数,一个是http.ResponseWriter,另一个是http.Request<br>往http.ResponseWriter写入什么内容,浏览器的网页源码就是什么内容<br>http.Request里面是封装了,浏览器发过来的请求(包含路径、浏览器类型等等)</p>
<p><a href="https://gowalker.org/net/http#ListenAndServe" target="_blank" rel="noopener">https://gowalker.org/net/http#ListenAndServe</a></p>
<p>认识http.ResponseWriter</p>
<p>把 “网页未找到”的代码改一下,让大家认识一下http.ResponseWriter<br>看清楚了,ServeHTTP方法是自己写的啊,自己去实现</p>
<p>package main</p>
<p>import (<br> “io”<br> “net/http”<br>)</p>
<p>type a struct{}</p>
<p>func (<em>a) ServeHTTP(w http.ResponseWriter, r </em>http.Request) {<br> io.WriteString(w, “hello world version 1.”)<br>}</p>
<p>func main() {<br> http.ListenAndServe(“:8080”, &a{})//第2个参数需要实现Hander的struct,a满足<br>}<br>访问localhost:8080的话,可以看到“hello world version 1.”<br>访问localhost:8080/abc的话,可以看到“hello world version 1.”<br>访问localhost:8080/123的话,可以看到“hello world version 1.”<br>事实上访问任何路径都是“hello world version 1.”</p>
<p>哦,原来是这样,当http.ListenAndServe(“:8080”, &a{})后,开始等待有访问请求<br>一旦有访问请求过来,http包帮我们处理了一系列动作后,最后他会去调用a的ServeHTTP这个方法,并把自己已经处理好的http.ResponseWriter, <em>http.Request传进去<br>而a的ServeHTTP这个方法,拿到</em>http.ResponseWriter后,并往里面写东西,客户端的网页就显示出来了</p>
<p>认识*http.Request</p>
<p>现在把上面的代码再改一下,让大家认识一下*http.Request</p>
<p>package main</p>
<p>import (<br> “io”<br> “net/http”<br>)</p>
<p>type a struct{}</p>
<p>func (<em>a) ServeHTTP(w http.ResponseWriter, r </em>http.Request) {<br> path := r.URL.String() //获得访问的路径<br> io.WriteString(w, path)<br>}</p>
<p>func main() {<br> http.ListenAndServe(“:8080”, &a{})//第2个参数需要实现Hander接口的struct,a满足<br>}<br>现在<br>访问localhost:8080的话,可以看到“/”<br>访问localhost:8080/abc的话,可以看到“/abc”<br>访问localhost:8080/123的话,可以看到“/123”</p>
<p>最傻的网站</p>
<p>如果再加上一些判断的话,一个最傻的可运行网站就出来了,如下</p>
<p>package main</p>
<p>import (<br> “io”<br> “net/http”<br>)</p>
<p>type a struct{}</p>
<p>func (<em>a) ServeHTTP(w http.ResponseWriter, r </em>http.Request) {<br> path := r.URL.String()<br> switch path {<br> case “/“:<br> io.WriteString(w, “</p><h1>root</h1><a href="\"abc\"">abc</a>“)<br> case “/abc”:<br> io.WriteString(w, “<h1>abc</h1><a href="\"/\"">root</a>“)<br> }<br>}<p></p>
<p>func main() {<br> http.ListenAndServe(“:8080”, &a{})//第2个参数需要实现Hander接口的struct,a满足<br>}<br>运行后,可以看出,一个case就是一个页面<br>如果一个网站有上百个页面,那是否要上百个case?<br>很不幸,是的<br>那管理起来岂不是要累死?<br>要累死,不过,还好有ServeMux</p>
<p>用ServeMux拯救最傻的网站</p>
<p>现在来介绍ServeMux</p>
<p>ServeMux大致作用是,他有一张map表,map里的key记录的是r.URL.String(),而value记录的是一个方法,这个方法和ServeHTTP是一样的,这个方法有一个别名,叫HandlerFunc<br>ServeMux还有一个方法名字是Handle,他是用来注册HandlerFunc 的<br>ServeMux还有另一个方法名字是ServeHTTP,这样ServeMux是实现Handler接口的,否者无法当http.ListenAndServe的第二个参数传输</p>
<p>package main</p>
<p>import (<br> “net/http”<br> “io”<br>)</p>
<p>type b struct{}</p>
<p>func (<em>b) ServeHTTP(w http.ResponseWriter, r </em>http.Request) {<br> io.WriteString(w, “hello”)<br>}<br>func main() {<br> mux := http.NewServeMux()<br> mux.Handle(“/h”, &b{})<br> http.ListenAndServe(“:8080”, mux)<br>}</p>
<p>解释一下<br>mux := http.NewServeMux():新建一个ServeMux。<br>mux.Handle(“/“, &b{}):注册路由,把”/“注册给b这个实现Handler接口的struct,注册到map表中。<br>http.ListenAndServe(“:8080”, mux)第二个参数是mux。<br>运行时,因为第二个参数是mux,所以http会调用mux的ServeHTTP方法。<br>ServeHTTP方法执行时,会检查map表(表里有一条数据,key是“/h”,value是&b{}的ServeHTTP方法)<br>如果用户访问/h的话,mux因为匹配上了,mux的ServeHTTP方法会去调用&b{}的 ServeHTTP方法,从而打印hello<br>如果用户访问/abc的话,mux因为没有匹配上,从而打印404 page not found</p>
<p>ServeMux就是个二传手!</p>
<p>ServeMux的HandleFunc方法</p>
<p>发现了没有,b这个struct仅仅是为了装一个ServeHTTP而存在,所以能否跳过b呢,ServeMux说:可以<br>mux.HandleFunc是用来注册func到map表中的</p>
<p>package main</p>
<p>import (<br> “net/http”<br> “io”<br>)</p>
<p>func main() {<br> mux := http.NewServeMux()<br> mux.HandleFunc(“/h”, func(w http.ResponseWriter, r <em>http.Request) {<br> io.WriteString(w, “hello”)<br> })<br> mux.HandleFunc(“/bye”, func(w http.ResponseWriter, r </em>http.Request) {<br> io.WriteString(w, “byebye”)<br> })<br> mux.HandleFunc(“/hello”, sayhello)<br> http.ListenAndServe(“:8080”, mux)<br>}</p>
<p>func sayhello(w http.ResponseWriter, r *http.Request) {<br> io.WriteString(w, “hello world”)<br>}</p>
<p>ServeMux的白话解释</p>
<p>如果把http服务想象成一个公司的话<br>没有ServeMux的话,就像这个公司只有1个人–老板,什么事情都是由老板来做(自己写switch)<br>包括做业务(“/sales”),做帐(“/account”),内勤(“/management”),扫地(“/cleaner”)</p>
<p>后来老板招了4个人,负责上面的4件事情,那老板要做的就是根据情况转发就是了,比如做业务的事情,自己就不用去跑客户了,交给销售经理去做,并给销售经理一些资源(包括客户名称地址什么的)<br>上面代码里的type b struct{}就是个销售经理,资源就是w http.ResponseWriter, r *http.Request,老板要工作的就是ServeMux要做的工作</p>
<p>以上的代码就做了一层转发,老板给销售经理事情后,销售经理去跑客户了,也就结束了</p>
<p>实际生活中,销售经理不会自己去跑客户的,他也会把接来的活转给更下面的业务员<br>那时,销售经理自己也变成一个ServeMux了</p>
<p>所以为了可以ServeMux套ServeMux,需要改造一下ServeMux的ServeHTTP,改完后可以嵌套无限层,把要做的事情不断的细化<br>到最后要真正做事情的人,只需要关心自己要做的事情就可以了,自己做自己份内的事,一个大公司就运作起来了</p>
<p>回到开头</p>
<p>回到开头,有让大家先忘掉http.HandleFunc(“/“, sayhello)<br>请先忘记引子里的http.HandleFunc(“/“, sayhello),这个要到很后面才提到</p>
<p>当http.ListenAndServe(“:8080”, nil)的第2个参数是nil时<br>http内部会自己建立一个叫DefaultServeMux的ServeMux,因为这个ServeMux是http自己维护的,如果要向这个ServeMux注册的话,就要用http.HandleFunc这个方法啦,现在看很简单吧</p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-POW共识算法" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/21/POW共识算法/" class="article-date">
<time datetime="2018-05-21T01:05:40.365Z" itemprop="datePublished">五月 21, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="POW共识算法"><a href="#POW共识算法" class="headerlink" title="POW共识算法"></a>POW共识算法</h1><p>以太坊和比特币运用该算法,为比特币提供挖矿的过程。<br>区块包括:第几块区块(高度);时间戳;当前hash,上一个hash,数据data,nonce值(随机值);diff难度系数。<br>第一个区块叫创世区块,每10分钟产生一个区块。<br>通过pow共识进行挖矿,产生满足难度系数的新区块。<br>代码如下:<br>package main</p>
<p>import (<br> “time”<br> “strconv”<br> “crypto/sha256”<br> “encoding/hex”<br> “fmt”<br> “strings”<br>)</p>
<p>//通过代码完成pow挖矿<br>//创建区块</p>
<p>type Block struct {<br> Index int//区块高度<br> TimeStamp string //时间戳<br> Diff int//当前网络的难度系数<br> PreHash string//上一个区块的hash值<br> HashCode string//当前区块的hash值<br> Nonce int//随机数<br> Data string//存交易信息<br>}<br>//创建创世区块,也就是第一个区块<br>func GenerateFirstBlock(data string)Block {<br> var firstBlock Block<br> firstBlock.Index=1<br> firstBlock.TimeStamp=time.Now().String()<br> firstBlock.Diff=4<br> firstBlock.Nonce=0<br> firstBlock.Data=data<br> firstBlock.HashCode=GenreateBlockHashValue(firstBlock)<br> return firstBlock<br>}<br>//生成区块的hash值<br>func GenreateBlockHashValue(block Block)string {<br> //按照比特的写法,将区块的所有属性拼接后做hash运算<br> var hashdata = strconv.Itoa(block.Index)+block.TimeStamp+strconv.Itoa(block.Diff)+<br> strconv.Itoa(block.Nonce)+block.Data<br> //hash算法<br> var sha=sha256.New()<br> sha.Write([]byte(hashdata))<br> hashed:=sha.Sum(nil)</p>
<pre><code>return hex.EncodeToString(hashed)//将16进制转换成字符串
</code></pre><p>}</p>
<p>//产生新区块<br>func GenerateNextBlock(data string,oldBlock Block)Block {<br> var newBlock Block<br> newBlock.Data=data<br> newBlock.Diff=6<br> newBlock.TimeStamp=time.Now().String()<br> //暂时设置为0,nonce值应该是有矿工操作处理<br> newBlock.Nonce=0<br> newBlock.PreHash=oldBlock.HashCode<br> newBlock.Index=2<br> //应该填写POW成功后,带有0000的那个哈希值<br> newBlock.HashCode=pow(newBlock.Diff,&newBlock)<br> return newBlock<br>}<br>//挖矿proof of work工作量证明算法<br>func pow(diff int,block <em>Block)string {<br> for {<br> hash := GenreateBlockHashValue(</em>block)<br> fmt.Println(hash)<br> if strings.HasPrefix(hash, strings.Repeat(“0”, diff)) {<br> fmt.Println(“挖矿成功”)<br> return hash<br> }else {<br> block.Nonce++<br> }<br> }<br>}<br>func main() {<br> var first =GenerateFirstBlock(“创世区块”)<br> fmt.Println(first)<br> //需要通过挖矿操作第二区块<br> GenerateNextBlock(“第二区块”,first)</p>
<p>}</p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-对称加密和非对称加密" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/19/对称加密和非对称加密/" class="article-date">
<time datetime="2018-05-19T11:48:23.164Z" itemprop="datePublished">五月 19, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="对称加密和非对称加密"><a href="#对称加密和非对称加密" class="headerlink" title="对称加密和非对称加密"></a>对称加密和非对称加密</h1><p>##DES加密解密<br>加密过程:明文64位->初始置换IP->16轮加密变换->逆初始置换IP-1->密文<br>1.首先对字符串的明文转成字节数组,按照密钥长度进行补码,补码过程:<br>func PKCS5Padding(ciphertext []byte,blockSize int) []byte {<br> padding:=blockSize-len(ciphertext)%blockSize<br> fmt.Println(blockSize)<br> padtext := bytes.Repeat([]byte{byte(padding)},padding)//补码过程<br> return append(ciphertext,padtext…)<br>}<br>2.把补码完的明文按blockSize的倍数分成n组。每组有64位,也就是8个字节。每组明文按照初始IP置换表的规则进行替换:如<br>图为初始置换IP表 <img src="media/15267305031577/15267942943081.jpg" alt=""></p>
<p>这里的初始IP置换表的意思为把64位明文按照表中的规则替换,比如第一行,把64位明文的第1位换为其58位,第2位换为50位,第3位换位42位…这表仔细观察有一定的规律,比如我们从右到左一列一列的分别读前4行,后4行。是不是就是2 4 6 8 10 12…和1 3 5 7 9 11…<br>3.16轮加密变换<br>把上边置换完每组明文分为LO和RO各32位。 <br>密钥先做一次置换,再做16次包含循环左移和置换的操作组合,每次都产生一个子密钥Ki。每一轮的置换操作都完全相同,但由于循环左移而使得每个子密钥不同每一轮的置换操作都完全相同,但由于循环左移而使得每个子密钥不同<img src="media/15267305031577/15267946625132.jpg" alt=""><br>上图所示:第一次运算函数f(RO,K1)的结果与LO异或,结果就是下一轮的R1,L1是上一轮的RO,接下来的一样方法,最后得到R16和L16进行逆初试置换IP-1(同始置换IP-1)得到密文。<br>代码如下:<br>package main</p>
<p>import (<br> “crypto/cipher”//密码<br> “crypto/des”<br> “encoding/base64”//将对象转换成字符串<br> “fmt”<br> “bytes”<br>)<br>//DES 3DES AES<br>//用同一个密钥加密和解密</p>
<p>//DES加密的方法<br>func MyDesEncrypt(origData,key[]byte) {<br> block,_:=des.NewCipher(key)</p>
<pre><code>origData =PKCS5Padding(origData,des.BlockSize)
//设置加密方式
blockMode:=cipher.NewCBCEncrypter(block,key)
//创建明文长度的字节数组
crypted :=make([]byte,len(origData))
//加密明文
blockMode.CryptBlocks(crypted,origData)
//将字节数组转换成字符串
fmt.Println(base64.StdEncoding.EncodeToString(crypted))
</code></pre><p>}<br>//明文补码<br>func PKCS5Padding(ciphertext []byte,blockSize int) []byte {<br> padding:=blockSize-len(ciphertext)%blockSize<br> fmt.Println(blockSize)<br> padtext := bytes.Repeat([]byte{byte(padding)},padding)//补码过程</p>
<pre><code>return append(ciphertext,padtext...)
</code></pre><p>}<br>//实现去补码<br>func PKCS5UnPadding(origData []byte)[]byte {<br> length:=len(origData)<br> unpadding:=int(origData[length-1])<br> return origData[:(length-unpadding)]<br>}<br>//DES解密方法<br>func MyDESDecrypt(data string,key []byte) {<br> //将字符串转换成字节数组<br> crypted,<em>:=base64.StdEncoding.DecodeString(data)<br> //将字节密钥转换成block块<br> block,</em>:=des.NewCipher(key)<br> //设置解密方式<br> blockMode:=cipher.NewCBCDecrypter(block,key)<br> //创建秘文大小的数组变量<br> origData:=make([]byte,len(crypted))<br> //解密秘文到数组origData中<br> blockMode.CryptBlocks(origData,crypted)<br> origData=PKCS5UnPadding(origData)<br> fmt.Println(origData)<br> fmt.Println(string((origData)))<br>}<br>func main() {<br> fmt.Println(“hello world”)<br> //声明一个密钥,利用此密钥实现明文的加密和解密<br> key :=[]byte(“12345698”)<br> MyDesEncrypt([]byte(“hello world “ ),key)<br> MyDESDecrypt(“NIJWb9F1DO11q08fSnB/HA==”,key)<br>}<br>CBC加密步骤如下:</p>
<ol>
<li>首先将数据按照8个字节一组进行分组得到D1D2……Dn(若数据不是8的整数倍,用指定的PADDING数据补位)</li>
<li>第一组数据D1与初始化向量I异或后的结果进行DES加密得到第一组密文C1(初始化向量I为全零)</li>
<li>第二组数据D2与第一组的加密结果C1异或以后的结果进行DES加密,得到第二组密文C2</li>
<li>之后的数据以此类推,得到Cn</li>
<li>按顺序连为C1C2C3……Cn即为加密结果。</li>
</ol>
<p>DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段段的8个字节的密文或者明文,最后一段不足8个字节(一般补0或者F),按照需求补足8个字节进行计算(并行计算),之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。</p>
<p>##DSA签名与验证<br>首先了解下bigInt和int的差别:<br>bigint 带符号的范围是-9223372036854775808到9223372036854775807。无符号的范围是0到18446744073709551615。<br>int 普通大小的整数。带符号的范围是-2147483648到2147483647。无符号的范围是0到4294967295。</p>
<p>DSA(Digital Signature Algorithm,数字签名算法,用作数字签名标准的一部分),它是另一种公开密钥算法,它不能用作加密,只用作数字签名。DSA使用公开密钥,为接受者验证数据的完整性和数据发送者的身份。它也可用于由第三方去确定签名和所签数据的真实性。DSA算法的安全性基于解离散对数的困难性,这类签字标准具有较大的兼容性和适用性,成为网络安全体系的基本构件之一。<br>p是L位长的素数,其中L从512到1024且是64的倍数。<br>q是160位长且与p-1互素的因子,其中h是小于p-1并且满足 大于1的任意数。</p>
<p>x是小于q的数。</p>
<p>另外,算法使用一个单向散列函数H(m)。标准指定了安全散列算法(SHA)。三个参数p,q和g是公开的,且可以被网络中所有的用户公有。私人密钥是x,公开密钥是y。</p>
<p>对消息m签名时:</p>
<p>(1) 发送者产生一个小于q的随机数k。</p>
<p>(2) 发送者产生:</p>
<p>r和s就是发送者的签名,发送者将它们发送给接受者。</p>
<p>(3) 接受者通过计算来验证签名:</p>
<p>如果v=r,则签名有效。</p>
<p>DSA签名:</p>
<p>公开密钥:</p>
<p>p 512位到1024位的素数</p>
<p>q 160位长,并与p-1互素的因子</p>
<p>其中h是小于p-1并且满足 大于1的任意数。</p>
<p>私人密钥:</p>
<p>x小于q</p>
<p>签名:</p>
<p>k选取小于q的随机数</p>
<p>验证:</p>
<p>如果v=r,则签名被验证。<br>代码如下:<br>package main</p>
<p>import (<br> “crypto/dsa”<br> “crypto/rand”<br> “fmt”</p>
<p>)<br>//作用1 确保传递数据的完整性 2 确保数据的来源<br>func main() {<br> //DSA专业做签名和验签<br> var param dsa.Parameters<br> dsa.GenerateParameters(&param,rand.Reader,dsa.L1024N160)<br> //生成私钥<br> var priv dsa.PrivateKey<br> priv.Parameters=param<br> dsa.GenerateKey(&priv,rand.Reader)</p>
<pre><code>//通过私钥生成公钥
pub:=priv.PublicKey
fmt.Println(pub)
message:=[]byte("hello world")
//r,s是两个整数
r,s,_:=dsa.Sign(rand.Reader,&priv,message)
//利用公钥验签
b:= dsa.Verify(&pub,message,r,s)
if b==true{
fmt.Println("验签成功")
}else {
fmt.Println("验证失败")
}
</code></pre><p>}</p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-012+公钥加密" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<div class="article-meta">
Posted on <a href="/2018/05/17/012+公钥加密/" class="article-date">
<time datetime="2018-05-17T07:08:48.764Z" itemprop="datePublished">五月 17, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="012-公钥加密"><a href="#012-公钥加密" class="headerlink" title="012 公钥加密"></a>012 公钥加密</h1><p>公钥密码又称为非对称密码,拥有公钥密码的用户分别拥有加密密钥和解密密钥。通过加密密钥不能得到解密密钥。并且加密密钥是公开的。</p>
<h2 id="什么是密钥配送问题"><a href="#什么是密钥配送问题" class="headerlink" title="什么是密钥配送问题"></a>什么是密钥配送问题</h2><p>在现实世界中使用对称密码时,我们一定会遇到密钥配送问题( key distribution problem)。</p>
<p>假如 A 给 B 写了一封情书,并使用对称加密,如果不讲加密密钥发送给B,B是无法查看情书的,如果将密钥和情书一起发送给B,就容易被攻击者截获。</p>
<p><strong>密钥必须要发送,但又不能发送</strong>,这就是对称密码的密钥配送问题。</p>
<p>解决密钥配送问题的方法:</p>
<ul>
<li>通过事先共享密钥来解决</li>
<li>通过密钥分配中心来解决</li>
<li>通过Diffie-Hellman密钥交换来解决</li>
<li>通过公钥密码来解决</li>
</ul>
<h3 id="通过事先共享密钥来解决"><a href="#通过事先共享密钥来解决" class="headerlink" title="通过事先共享密钥来解决"></a>通过事先共享密钥来解决</h3><p>密钥配送问题最简单的一种解决方法,就是事先用安全的方式将密钥交给对方,这称为密钥的事先共享。 事先共享的局限性:</p>
<ul>
<li>需要一种安全的方式将密钥交给对方。</li>
<li>即便能够实现事先共享密钥,但在人数很多的情况下,通信所需要的密钥数量也会增大。</li>
</ul>
<h3 id="通过密钥分配中心来解决"><a href="#通过密钥分配中心来解决" class="headerlink" title="通过密钥分配中心来解决"></a>通过密钥分配中心来解决</h3><p>如果所有参与加密通信的人都需要事先共享密钥,则密钥的数量会变得巨大,这样额情况下就可以使用密钥分配中心(Key Distribution Center,KDC)来解决密钥配送问题。当需要进行加密通信时,密钥分配中心会生成一个通信密钥,每个人只要和密钥分配中心事先共享密钥就可以了。有多少个人进行通信分配中心就保存了多少密钥。</p>
<p>局限性:</p>
<ul>
<li><p>随着通信人数的增加,密钥分配中心的负荷也会随之增加。如果密钥分配中心计算机发生故障,所有的加密通信就会瘫痪。</p>
</li>
<li><p>如果主动攻击者入侵了密钥分配中心计算机,并盗取了密钥数据库,所有人的加密通信都会被破译。</p>
</li>
</ul>
<h3 id="通过Diffie-Hellman密钥交换来解决"><a href="#通过Diffie-Hellman密钥交换来解决" class="headerlink" title="通过Diffie-Hellman密钥交换来解决"></a>通过Diffie-Hellman密钥交换来解决</h3><p>在Diffie-Hellman密钥交换中,进行加密通信的双方需要交换一些信息,而这些信息即便被窃听者听到也没有关系。<br>根据所交换的信息,双方可以各自生成相同的密钥,而窃听者却无法生成相同的密钥。窃听者虽然能够窃听到双方交换的信息但却无法根据这些信息生成和双方相同的密钥。</p>
<h3 id="通过公钥密码来解决"><a href="#通过公钥密码来解决" class="headerlink" title="通过公钥密码来解决"></a>通过公钥密码来解决</h3><h2 id="什么是公钥密码"><a href="#什么是公钥密码" class="headerlink" title="什么是公钥密码"></a>什么是公钥密码</h2><p>公钥密码( public-key cryptography),又称为非对称密码,密钥分为加密密钥和解密密钥两种。发送者用加密密钥对消息进行加密,接收者用解密密钥对密文进行解密。</p>
<p>加密密钥和解密密钥的区别:</p>
<ul>
<li>发送者只需要加密密钥</li>
<li>接收者只需要解密密钥</li>
<li>解密密钥不可以被窃听者获取</li>
<li>加密密钥被窃听者获取也没问题</li>
</ul>
<p>解密密钥从一开始就是由接收者自己保管的,因此只要将加密密钥发给发送者就可以解决<strong>密钥配送问题</strong>了,而根本不需要配送解密密钥。</p>
<h2 id="公钥通信的流程"><a href="#公钥通信的流程" class="headerlink" title="公钥通信的流程"></a>公钥通信的流程</h2><p>我们还是假设Alice要给Bob发送一条消息,Alice是发送者,Bob 是接收者,而这次窃听者Eve依然能够窃听到他们之间<br>的通信内容。</p>
<p>在公钥密码通信中,通信过程是由接收者Bob来启动的。</p>
<ol>
<li><p>Bob生成一个包含公钥和私钥的密钥对。私钥由Bob自行妥善保管。</p>
</li>
<li><p>Bob 将自己的公钥发送给Alice。</p>
<p> Bob的公钥被窃听者Eve截获也没关系。<br> 将公钥发送给Alice,表示Bob请Alice用这个公钥对消息进行加密并发送给他。</p>
</li>
<li><p>Alice用Bob的公钥对消息进行加密。</p>
<p> 加密后的消息只有用Bob的私钥才能够解密。虽然Alice拥有Bob 的公钥,但用Bob的公钥是无法对密文进行解密的。</p>
</li>
<li><p>Alice将密文发送给Bob。</p>
<p> 密文被窃听者Eve截获也没关系。Eve可能拥有Bob的公钥,但是用Bob的公钥是无法进行解密的。</p>
</li>
<li><p>Bob用自己的私钥对密文进行解密</p>
</li>
</ol>
<p>公钥通信的流程图:</p>
<p><img src="http://olgjbx93m.bkt.clouddn.com/20180117-065945.png" alt=""></p>
</div>
<footer class="entry-meta entry-footer">
</footer>
</div>
</article>
<!-- Table of Contents -->
<article id="post-Golang细节汇总" class="article article-type-post" itemscope itemprop="blogPost" >
<div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
<header class="article-header">
<h1 class="thumb" itemprop="name">
<a class="article-title" href="/2018/05/02/Golang细节汇总/">go语言细节及重点汇总</a>
</h1>
</header>
<div class="article-meta">
Posted on <a href="/2018/05/02/Golang细节汇总/" class="article-date">
<time datetime="2018-05-02T13:53:12.506Z" itemprop="datePublished">五月 2, 2018</time>
</a>
</div>
<div class="article-entry" itemprop="articleBody">
<h1 id="Golang细节汇总"><a href="#Golang细节汇总" class="headerlink" title="Golang细节汇总"></a>Golang细节汇总</h1><h2 id="mac-goland-安装"><a href="#mac-goland-安装" class="headerlink" title="mac goland 安装"></a>mac goland 安装</h2><p>mac系统安装并配置</p>
<p>安装</p>
<p>双击pkg包,顺着指引,即可安装成功。 </p>
<p>在命令行输入 go version,获取到go的版本号,则代表安装成功。</p>
<p>配置环境变量</p>
<p>1、打开终端输入cd ~进入用户主目录; </p>
<p>2、输入ls -all命令查看是否存在.bash_profile; </p>
<p>3、存在既使用vim .bash_profile 打开文件; </p>
<p>4、输入 i 进入vim编辑模式; </p>
<p>5、输入下面代码, </p>
<p>其中 GOPATH: 日常开发的根目录。GOBIN:是GOPATH下的bin目录。</p>
<p>export GOPATH=/Users/ruby/go</p>
<p>export GOBIN=$GOPATH/bin</p>
<p>export PATH=$PATH:$GOBIN</p>
<p>6、点击ESC,并输入 :wq 保存并退出编辑。可输入vim .bash_profile 查看是否保存成功。</p>
<p>7、输入source ~/.bash_profile 完成对golang环境变量的配置,配置成功没有提示。 </p>
<p>8、输入go env 查看配置结果</p>
<h2 id="原码,反码,补码"><a href="#原码,反码,补码" class="headerlink" title="原码,反码,补码"></a>原码,反码,补码</h2><p>正数的原码,反码,补码都是二进制的本身(第一位表示符号位)</p>
<p>负数的第一位为1,表示负数</p>
<p>负数的反码是在其原码的基础上,符号位不变,其余各位按位取反</p>
<p>负数的补码是反码+1</p>
<p>计算机存储数值都是二进制,而且是以补码的形式存储。为了解决负数问题</p>
<h2 id="switch-fallthrough用法"><a href="#switch-fallthrough用法" class="headerlink" title="switch fallthrough用法"></a>switch fallthrough用法</h2><p><1> 如需贯通后续的case,就添加fallthrough</1></p>
<p>如:</p>
<pre><code>switch x := 5; x {
default:
fmt.Println(x)
case 5:
x += 10
fmt.Println(x)
fallthrough
case 6:
x += 20
fmt.Println(x)
}
</code></pre><p>输出</p>
<p>15<br>35</p>
<p><2>case中的表达式是可选的,可以省略。如果该表达式被省略,则被认为是switch true,并且每个case表达式都被计算为true,并执行相应的代码块。</2></p>
<pre><code>func main(){
num := 75
switch { // expression is omitted
case num >= 0 && num <= 50:
fmt.Println("num is greater than 0 and less than 50")
case num >= 51 && num <= 100:
fmt.Println("num is greater than 51 and less than 100")
case num >= 101:
fmt.Println("num is greater than 100")
}
}
</code></pre><p><3>switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。</3></p>
<p>语法以及举证:</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span> x.(<span class="keyword">type</span>){</span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">type</span>:</span><br><span class="line"> statement(s); </span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">type</span>:</span><br><span class="line"> statement(s); </span><br><span class="line"> <span class="comment">/* 你可以定义任意个数的case */</span></span><br><span class="line"> <span class="keyword">default</span>: <span class="comment">/* 可选 */</span></span><br><span class="line"> statement(s);</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">var</span> x <span class="keyword">interface</span>{}</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">switch</span> i := x.(<span class="keyword">type</span>) {</span><br><span class="line"> <span class="keyword">case</span> <span class="literal">nil</span>: </span><br><span class="line"> fmt.Printf(<span class="string">" x 的类型 :%T"</span>,i) </span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">int</span>: </span><br><span class="line"> fmt.Printf(<span class="string">"x 是 int 型"</span>) </span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">float64</span>:</span><br><span class="line"> fmt.Printf(<span class="string">"x 是 float64 型"</span>) </span><br><span class="line"> <span class="keyword">case</span> <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">int</span>)</span> <span class="title">float64</span>:</span></span><br><span class="line"> fmt.Printf("x 是 func(int) 型") </span><br><span class="line"> <span class="keyword">case</span> <span class="keyword">bool</span>, <span class="keyword">string</span>:</span><br><span class="line"> fmt.Printf(<span class="string">"x 是 bool 或 string 型"</span> ) </span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> fmt.Printf(<span class="string">"未知型"</span>) </span><br><span class="line"> } </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="select-语句"><a href="#select-语句" class="headerlink" title="select 语句"></a>select 语句</h2><p>select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">var</span> c1, c2, c3 <span class="keyword">chan</span> <span class="keyword">int</span></span><br><span class="line"> <span class="keyword">var</span> i1, i2 <span class="keyword">int</span></span><br><span class="line"> <span class="keyword">select</span> {</span><br><span class="line"> <span class="keyword">case</span> i1 = <-c1:</span><br><span class="line"> fmt.Printf(<span class="string">"received "</span>, i1, <span class="string">" from c1\n"</span>)</span><br><span class="line"> <span class="keyword">case</span> c2 <- i2:</span><br><span class="line"> fmt.Printf(<span class="string">"sent "</span>, i2, <span class="string">" to c2\n"</span>)</span><br><span class="line"> <span class="keyword">case</span> i3, ok := (<-c3): <span class="comment">// same as: i3, ok := <-c3</span></span><br><span class="line"> <span class="keyword">if</span> ok {</span><br><span class="line"> fmt.Printf(<span class="string">"received "</span>, i3, <span class="string">" from c3\n"</span>)</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> fmt.Printf(<span class="string">"c3 is closed\n"</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> fmt.Printf(<span class="string">"no communication\n"</span>)</span><br><span class="line"> } </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>运行结果:</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">no communication</span><br></pre></td></tr></table></figure>
<ul>
<li><p>每个case都必须是一个通信</p>
</li>
<li><p>所有channel表达式都会被求值</p>
</li>
<li><p>所有被发送的表达式都会被求值</p>
</li>
<li><p>如果任意某个通信可以进行,它就执行;其他被忽略。</p>
</li>
<li><p>如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。 </p>
</li>
<li><p>否则:</p>
<p>如果有default子句,则执行该语句。</p>
<p>如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。</p>
</li>
</ul>
<h2 id="slice-array切片和数组的创建"><a href="#slice-array切片和数组的创建" class="headerlink" title="slice,array切片和数组的创建"></a>slice,array切片和数组的创建</h2><p>1.数组 :值传递</p>
<p> 概念:存储一组相同的数据类型的数据结构。</p>
<p> 特点:数据结构:内存上是连续空间。</p>
<p> 存储数据特点:有序,可以重复。</p>
<p> 数据类型一致。</p>
<p> 定长:数组一旦创建长度不能更改,但是可以更改存储的数据。</p>
<p> 语法:</p>
<p> A:数组的创建</p>
<p> var variable_name [SIZE] variable_type</p>
<p> var a [4] int</p>
<p> var b = [4]int{}</p>
<p> var c = [4] int {1,2,3,4}</p>
<p> var d = [4]int{1,2}//后边补零</p>
<p> e := [4]int{index:value}</p>
<p> f:=[…] int{}</p>
<p> B:数组的访问</p>
<p> 主要通过下标:index,取值范围是:从0开始,到长度减1。</p>
<p> index(下标):,数据在数组中的位置。从0开始,到长度减1。否则越界异常。</p>
<p> 赋值:数组名[index] = value(数据)</p>
<p> 取值:数组名[index]</p>
<p>遍历数组:依次获取数组中的数据</p>
<p> range 数组名:index,value</p>
<p> 数组的类型:值类型:传递该数据的时候,传递数据的副本(备份,复制)</p>
<p> arr1:=[5] int {1,1,1,1,1}</p>
<p> arr2 = arr1//将arr1的数据拷贝一份,值赋值给arr2。</p>
<p> //如果在把arr1的值赋值给arr1之后,更改了arr1的内容,对于arr2没</p>
<p> 有影响。因为是值类型,传递的是备份数据。 </p>
<p> 循环操作数组:</p>
<p> for i:=0;i<len(arr);i++{</p>
<p> arr[i] </p>
<p> }</p>
<p> range–>数组:将数组的下标和对应的数值</p>
<p> for index,value := range arr{</p>
<p> index:下标</p>
<p> value:数据</p>
<p> }</p>
<p> 数据类型:数组的类型:[size]type,</p>
<p> 数组的排序:数组中的数据,按照升序或降序排列。</p>
<p> 冒泡排序:思路:每次比较相邻的两个数,如果前一个数大于后一个数,交换。排n轮: </p>
<p> 长度-1 </p>
<p>a := [5] int {30,31,18,17,15}</p>
<p>for i:=1;i<len(a);i++{</p>
<p> for j:=0;j<len(a)-i;j++{</p>
<p> if a[j]>a[j+1]{</p>
<p> a[j] ,a[j+1]=a[j+1],a[j]</p>
<p> }</p>
<p> }</p>
<p> fmt.Println(a)</p>
<p> 多维数组:二维数组:一维的一维</p>
<p> 一维数组,直接存储数据本身</p>
<p> 二维数组,存储的是一维数组</p>
<p>语法: c := [3][4] int{</p>
<p> {1,2,3,4},</p>
<p> {5,6,7,8},</p>
<p> {9,10,11,12}}</p>
<p>len(b)–>二维数组的长度:存储了几个一维数组</p>
<p>len(b[0])–>第一个一维数组的长度</p>
<p>b[0][0]–>第一个一维数组中,第一个数据</p>
<p>len(),cap(),数组的长度和容量一致的。</p>
<p><img src="https://note.youdao.com/yws/public/resource/9c0a3e77aee595f07194cb7cce079811/xmlnote/0FC740ACE2114E5DA5678F848911BCD6/32BA34A8FF704B5E95B9C9A0C93CB942/418" alt="img"></p>
<p> </p>
<p> 2.切片:slice(引用类型)</p>
<p> 理解为变长的数组</p>
<p> A:切片创建</p>
<p> 1.创建切片1.直接创建</p>
<p> s1 := [] int{1,2,3,4,5,6,7,8}</p>
<p> 2.使用make([]T, len,cap) cap如果不给数值,那么和len一致, </p>
<p> s2:=make([]T,len,cap)</p>
<p> s3 := make([]int, 3, 8)</p>
<p> 3.在数组的基础上创建切片</p>
<p> b := [10]int{1,2,3,4,5,6,7,8,9,10}</p>
<p> s4 := b[2:6] // 数组名[start:end),start,end指的是下标。不包含end</p>
<p> s5 := b[:6] // [0:6],从头开始,切割刀下标6(不包含6)</p>
<p> s6 :=b[6:] // [start:],从start开始,切割刀最后</p>
<p> B:切片的类型:</p>
<p> []数据类型 </p>
<p> 切片属于引用类型:</p>
<p> s1:=[] int{1,2,3,4}</p>
<p> s2:=s1</p>
<p> append(slice, ele1,ele2,ele3)//向切片后面直接加数值</p>
<p> append(slice1,slice2…)//向切片后面加切片,注意加 …</p>
<p> </p>
<h2 id="slice-copy和append方法"><a href="#slice-copy和append方法" class="headerlink" title="slice copy和append方法"></a>slice copy和append方法</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">语法:</span><br><span class="line">len(),存储的实际的数量</span><br><span class="line">cap(),存储的最大的数量,自动扩容:规则:2倍</span><br><span class="line">append(slice, ele1,ele2,ele3),增加同类型元素</span><br><span class="line">append(slice1,slice2...),增加切片里元素</span><br><span class="line">cap:0-->1-->2-->4-->8-->16-->32,倍数增加容量</span><br></pre></td></tr></table></figure>
<p>下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> <span class="string">"fmt"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"> <span class="keyword">var</span> numbers []<span class="keyword">int</span></span><br><span class="line"> printSlice(numbers)</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* 允许追加空切片 */</span></span><br><span class="line"> numbers = <span class="built_in">append</span>(numbers, <span class="number">0</span>)</span><br><span class="line"> printSlice(numbers)</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* 向切片添加一个元素 */</span></span><br><span class="line"> numbers = <span class="built_in">append</span>(numbers, <span class="number">1</span>)</span><br><span class="line"> printSlice(numbers)</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* 同时添加多个元素 */</span></span><br><span class="line"> numbers = <span class="built_in">append</span>(numbers, <span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>)</span><br><span class="line"> printSlice(numbers)</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* 创建切片 numbers1 是之前切片的两倍容量*/</span></span><br><span class="line"> numbers1 := <span class="built_in">make</span>([]<span class="keyword">int</span>, <span class="built_in">len</span>(numbers), (<span class="built_in">cap</span>(numbers))*<span class="number">2</span>)</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 拷贝 numbers 的内容到 numbers1,如果numbers1的长度小于numbers,那么numbers1内的数值将被全部覆盖 </span></span><br><span class="line"> <span class="built_in">copy</span>(numbers1,numbers)</span><br><span class="line"> printSlice(numbers1) </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">printSlice</span><span class="params">(x []<span class="keyword">int</span>)</span></span>{</span><br><span class="line"> fmt.Printf(<span class="string">"len=%d cap=%d slice=%v\n"</span>,<span class="built_in">len</span>(x),<span class="built_in">cap</span>(x),x)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><code>结果</code></p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">len</span>=<span class="number">0</span> <span class="built_in">cap</span>=<span class="number">0</span> slice=[]</span><br><span class="line"><span class="built_in">len</span>=<span class="number">1</span> <span class="built_in">cap</span>=<span class="number">2</span> slice=[<span class="number">0</span>]</span><br><span class="line"><span class="built_in">len</span>=<span class="number">2</span> <span class="built_in">cap</span>=<span class="number">2</span> slice=[<span class="number">0</span> <span class="number">1</span>]</span><br><span class="line"><span class="built_in">len</span>=<span class="number">5</span> <span class="built_in">cap</span>=<span class="number">8</span> slice=[<span class="number">0</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="built_in">len</span>=<span class="number">5</span> <span class="built_in">cap</span>=<span class="number">12</span> slice=[<span class="number">0</span> <span class="number">1</span> <span class="number">2</span> <span class="number">3</span> <span class="number">4</span>]</span><br></pre></td></tr></table></figure>
<blockquote>
<p>numbers1与numbers两者不存在联系,numbers发生变化时,numbers1是不会随着变化的。也就是说copy方法是不会建立两个切片的联系的</p>
</blockquote>
<p>Append里有个坑,详见例子</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">func main() {</span><br><span class="line"> a := make([]int, 5, 10)</span><br><span class="line"> b := append(a, 1)//新开辟内存b,b内的值是指针传递,由a传递,a变化,b也会跟着相应变化</span><br><span class="line"> _ = append(a, 2)</span><br><span class="line"> a[0]=9</span><br><span class="line"> a=append(a,3,4,5)</span><br><span class="line"> fmt.Println(a)</span><br><span class="line"> fmt.Println(b)</span><br><span class="line"> fmt.Printf("%p\n",&a)</span><br><span class="line"> fmt.Printf("%p",&b)</span><br></pre></td></tr></table></figure>
<p>输出</p>
<p>[9 0 0 0 0 3 4 5]<br>[9 0 0 0 0 3]<br>0xc0420023e0<br>0xc042002400</p>
<h2 id="Map-字典"><a href="#Map-字典" class="headerlink" title="Map 字典"></a>Map 字典</h2><p>Map集合是引用类型:传递时候,传递的是地址。</p>
<pre><code>映射。存储一组无需的键值对的容器。
存储的特点:a.键与值是一一对应的。---->映射
b.键是唯一的
</code></pre><p>语法:<br> A:创建:如果一个map仅有声明,就是nil map,不能直接存储数据<br> var map名 [key类型]value类型<br> map名:=map[key类型]value类型{}<br> map名:=make(map[key类型]value类型)<br> B:向map中添加数据<br> map[key] = value</p>
<p> C:获取map的数据:根据key获取value,如果key 不存在<br> /<em> 使用 key 输出 map 值 </em>/<br> map1:=make(map[int]string)<br> for key := range map1 {<br> fmt.Println(key,map1[key])<br> }</p>
<pre><code> /* 查看元素在集合中是否存在 */
value, ok := map1[key]
/* 如果 ok 是 true, 则存在,否则不存在 */
if(ok){
fmt.Println(value)
}else {
fmt.Println("value is not present")
}
D:删除键值对
delete(map,key)
根据key删除键值对,如果key不存在,删除失败。
</code></pre><p> E:修改:<br> 根据key修改<br>map的遍历:<br>创建slice,利用append函数,将map中的key值遍历再加入到slice中,排序<br>//1.定义一个slice<br>s1 := make([]int,0,len(map2))<br>//2.遍历map获取key–>s1中<br>for key := range map2{<br> s1 = append(s1, key)<br>}<br>//3.给s1进行排序<br>sort.Ints(s1)//使用sort包下的方法直接排序,不用自己写冒泡了。<br>//4. 遍历s1,map<br>for _,k:=range s1{ // 先下标,再数值<br> fmt.Println(k, map2[k])<br>}</p>
<h2 id="string字符串"><a href="#string字符串" class="headerlink" title="string字符串"></a>string字符串</h2><p> 字符串:多个字节的集合。理解为一个字符序列。</p>
<p> //长度:字符串中的字节的数量。</p>
<p> //序列:有序–>下标,也叫索引,每个字符的位置。从0开始,到长度减1。</p>
<p> 遍历:可以根据字符的下标,进行访问遍历</p>
<p> for i:=0;i<len(s2);i++{</p>
<pre><code>//fmt.Println(s2[i])
fmt.Printf("%c\n",s2[i])
</code></pre><p> }</p>
<p> 字符串—>[]byte</p>
<p> []byte(s1)</p>
<p> string(arr1)</p>
<p> strings函数包使用方法:</p>
<p> s1:=”HelloWorld”</p>
<p> s2:=”20180403课堂笔记.txt”</p>
<p> 1.strings.Contains(s,””):返回值为bool </p>
<p> 是否包含指定内容,</p>
<p> fmt.Println(strings.Contains(s1,”O”))</p>
<p> //判断s1中是否包含“0”</p>
<p> 2.strings.ContainsAny(s,””):返回值为bool</p>
<p> 是否包含指定内容中的任意一个,</p>
<p> fmt.Println(strings.ContainsAny(s1,”abcd”))</p>
<p> //判断s1中是否包含”abcd”中的任意一个</p>
<p> 3.strings.HasPrefix(s,””):返回值为bool</p>
<p> 判断s是否有前缀字符串,</p>
<p> if strings.HasPrefix(s2,”201804”) {</p>
<pre><code>fmt.Println("这个是4月份的笔记。。")
</code></pre><p> }</p>
<p> //判断s2是不是以”201804”为开头的</p>
<p> 4.strings.HasSuffix(s,””):返回值为bool</p>
<p> 判断s是否有后缀字符串</p>
<p> if strings.HasSuffix(s2,”.txt”){</p>
<pre><code>fmt.Println("这个是一个文本文档。。")
</code></pre><p> }</p>
<p> //判断s2是不是以”.txt”为结束的</p>
<p> 5.strings.Index(s,””):返回值为int</p>
<p> 子串” “在字符串s中第一次出现的位置,不存在则返回-1。</p>
<p> fmt.Println(strings.Index(s1,”llo”))</p>
<p> //查找s1第一次出现”llo”的下标,不存在则返回-1.</p>
<p> 6.strings.LastIndex(s,””):返回值为int</p>
<p> 子串” “在字符串s中最后一次出现的位置,不存在则返回-1。</p>
<p> fmt.Println(strings.LastIndex(s1,”l”))</p>
<p> //查找s1最后一次出现”l”的下标,不存在则返回-1</p>
<p> 7.strings.Count(s,””):返回值为int。</p>
<p> 统计s字符串中出现子串” “的次数。</p>
<p> fmt.Println(strings.Count(s1,”l”))</p>
<p> //统计s1中出现”l”的次数</p>
<p> 8.strings.Split(s1,””): 返回值为[]string</p>
<p> 用去掉s中出现的sep的方式进行分割,会分割到结尾,并返回生成的所</p>
<p> 有片段组成的切片(每一个sep都会进行一次切割,即使两个sep相邻,也会</p>