<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[NET-E]]></title><description><![CDATA[Thoughts, stories and ideas.]]></description><link>http://www.net-e.cn/</link><image><url>http://www.net-e.cn/favicon.png</url><title>NET-E</title><link>http://www.net-e.cn/</link></image><generator>Ghost 4.11</generator><lastBuildDate>Sun, 12 Apr 2026 14:07:01 GMT</lastBuildDate><atom:link href="http://www.net-e.cn/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[基于 golang 从零到一实现时间轮算法]]></title><description><![CDATA[<h2 id="0-%E5%89%8D%E8%A8%80">0 &#x524D;&#x8A00;</h2><p>&#x8FD1;&#x671F;&#x8BA1;&#x5212;&#x653B;&#x575A;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x4E13;&#x9898;&#x7CFB;&#x5217;&#x2014;&#x2014;&#x5982;&#x4F55;&#x57FA;&#x4E8E; golang &#x4ECE;&#x96F6;&#x5230;&#x4E00;&#x5B9E;&#x73B0; redis.</p><p>&#x8FD9;&#x91CC;&#x9009;&#x62E9;&#x7684;&#x5B66;&#x4E60;&#x7D20;&#x6750;&#x662F; hdt3213 &#x5927;&#x4F6C;&#x4E8E; github &#x4E0A;&#x5F00;&#x6E90;&#x7684;</p>]]></description><link>http://www.net-e.cn/ji-yu-golang-cong-ling-dao-yi-shi-xian-shi-jian-lun-suan-fa/</link><guid isPermaLink="false">65824f2b1cca100001bb3f7d</guid><dc:creator><![CDATA[Liang Wang]]></dc:creator><pubDate>Wed, 20 Dec 2023 02:20:22 GMT</pubDate><content:encoded><![CDATA[<h2 id="0-%E5%89%8D%E8%A8%80">0 &#x524D;&#x8A00;</h2><p>&#x8FD1;&#x671F;&#x8BA1;&#x5212;&#x653B;&#x575A;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x4E13;&#x9898;&#x7CFB;&#x5217;&#x2014;&#x2014;&#x5982;&#x4F55;&#x57FA;&#x4E8E; golang &#x4ECE;&#x96F6;&#x5230;&#x4E00;&#x5B9E;&#x73B0; redis.</p><p>&#x8FD9;&#x91CC;&#x9009;&#x62E9;&#x7684;&#x5B66;&#x4E60;&#x7D20;&#x6750;&#x662F; hdt3213 &#x5927;&#x4F6C;&#x4E8E; github &#x4E0A;&#x5F00;&#x6E90;&#x7684; godis &#x9879;&#x76EE;. &#x5728;&#x5927;&#x4F6C;&#x7684;&#x5B9E;&#x73B0;&#x4E2D;&#xFF0C;&#x5145;&#x5206;&#x5229;&#x7528;&#x4E86; golang &#x7684;&#x7279;&#x6027;&#xFF0C;&#x5C06; redis &#x5B58;&#x50A8;&#x5C42;&#x7531;&#x5355;&#x7EBF;&#x7A0B;&#x6A21;&#x578B;&#x8F6C;&#x4E3A;&#x5E76;&#x53D1;&#x6A21;&#x578B;&#xFF0C;&#x5176;&#x4E2D;&#x5728;&#x5B9E;&#x73B0;&#x6570;&#x636E;&#x7684; expire &#x673A;&#x5236;&#x65F6;&#xFF0C;&#x91C7;&#x7528;&#x7684;&#x662F;&#x5355;&#x673A;&#x65F6;&#x95F4;&#x8F6E;&#x6A21;&#x578B;&#x8FDB;&#x884C;&#x8FC7;&#x671F;&#x6570;&#x636E;&#x7684;&#x5220;&#x9664;&#x64CD;&#x4F5C;.</p><p>godis &#x9879;&#x76EE;&#x5F00;&#x6E90;&#x5730;&#x5740;&#xFF1A;<a href="https://link.zhihu.com/?target=http%3A//github.com/HDT3213/godis" rel="nofollow noreferrer">http://github.com/HDT3213/godis</a></p><p>godis &#x65F6;&#x95F4;&#x8F6E;&#x4EE3;&#x7801;&#xFF1A;<a href="https://link.zhihu.com/?target=http%3A//github.com/HDT3213/godis/blob/master/lib/timewheel/timewheel.go" rel="nofollow noreferrer">http://github.com/HDT3213/godis/blob/master/lib/timewheel/timewheel.go</a></p><p>&#x5B9E;&#x9645;&#x4E0A;&#xFF0C;&#x5728;&#x6211;&#x4E4B;&#x524D;&#x5206;&#x4EAB;&#x4E2A;&#x4EBA;&#x9879;&#x76EE;&#x2014;&#x2014;&#x5206;&#x5E03;&#x5F0F;&#x5B9A;&#x65F6;&#x5668; xtimer &#x4E2D;&#x4E5F;&#x6709;&#x5230;&#x4E86;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#xFF0C;&#x8FD9;&#x90E8;&#x5206;&#x5185;&#x5BB9;&#x5177;&#x6709;&#x4E00;&#x5B9A;&#x5171;&#x6027;. &#x501F;&#x6B64;&#x673A;&#x4F1A;&#xFF0C;&#x672C;&#x671F;&#x5355;&#x72EC;&#x5BF9;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#x7684;&#x539F;&#x7406;&#x548C;&#x5B9E;&#x8DF5;&#x5185;&#x5BB9;&#x8FDB;&#x884C;&#x68B3;&#x7406;&#xFF0C;&#x5E76;&#x57FA;&#x4E8E; golang &#x4ECE;&#x96F6;&#x5230;&#x4E00;&#x5F00;&#x6E90;&#x5B9E;&#x73B0;&#x51FA;&#x4E00;&#x4E2A;&#x5355;&#x673A;&#x7248;&#x548C; redis &#x5206;&#x5E03;&#x5F0F;&#x7248;&#x7684;&#x65F6;&#x95F4;&#x8F6E;&#xFF0C;&#x4F9B;&#x5927;&#x5BB6;&#x4E00;&#x8D77;&#x4EA4;&#x6D41;&#x63A2;&#x8BA8;.</p><p>&#x4E2A;&#x4EBA;&#x5F00;&#x6E90;&#x7684;&#x65F6;&#x95F4;&#x8F6E;&#x9879;&#x76EE;&#x5730;&#x5740;&#x4E3A;&#xFF1A;<a href="https://link.zhihu.com/?target=http%3A//github.com/xiaoxuxiansheng/timewheel" rel="nofollow noreferrer">http://github.com/xiaoxuxiansheng/timewheel</a></p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-2974cb21d1054ba8c8430d77e2ad1f44_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x672C;&#x671F;&#x5185;&#x5BB9;&#x7684;&#x76EE;&#x5F55;&#x5927;&#x7EB2;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-6a1615007ac030f31e6f1d52af7091cf_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="1-%E6%97%B6%E9%97%B4%E8%BD%AE%E5%8E%9F%E7%90%86">1 &#x65F6;&#x95F4;&#x8F6E;&#x539F;&#x7406;</h2><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-f34443d40b83648dd67316de8db137d0_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x65F6;&#x95F4;&#x8F6E;&#x662F;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8C03;&#x5EA6;&#x7CFB;&#x7EDF;&#x4E2D;&#x5E38;&#x7528;&#x5230;&#x7684;&#x4E00;&#x79CD;&#x7ECF;&#x5178;&#x7684;&#x7B97;&#x6CD5;&#x6A21;&#x578B;. &#x6709;&#x5173;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#x7684;&#x8BE6;&#x7EC6;&#x6982;&#x5FF5;&#x4ECB;&#x7ECD;&#xFF0C;&#x53EF;&#x4EE5;&#x53C2;&#x89C1;&#x8BBA;&#x6587;:&#x300A;Hashed and Hierarchical Time Wheels: Data Structures for the Efficient Implementation of a Time Facility&#x300B;<a href="https://link.zhihu.com/?target=http%3A//www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf" rel="nofollow noreferrer">http://www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf</a></p><p>&#x63A5;&#x4E0B;&#x6765;&#x6211;&#x4E5F;&#x4F1A;&#x4ECE;&#x4E2A;&#x4EBA;&#x89D2;&#x5EA6;&#x51FA;&#x53D1;&#xFF0C;&#x8C08;&#x8C08;&#x6211;&#x5BF9;&#x4E8E;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#x7684;&#x4E00;&#x4E9B;&#x6D45;&#x663E;&#x7406;&#x89E3;.</p><p><br></p><h2 id="11-%E6%97%B6%E9%97%B4%E8%BD%AE%E6%A6%82%E5%BF%B5">1.1 &#x65F6;&#x95F4;&#x8F6E;&#x6982;&#x5FF5;</h2><p>&#x804A;&#x65F6;&#x95F4;&#x8F6E;&#x4E4B;&#x524D;&#xFF0C;&#x5148;&#x804A;&#x804A;&#x65F6;&#x95F4;&#x7684;&#x6982;&#x5FF5;.</p><p>&#x9996;&#x5148;&#x65F6;&#x95F4;&#x662F;&#x4E00;&#x7EF4;&#x3001;&#x5355;&#x5411;&#x7684;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7528;&#x4E00;&#x6761;&#x4E00;&#x7EF4;&#x7684;&#x65F6;&#x95F4;&#x8F74;&#x5C06;&#x5176;&#x5177;&#x8C61;&#x5316;. &#x6211;&#x4EEC;&#x5BF9;&#x65F6;&#x95F4;&#x8F74;&#x8FDB;&#x884C;&#x523B;&#x5EA6;&#x62C6;&#x5206;&#xFF0C;&#x6BCF;&#x4E2A;&#x523B;&#x5EA6;&#x5BF9;&#x5E94;&#x4E00;&#x4E2A;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#xFF0C;&#x90A3;&#x4E48;&#x523B;&#x5EA6;&#x62C6;&#x5206;&#x5F97;&#x8D8A;&#x7EC6;&#xFF0C;&#x5219;&#x8868;&#x793A;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x8D8A;&#x7CBE;&#x786E;.</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-26a31dc09507f5e7ca9a9432bffeab0d_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x7136;&#x800C;&#xFF0C;&#x6211;&#x4EEC;&#x77E5;&#x9053;&#x65F6;&#x95F4;&#x662F;&#x6CA1;&#x6709;&#x5C3D;&#x5934;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x8FD9;&#x6761;&#x4E00;&#x7EF4;&#x65F6;&#x95F4;&#x8F74;&#x7684;&#x957F;&#x5EA6;&#x662F;&#x65E0;&#x7A77;&#x5927;&#x7684;. &#x5018;&#x82E5;&#x6211;&#x4EEC;&#x60F3;&#x8981;&#x5EFA;&#x7ACB;&#x4E00;&#x4E2A;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x53BB;&#x8868;&#x8FBE;&#x8FD9;&#x6761;&#x7531;&#x4E00;&#x7CFB;&#x5217;&#x523B;&#x5EA6;&#x805A;&#x5408;&#x5F62;&#x6210;&#x7684;&#x65F6;&#x95F4;&#x8F74;&#xFF0C;&#x8FD9;&#x4E2A;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x6240;&#x5360;&#x7528;&#x7684;&#x7A7A;&#x95F4;&#x4E5F;&#x662F;&#x65E0;&#x7A77;&#x65E0;&#x5C3D;&#x7684;.</p><p>&#x90A3;&#x4E48;&#xFF0C;&#x6211;&#x4EEC;&#x5E94;&#x8BE5;&#x5982;&#x4F55;&#x4F18;&#x5316;&#x8FD9;&#x4E2A;&#x95EE;&#x9898;&#x5462;&#xFF1F;&#x6B64;&#x65F6;&#xFF0C;&#x5927;&#x5BB6;&#x4E0D;&#x59A8;&#x4F4E;&#x5934;&#x770B;&#x4E00;&#x773C;&#x81EA;&#x5DF1;&#x7684;&#x624B;&#x8868;. &#x624B;&#x8868;&#x6216;&#x65F6;&#x949F;&#x8FD9;&#x7C7B;&#x65E5;&#x5E38;&#x751F;&#x6D3B;&#x4E2D;&#x7528;&#x6765;&#x5173;&#x8054;&#x8868;&#x8FBE;&#x65F6;&#x95F4;&#x7684;&#x5DE5;&#x5177;&#xFF0C;&#x91C7;&#x7528;&#x7684;&#x662F;&#x9996;&#x5C3E;&#x8854;&#x63A5;&#x7684;&#x73AF;&#x72B6;&#x7ED3;&#x6784;&#x6765;&#x66FF;&#x4EE3;&#x65E0;&#x7A77;&#x957F;&#x5EA6;&#x7684;&#x4E00;&#x7EF4;&#x65F6;&#x95F4;&#x8F74;&#xFF0C;&#x6BCF;&#x5F53;&#x949F;&#x8868;&#x5212;&#x8FC7;&#x4E00;&#x5708;&#xFF0C;&#x523B;&#x5EA6;&#x4ECE;&#x65B0;&#x56DE;&#x5230;&#x96F6;&#x503C;&#xFF0C;&#x4F46;&#x662F;&#x5DF2;&#x6709;&#x7684;&#x65F6;&#x95F4;&#x8FDB;&#x5EA6;&#x4F1A;&#x4F20;&#x627F;&#x5F80;&#x4E0B;.</p><p>&#x672C;&#x671F;&#x6240;&#x804A;&#x7684;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#x91C7;&#x7528;&#x7684;&#x601D;&#x8DEF;&#x6B63;&#x662F;&#x4E0E;&#x4E4B;&#x7C7B;&#x4F3C;&#xFF0C;&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x68B3;&#x7406;&#x4E00;&#x4E0B;&#x6838;&#x5FC3;&#x6D41;&#x7A0B;&#xFF1A;</p><ul><li>&#x5EFA;&#x7ACB;&#x4E00;&#x4E2A;&#x73AF;&#x72B6;&#x6570;&#x636E;&#x7ED3;&#x6784;</li><li>&#x6BCF;&#x4E2A;&#x523B;&#x5EA6;&#x5BF9;&#x5E94;&#x4E00;&#x4E2A;&#x65F6;&#x95F4;&#x8303;&#x56F4;</li><li>&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x6839;&#x636E;&#x8DDD;&#x4ECA;&#x7684;&#x76F8;&#x5BF9;&#x65F6;&#x957F;&#xFF0C;&#x63A8;&#x7B97;&#x51FA;&#x9700;&#x8981;&#x5411;&#x540E;&#x63A8;&#x79FB;&#x7684;&#x523B;&#x5EA6;&#x503C;</li><li>&#x5018;&#x82E5;&#x6765;&#x5230;&#x73AF;&#x5F62;&#x6570;&#x7EC4;&#x7684;&#x7ED3;&#x5C3E;&#xFF0C;&#x5219;&#x91CD;&#x65B0;&#x4ECE;&#x8D77;&#x70B9;&#x5F00;&#x59CB;&#x8BA1;&#x7B97;&#xFF0C;&#x4F46;&#x662F;&#x8BB0;&#x5F55;&#x65F6;&#x628A;&#x6267;&#x884C;&#x8F6E;&#x6B21;&#x6570;&#x52A0;1</li><li>&#x4E00;&#x4E2A;&#x523B;&#x5EA6;&#x53EF;&#x80FD;&#x5B58;&#x5728;&#x591A;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x6240;&#x4EE5;&#x6BCF;&#x4E2A;&#x523B;&#x5EA6;&#x9700;&#x8981;&#x6302;&#x8F7D;&#x4E00;&#x4E2A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x94FE;&#x8868;</li></ul><p>&#x63A5;&#x4E0B;&#x6765;&#xFF0C;&#x6211;&#x4EEC;&#x5EFA;&#x7ACB;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x626B;&#x63CF;&#x673A;&#x5236;&#xFF0C;&#x5C31;&#x5982;&#x540C;&#x949F;&#x8868;&#x4E2D;&#x7684;&#x6307;&#x9488;&#x4E00;&#x822C;&#xFF0C;&#x6309;&#x7167;&#x56FA;&#x5B9A;&#x7684;&#x65F6;&#x95F4;&#x8282;&#x594F;&#xFF0C;&#x6CBF;&#x7740;&#x73AF;&#x5F62;&#x6570;&#x7EC4;&#x5468;&#x800C;&#x590D;&#x59CB;&#x5730;&#x6301;&#x7EED;&#x5411;&#x4E0B;&#x626B;&#x63CF;. &#x6BCF;&#x5F53;&#x6765;&#x5230;&#x4E00;&#x4E2A;&#x523B;&#x5EA6;&#x65F6;&#xFF0C;&#x5219;&#x53D6;&#x51FA;&#x94FE;&#x8868;&#x4E2D;&#x8F6E;&#x6B21;&#x4E3A; 0 &#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FDB;&#x884C;&#x6267;&#x884C;. &#x8FD9;&#x5C31;&#x662F;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#x7684;&#x6838;&#x5FC3;&#x601D;&#x8DEF;.</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-1372c94a8de48a692ea5565ad51db9ec_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="12-%E5%A4%9A%E7%BA%A7%E6%97%B6%E9%97%B4%E8%BD%AE">1.2 &#x591A;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;</h2><p>&#x63A5;&#x4E0B;&#x6765;&#x804A;&#x4E00;&#x804A;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x7684;&#x7B49;&#x7EA7;&#x5236;&#x5EA6;&#x4E0E;&#x591A;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x6982;&#x5FF5;.</p><p>&#x9996;&#x5148;&#x634B;&#x4E00;&#x634B;&#xFF0C;&#x65F6;&#x95F4;&#x8F6E;&#x6BCF;&#x4E2A;&#x5468;&#x671F;&#x8F6E;&#x6B21;&#x4E2D;&#xFF0C;&#x4F7F;&#x7528;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x5BB9;&#x91CF;&#x4E0E;&#x6240;&#x8868;&#x8FBE;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x4E4B;&#x95F4;&#x7684;&#x5173;&#x7CFB;.</p><p>&#x6211;&#x4EEC;&#x628A;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x7684;&#x6BCF;&#x4E2A;&#x523B;&#x5EA6;&#x8BB0;&#x4E3A;&#x4E00;&#x4E2A; slot&#xFF0C;&#x6BCF;&#x4E2A; slot &#x8868;&#x793A;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x8BB0;&#x4E3A; t.</p><p>&#x5047;&#x8BBE;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x603B;&#x5171;&#x5305;&#x542B; 2m &#x4E2A; slot&#xFF0C;&#x6C42;&#x95EE;&#x5982;&#x4F55;&#x7EC4;&#x7EC7;&#x6211;&#x4EEC;&#x7684;&#x65F6;&#x95F4;&#x8F6E;&#x6570;&#x636E;&#x7ED3;&#x6784;&#xFF0C;&#x80FD;&#x591F;&#x4F7F;&#x5F97;&#x65F6;&#x95F4;&#x8F6E;&#x6BCF;&#x4E2A;&#x8F6E;&#x6B21;&#x5BF9;&#x5E94;&#x8868;&#x8FBE;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x5C3D;&#x53EF;&#x80FD;&#x7684;&#x957F;. &#xFF08;&#x4E00;&#x4E2A;&#x8F6E;&#x6B21;&#x5BF9;&#x5E94;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x8D8A;&#x957F;&#xFF0C;&#x5728;&#x65F6;&#x95F4;&#x6D41;&#x901D;&#x8FC7;&#x7A0B;&#x4E2D;&#x8F6E;&#x6B21;&#x7684;&#x8FED;&#x4EE3;&#x901F;&#x5EA6;&#x5C31;&#x8D8A;&#x6162;&#xFF0C;&#x4E8E;&#x662F;&#x6BCF;&#x4E2A; slot &#x5BF9;&#x5E94;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x94FE;&#x8868;&#x957F;&#x5EA6;&#x5C31;&#x8D8A;&#x77ED;&#xFF0C;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#x7684;&#x68C0;&#x7D22;&#x6548;&#x7387;&#x5C31;&#x8D8A;&#x9AD8;.&#xFF09;</p><p>&#x8FD9;&#x91CC;&#x6700;&#x7B80;&#x5355;&#x7684;&#x65B9;&#x5F0F;&#x5C31;&#x662F;&#x8FDB;&#x884C;&#x91C7;&#x7528;&#x4E00;&#x7EF4;&#x7EB5;&#x5411;&#x6392;&#x5217;&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x90A3;&#x4E48;&#x80FD;&#x591F;&#x8868;&#x8FBE;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x5C31;&#x662F; 2m * t&#xFF0C;&#x67D0;&#x4E2A;&#x523B;&#x5EA6;&#x5BF9;&#x5E94;&#x7684;&#x65F6;&#x95F4;&#x503C;&#x5C31;&#x8BB0;&#x4E3A; {slot_i}.</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-a88bdfd8971bc26cefd9ac843f8e94f6_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x53E6;&#x4E00;&#x79CD;&#x601D;&#x8DEF;&#x662F;&#xFF0C;&#x6211;&#x4EEC;&#x5728;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x5EFA;&#x7ACB;&#x4E00;&#x79CD;&#x7B49;&#x7EA7;&#x79E9;&#x5E8F;.</p><p>&#x6BD4;&#x5982;&#x6211;&#x4EEC;&#x5C06; 2m &#x4E2A; slot &#x62C6;&#x6210;&#x4E24;&#x4E2A;&#x7B49;&#x7EA7;&#x2014;&#x2014;level1 &#x548C; level2. &#x6700;&#x7EC8;&#x6211;&#x4EEC;&#x901A;&#x8FC7; {level1_slot}_{level2_slot} &#x7684;&#x65B9;&#x5F0F;&#x8FDB;&#x884C;&#x65F6;&#x95F4;&#x7684;&#x8868;&#x8FBE;.</p><p>&#x6211;&#x4EEC;&#x7ED9; level2 &#x5206;&#x914D; m &#x4E2A; slot&#xFF0C;&#x5176;&#x4E2D;&#x6BCF;&#x4E2A; slot &#x5BF9;&#x5E94;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x540C;&#x6837;&#x4E3A; t. &#x800C; level1 &#x540C;&#x6837;&#x4E5F;&#x5206;&#x914D; m &#x4E2A; slot&#xFF0C;&#x4F46;&#x662F;&#x6B64;&#x65F6;&#x5176;&#x4E2D;&#x6BCF;&#x4E2A; slot &#x5BF9;&#x5E94;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x5E94;&#x8BE5;&#x4E3A; m * t&#xFF0C;&#x56E0;&#x4E3A;&#x5728; level1 &#x4E2D;&#x7684; slot &#x786E;&#x5B9A;&#x65F6;&#xFF0C;level2 &#x4E2D;&#x8FD8;&#x6709; m &#x79CD; slot &#x7684;&#x7EC4;&#x5408;&#x65B9;&#x5F0F;.</p><p>&#x5982;&#x6B64;&#x4E00;&#x6765;&#xFF0C;&#x8FD9;&#x79CD;&#x7EC4;&#x7EC7;&#x65B9;&#x5F0F;&#x4E0B;&#xFF0C;&#x65F6;&#x95F4;&#x8F6E;&#x5355;&#x4E2A;&#x8F6E;&#x6B21;&#x6240;&#x80FD;&#x8868;&#x8FBE;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x5C31;&#x662F; m * m * t.</p><p>&#x8FD9;&#x91CC;&#x63A2;&#x8BA8;&#x7684;&#x6838;&#x5FC3;&#x4E0D;&#x662F;&#x5177;&#x4F53;&#x67D0;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x7ED3;&#x679C;&#xFF0C;&#x800C;&#x662F;&#x629B;&#x51FA;&#x4E86;&#x4E00;&#x79CD;&#x591A;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x601D;&#x8DEF;&#xFF0C;&#x4ECE;&#x4E00;&#x5230;&#x4E8C;&#x662F;&#x8D28;&#x53D8;&#xFF0C;&#x4ECE;&#x4E8C;&#x5230;&#x4E09;&#x3001;&#x4ECE;&#x4E09;&#x5230;&#x56DB;&#x5C31;&#x4EC5;&#x4EC5;&#x662F;&#x91CF;&#x53D8;&#x7684;&#x95EE;&#x9898;&#xFF0C;&#x53EF;&#x4EE5;&#x7EE7;&#x7EED;&#x590D;&#x523B;&#x76F8;&#x540C;&#x7684;&#x601D;&#x8DEF;.</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-76361c074d4b4875081a43895bfd6b50_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x56DE;&#x8FC7;&#x5934;&#x6765;&#x770B;&#xFF0C;&#x6211;&#x4EEC;&#x4F1A;&#x53D1;&#x73B0;&#x65E5;&#x5E38;&#x4F7F;&#x7528;&#x7684;&#x65F6;&#x95F4;&#x8868;&#x8FBE;&#x5F0F;&#x6B63;&#x662F;&#x91C7;&#x7528;&#x4E86;&#x8FD9;&#x6837;&#x4E00;&#x79CD;&#x591A;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x7B49;&#x7EA7;&#x5236;&#x5EA6;&#xFF0C;&#x6BD4;&#x5982;&#x5F53;&#x524D;&#x7684;&#x65F6;&#x523B;&#x4E3A;&#xFF1A;2023-09-23 15:50:00. &#x8FD9;&#x672C;&#x8D28;&#x4E0A;&#x662F;&#x4E00;&#x79CD;&#x901A;&#x8FC7; {year}-{month}-{date}-{hour}-{minute}-{second} &#x7EC4;&#x6210;&#x7684; 6 &#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7B49;&#x7EA7;&#x7ED3;&#x6784;.</p><p>&#x540E;&#x7EED;&#x5728;&#x672C;&#x6587;&#x7B2C; 3 &#x7AE0;&#x63A2;&#x8BA8;&#x5982;&#x4F55;&#x57FA;&#x4E8E; redis zset &#x5B9E;&#x73B0;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x8BDD;&#x9898;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x4F1A;&#x8FDB;&#x4E00;&#x6B65;&#x5229;&#x7528;&#x8FD9;&#x79CD;&#x591A;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x601D;&#x8DEF;&#xFF0C;&#x5C06;&#x6BCF;&#x4E2A;&#x4EFB;&#x52A1;&#x9996;&#x5148;&#x57FA;&#x4E8E;&#x524D; 5 &#x7EA7; {year}-{month}-{date}-{hour}-{minute} &#x7684;&#x7B49;&#x7EA7;&#x8868;&#x8FBE;&#x5F0F;&#x8FDB;&#x884C;&#x5206;&#x949F;&#x7EA7;&#x65F6;&#x95F4;&#x7247;&#x7684;&#x7EB5;&#x5411;&#x62C6;&#x5206;&#xFF0C;&#x6700;&#x7EC8;&#x5728; 1 &#x5206;&#x949F;&#x8303;&#x56F4;&#x5185;&#x8FDB;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6709;&#x5E8F;&#x7EC4;&#x7EC7;&#xFF0C;&#x4FDD;&#x8BC1;&#x5728;&#x6BCF;&#x6B21;&#x63D2;&#x5165;&#x3001;&#x5220;&#x9664;&#x548C;&#x68C0;&#x7D22;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x5904;&#x7406;&#x7684;&#x6570;&#x636E;&#x91CF;&#x7EA7;&#x80FD;&#x591F;&#x7EF4;&#x6301;&#x5728;&#x5206;&#x949F;&#x7EA7;&#x7684;&#x6570;&#x91CF;&#xFF0C;&#x6700;&#x5927;&#x5316;&#x5730;&#x63D0;&#x9AD8;&#x65F6;&#x95F4;&#x8F6E;&#x7ED3;&#x679C;&#x7684;&#x5904;&#x7406;&#x6027;&#x80FD;.</p><h2 id="2-%E5%8D%95%E6%9C%BA%E7%89%88%E5%AE%9E%E7%8E%B0">2 &#x5355;&#x673A;&#x7248;&#x5B9E;&#x73B0;</h2><p>&#x804A;&#x5B8C;&#x539F;&#x7406;&#x90E8;&#x5206;&#xFF0C;&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x4E00;&#x8D77;&#x8FDB;&#x5165;&#x5B9E;&#x6218;&#x73AF;&#x8282;.</p><p>&#x5728;&#x672C;&#x7AE0;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x4F1A;&#x4F7F;&#x7528; golang &#x6807;&#x51C6;&#x5E93;&#x7684;&#x5B9A;&#x65F6;&#x5668;&#x5DE5;&#x5177; time ticker &#x7ED3;&#x5408;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x7684;&#x8BBE;&#x8BA1;&#x601D;&#x8DEF;&#xFF0C;&#x5B9E;&#x73B0;&#x4E00;&#x4E2A;&#x5355;&#x673A;&#x7248;&#x7684;&#x5355;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;.</p><h2 id="21-%E6%A0%B8%E5%BF%83%E7%B1%BB">2.1 &#x6838;&#x5FC3;&#x7C7B;</h2><h3 id="211-%E6%97%B6%E9%97%B4%E8%BD%AE">2.1.1 &#x65F6;&#x95F4;&#x8F6E;</h3><p>&#x5728;&#x5BF9;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;&#x4E2D;&#xFF0C;&#x6838;&#x5FC3;&#x5B57;&#x6BB5;&#x5982;&#x4E0B;&#x56FE;&#x6240;&#x793A;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-4a4c3ace51290539c0470688c30e312e_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5728;&#x51E0;&#x4E2A;&#x6838;&#x5FC3;&#x5B57;&#x6BB5;&#x4E2D;&#xFF1A;</p><ul><li>slots&#x2014;&#x2014;&#x7C7B;&#x4F3C;&#x4E8E;&#x65F6;&#x949F;&#x7684;&#x8868;&#x76D8;</li><li>curSlot&#x2014;&#x2014;&#x7C7B;&#x4F3C;&#x4E8E;&#x65F6;&#x949F;&#x7684;&#x6307;&#x9488;</li><li>ticker &#x662F;&#x4F7F;&#x7528; golang &#x6807;&#x51C6;&#x5E93;&#x7684;&#x5B9A;&#x65F6;&#x5668;&#x5DE5;&#x5177;&#xFF0C;&#x7C7B;&#x4F3C;&#x4E8E;&#x9A71;&#x52A8;&#x6307;&#x9488;&#x8FD0;&#x8F6C;&#x7684;&#x9F7F;&#x8F6E;</li></ul><p>&#x5728;&#x521B;&#x5EFA;&#x65F6;&#x95F4;&#x8F6E;&#x5B9E;&#x4F8B;&#x65F6;&#xFF0C;&#x4F1A;&#x901A;&#x8FC7;&#x4E00;&#x4E2A;&#x5F02;&#x6B65;&#x7684;&#x5E38;&#x9A7B; goroutine &#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x68C0;&#x7D22;&#x3001;&#x6DFB;&#x52A0;&#x3001;&#x5220;&#x9664;&#x7B49;&#x64CD;&#x4F5C;&#xFF0C;&#x5E76;&#x901A;&#x8FC7;&#x51E0;&#x4E2A; channel &#x8FDB;&#x884C; goroutine &#x7684;&#x6267;&#x884C;&#x903B;&#x8F91;&#x548C;&#x751F;&#x547D;&#x5468;&#x671F;&#x7684;&#x63A7;&#x5236;&#xFF1A;</p><ul><li>stopc&#xFF1A;&#x7528;&#x4E8E;&#x505C;&#x6B62; goroutine</li><li>addTaskCh&#xFF1A;&#x7528;&#x4E8E;&#x63A5;&#x6536;&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x5668;&#x6307;&#x4EE4;</li><li>removeTaskCh&#xFF1A;&#x7528;&#x4E8E;&#x63A5;&#x6536;&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6307;&#x4EE4;</li></ul><pre><code class="language-text">// &#x5355;&#x673A;&#x7248;&#x65F6;&#x95F4;&#x8F6E;
type TimeWheel struct {
    // &#x5355;&#x4F8B;&#x5DE5;&#x5177;&#xFF0C;&#x4FDD;&#x8BC1;&#x65F6;&#x95F4;&#x8F6E;&#x505C;&#x6B62;&#x64CD;&#x4F5C;&#x53EA;&#x80FD;&#x6267;&#x884C;&#x4E00;&#x6B21;
    sync.Once
    // &#x65F6;&#x95F4;&#x8F6E;&#x8FD0;&#x884C;&#x65F6;&#x95F4;&#x95F4;&#x9694;
    interval     time.Duration
    // &#x65F6;&#x95F4;&#x8F6E;&#x5B9A;&#x65F6;&#x5668;
    ticker       *time.Ticker
    // &#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;&#x7684; channel
    stopc        chan struct{}
    // &#x65B0;&#x589E;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5165;&#x53E3; channel  
    addTaskCh    chan *taskElement
    // &#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5165;&#x53E3; channel
    removeTaskCh chan string
    // &#x901A;&#x8FC7; list &#x7EC4;&#x6210;&#x7684;&#x73AF;&#x72B6;&#x6570;&#x7EC4;. &#x901A;&#x8FC7;&#x904D;&#x5386;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x7684;&#x65B9;&#x5F0F;&#x5B9E;&#x73B0;&#x65F6;&#x95F4;&#x8F6E;
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6570;&#x91CF;&#x8F83;&#x5927;&#xFF0C;&#x6BCF;&#x4E2A; slot &#x69FD;&#x5185;&#x53EF;&#x80FD;&#x5B58;&#x5728;&#x591A;&#x4E2A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x56E0;&#x6B64;&#x901A;&#x8FC7; list &#x8FDB;&#x884C;&#x7EC4;&#x88C5;
    slots        []*list.List
    // &#x5F53;&#x524D;&#x904D;&#x5386;&#x5230;&#x7684;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x7684;&#x7D22;&#x5F15;
    curSlot      int
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1; key &#x5230;&#x4EFB;&#x52A1;&#x8282;&#x70B9;&#x7684;&#x6620;&#x5C04;&#xFF0C;&#x4FBF;&#x4E8E;&#x5728; list &#x4E2D;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x8282;&#x70B9;
    keyToETask   map[string]*list.Element
}</code></pre><p>&#x6B64;&#x5904;&#x6709;&#x51E0;&#x4E2A;&#x6280;&#x672F;&#x7EC6;&#x8282;&#x9700;&#x8981;&#x63D0;&#x53CA;&#xFF1A;</p><p><strong>&#x9996;&#x5148;&#xFF1A;</strong>&#x6240;&#x8C13;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x6307;&#x7684;&#x662F;&#x903B;&#x8F91;&#x610F;&#x4E49;&#x4E0A;&#x7684;. &#x5728;&#x5B9E;&#x9645;&#x7684;&#x5B9E;&#x73B0;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x4F1A;&#x901A;&#x8FC7;&#x4E00;&#x4E2A;&#x5B9A;&#x957F;&#x6570;&#x7EC4;&#x7ED3;&#x5408;&#x5FAA;&#x73AF;&#x904D;&#x5386;&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x6765;&#x5B9E;&#x73B0;&#x8FD9;&#x4E2A;&#x903B;&#x8F91;&#x610F;&#x4E49;&#x4E0A;&#x7684;&#x201C;&#x73AF;&#x72B6;&#x201D;&#x6027;&#x8D28;.</p><p><strong>&#x5176;&#x6B21;&#xFF1A;</strong>&#x6570;&#x7EC4;&#x6BCF;&#x4E00;&#x8F6E;&#x80FD;&#x8868;&#x8FBE;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#x662F;&#x56FA;&#x5B9A;&#x7684;. &#x6BCF;&#x5F53;&#x5728;&#x6DFB;&#x52A0;&#x6DFB;&#x52A0;&#x4E00;&#x4E2A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x9700;&#x8981;&#x6839;&#x636E;&#x5176;&#x5EF6;&#x8FDF;&#x7684;&#x76F8;&#x5BF9;&#x65F6;&#x957F;&#x63A8;&#x7B97;&#x51FA;&#x5176;&#x6240;&#x5904;&#x7684; slot &#x4F4D;&#x7F6E;&#xFF0C;&#x5176;&#x4E2D;&#x53EF;&#x80FD;&#x8DE8;&#x904D;&#x5386;&#x8F6E;&#x6B21;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x8FD9;&#x65F6;&#x5019;&#x9700;&#x8981;&#x989D;&#x5916;&#x901A;&#x8FC7;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4E2D;&#x7684; cycle &#x5B57;&#x6BB5;&#x6765;&#x8BB0;&#x5F55;&#x8FD9;&#x4E00;&#x4FE1;&#x606F;&#xFF0C;&#x907F;&#x514D;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x88AB;&#x63D0;&#x524D;&#x6267;&#x884C;.</p><p><strong>&#x6700;&#x540E;&#xFF1A;</strong>&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x4E00;&#x4E2A; slot &#x53EF;&#x80FD;&#x9700;&#x8981;&#x6302;&#x8F7D;&#x591A;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x56E0;&#x6B64;&#x9488;&#x5BF9;&#x6BCF;&#x4E2A; slot&#xFF0C;&#x9700;&#x8981;&#x91C7;&#x7528; golang &#x6807;&#x51C6;&#x5E93; container/list &#x4E2D;&#x5B9E;&#x73B0;&#x7684;&#x53CC;&#x5411;&#x94FE;&#x8868;&#x8FDB;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6570;&#x636E;&#x7684;&#x5B58;&#x50A8;.</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-5656f8176bf346ead8fc932872eebde6_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h3 id="212-%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1">2.1.2 &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</h3><p>&#x4E0B;&#x9762;&#x662F;&#x5BF9;&#x4E00;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;&#xFF1A;</p><ul><li>key&#xFF1A;&#x6BCF;&#x4E2A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5168;&#x5C40;&#x552F;&#x4E00;&#x6807;&#x8BC6;&#x952E;</li><li>task&#xFF1A;&#x5305;&#x542B;&#x4E86;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6267;&#x884C;&#x903B;&#x8F91;&#x7684;&#x95ED;&#x5305;&#x51FD;&#x6570;</li><li>pos&#xFF1A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5728;&#x73AF;&#x5F62;&#x6570;&#x7EC4;&#x6240;&#x5904;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;&#x5373;&#x6570;&#x7EC4;&#x7684;&#x7D22;&#x5F15; index</li><li>cycle&#xFF1A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5EF6;&#x8FDF;&#x8F6E;&#x6B21;. &#x65F6;&#x95F4;&#x8F6E;&#x7684; curSlot &#x6307;&#x9488;&#x6BCF;&#x5B8C;&#x6210;&#x4E00;&#x6574;&#x8F6E;&#x7684;&#x6570;&#x7EC4;&#x904D;&#x5386;&#xFF0C;&#x6240;&#x6709;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684; cycle &#x6307;&#x6570;&#x90FD;&#x9700;&#x8981;&#x51CF; 1. &#x5F53;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; cycle &#x6307;&#x6570;&#x4E3A; 0 &#x65F6;&#xFF0C;&#x4EE3;&#x8868;&#x8BE5;&#x4EFB;&#x52A1;&#x5728;&#x5F53;&#x524D;&#x904D;&#x5386;&#x8F6E;&#x6B21;&#x6267;&#x884C;.</li></ul><pre><code class="language-text">// &#x5C01;&#x88C5;&#x4E86;&#x4E00;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x660E;&#x7EC6;&#x4FE1;&#x606F;
type taskElement struct {
    // &#x5185;&#x805A;&#x4E86;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6267;&#x884C;&#x903B;&#x8F91;&#x7684;&#x95ED;&#x5305;&#x51FD;&#x6570;
    task  func()
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6302;&#x8F7D;&#x5728;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x7D22;&#x5F15;&#x4F4D;&#x7F6E;
    pos   int
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5EF6;&#x8FDF;&#x8F6E;&#x6B21;. &#x6307;&#x7684;&#x662F; curSlot &#x6307;&#x9488;&#x8FD8;&#x8981;&#x626B;&#x63CF;&#x8FC7;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x591A;&#x5C11;&#x8F6E;&#xFF0C;&#x624D;&#x6EE1;&#x8DB3;&#x6267;&#x884C;&#x8BE5;&#x4EFB;&#x52A1;&#x7684;&#x6761;&#x4EF6;
    cycle int
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x552F;&#x4E00;&#x6807;&#x8BC6;&#x952E;
    key   string
}</code></pre><h2 id="22-%E6%9E%84%E9%80%A0%E5%99%A8">2.2 &#x6784;&#x9020;&#x5668;</h2><p>&#x5728;&#x521B;&#x5EFA;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x6784;&#x9020;&#x5668;&#x51FD;&#x6570;&#x4E2D;&#xFF0C;&#x9700;&#x8981;&#x4F20;&#x5165;&#x4E24;&#x4E2A;&#x5165;&#x53C2;&#xFF1A;</p><ul><li>slotNum&#xFF1A;&#x7531;&#x4F7F;&#x7528;&#x65B9;&#x6307;&#x5B9A; slot &#x7684;&#x4E2A;&#x6570;&#xFF0C;&#x9ED8;&#x8BA4;&#x4E3A; 10</li><li>interval&#xFF1A;&#x7531;&#x4F7F;&#x7528;&#x65B9;&#x6307;&#x5B9A;&#x6BCF;&#x4E2A; slot &#x5BF9;&#x5E94;&#x7684;&#x65F6;&#x95F4;&#x8303;&#x56F4;&#xFF0C;&#x9ED8;&#x8BA4;&#x4E3A; 1 &#x79D2;</li></ul><p>&#x521D;&#x59CB;&#x5316;&#x65F6;&#x95F4;&#x8F6E;&#x5B9E;&#x4F8B;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x4F1A;&#x5B8C;&#x6210;&#x5B9A;&#x65F6;&#x5668; ticker &#x4EE5;&#x53CA;&#x5404;&#x4E2A; channel &#x7684;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x5E76;&#x9488;&#x5BF9;&#x6570;&#x7EC4; &#x4E2D;&#x7684;&#x5404;&#x4E2A; slot &#x8FDB;&#x884C;&#x521D;&#x59CB;&#x5316;&#xFF0C;&#x6BCF;&#x4E2A; slot &#x4F4D;&#x7F6E;&#x90FD;&#x9700;&#x8981;&#x586B;&#x5145;&#x4E00;&#x4E2A; list.</p><p>&#x6BCF;&#x4E2A;&#x65F6;&#x95F4;&#x8F6E;&#x5B9E;&#x4F8B;&#x90FD;&#x4F1A;&#x5F02;&#x6B65;&#x8C03;&#x7528; run &#x65B9;&#x6CD5;&#xFF0C;&#x542F;&#x52A8;&#x4E00;&#x4E2A;&#x5E38;&#x9A7B; goroutine &#x7528;&#x4E8E;&#x63A5;&#x6536;&#x548C;&#x5904;&#x7406;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;.</p><pre><code class="language-text">// &#x521B;&#x5EFA;&#x5355;&#x673A;&#x7248;&#x65F6;&#x95F4;&#x8F6E; slotNum&#x2014;&#x2014;&#x65F6;&#x95F4;&#x8F6E;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x957F;&#x5EA6;  interval&#x2014;&#x2014;&#x626B;&#x63CF;&#x65F6;&#x95F4;&#x95F4;&#x9694;
func NewTimeWheel(slotNum int, interval time.Duration) *TimeWheel {
    // &#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x957F;&#x5EA6;&#x9ED8;&#x8BA4;&#x4E3A; 10
    if slotNum &lt;= 0 {
        slotNum = 10
    }
    // &#x626B;&#x63CF;&#x65F6;&#x95F4;&#x95F4;&#x9694;&#x9ED8;&#x8BA4;&#x4E3A; 1 &#x79D2;
    if interval &lt;= 0 {
        interval = time.Second
    }


    // &#x521D;&#x59CB;&#x5316;&#x65F6;&#x95F4;&#x8F6E;&#x5B9E;&#x4F8B;
    t := TimeWheel{
        interval:     interval,
        ticker:       time.NewTicker(interval),
        stopc:        make(chan struct{}),
        keyToETask:   make(map[string]*list.Element),
        slots:        make([]*list.List, 0, slotNum),
        addTaskCh:    make(chan *taskElement),
        removeTaskCh: make(chan string),
    }
    for i := 0; i &lt; slotNum; i++ {
        t.slots = append(t.slots, list.New())
    }
    
    // &#x5F02;&#x6B65;&#x542F;&#x52A8;&#x65F6;&#x95F4;&#x8F6E;&#x5E38;&#x9A7B; goroutine
    go t.run()
    return &amp;t
}</code></pre><h2 id="23-%E5%90%AF%E5%8A%A8%E4%B8%8E%E5%81%9C%E6%AD%A2">2.3 &#x542F;&#x52A8;&#x4E0E;&#x505C;&#x6B62;</h2><p>&#x65F6;&#x95F4;&#x8F6E;&#x8FD0;&#x884C;&#x7684;&#x6838;&#x5FC3;&#x903B;&#x8F91;&#x4F4D;&#x4E8E; timeWheel.run &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x8BE5;&#x65B9;&#x6CD5;&#x4F1A;&#x901A;&#x8FC7; for &#x5FAA;&#x73AF;&#x7ED3;&#x5408; select &#x591A;&#x8DEF;&#x590D;&#x7528;&#x7684;&#x65B9;&#x5F0F;&#x8FD0;&#x884C;&#xFF0C;&#x5C5E;&#x4E8E; golang &#x4E2D;&#x975E;&#x5E38;&#x5E38;&#x89C1;&#x7684;&#x5F02;&#x6B65;&#x7F16;&#x7A0B;&#x98CE;&#x683C;.</p><p>goroutine &#x8FD0;&#x884C;&#x8FC7;&#x7A0B;&#x4E2D;&#x9700;&#x8981;&#x4ECE;&#x4EE5;&#x4E0B;&#x56DB;&#x7C7B; channel &#x4E2D;&#x63A5;&#x6536;&#x4E0D;&#x540C;&#x7684;&#x4FE1;&#x53F7;&#xFF0C;&#x5E76;&#x8FDB;&#x884C;&#x903B;&#x8F91;&#x7684;&#x5206;&#x53D1;&#x5904;&#x7406;&#xFF1A;</p><ul><li>stopc&#xFF1A;&#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;&#xFF0C;&#x4F7F;&#x5F97;&#x5F53;&#x524D; goroutine &#x9000;&#x51FA;</li><li>ticker&#xFF1A;&#x63A5;&#x6536;&#x5230; ticker &#x7684;&#x4FE1;&#x53F7;&#x8BF4;&#x660E;&#x65F6;&#x95F4;&#x7531;&#x5F80;&#x524D;&#x63A8;&#x8FDB;&#x4E86;&#x4E00;&#x4E2A; interval&#xFF0C;&#x5219;&#x9700;&#x8981;&#x6279;&#x91CF;&#x68C0;&#x7D22;&#x5E76;&#x6267;&#x884C;&#x5F53;&#x524D; slot &#x4E2D;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;. &#x5E76;&#x63A8;&#x8FDB;&#x6307;&#x9488; curSlot &#x5F80;&#x524D;&#x504F;&#x79FB;</li><li>addTaskCh&#xFF1A;&#x63A5;&#x6536;&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6307;&#x4EE4;</li><li>removeTaskCh&#xFF1A;&#x63A5;&#x6536;&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6307;&#x4EE4;</li></ul><p>&#x6B64;&#x5904;&#x503C;&#x5F97;&#x4E00;&#x63D0;&#x7684;&#x662F;&#xFF0C;&#x540E;&#x7EED;&#x4E0D;&#x8BBA;&#x662F;&#x521B;&#x5EFA;&#x3001;&#x5220;&#x9664;&#x8FD8;&#x662F;&#x68C0;&#x7D22;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x90FD;&#x662F;&#x901A;&#x8FC7;&#x8FD9;&#x4E2A;&#x5E38;&#x9A7B; goroutine &#x5B8C;&#x6210;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x5728;&#x8BBF;&#x95EE;&#x4E00;&#x4E9B;&#x4E34;&#x754C;&#x8D44;&#x6E90;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4E0D;&#x9700;&#x8981;&#x52A0;&#x9501;&#xFF0C;&#x56E0;&#x4E3A;&#x4E0D;&#x5B58;&#x5728;&#x5E76;&#x53D1;&#x8BBF;&#x95EE;&#x7684;&#x60C5;&#x51B5;</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-e142fac10cf813bc7c940703159d8b55_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">// &#x8FD0;&#x884C;&#x65F6;&#x95F4;&#x8F6E;
func (t *TimeWheel) run() {
    defer func() {
        if err := recover(); err != nil {
            // ...
        }
    }()
 
    // &#x901A;&#x8FC7; for + select &#x7684;&#x4EE3;&#x7801;&#x7ED3;&#x6784;&#x8FD0;&#x884C;&#x4E00;&#x4E2A;&#x5E38;&#x9A7B; goroutine &#x662F;&#x5E38;&#x89C4;&#x64CD;&#x4F5C;
    for {
        select {
        // &#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;
        case &lt;-t.stopc:
            return
        // &#x63A5;&#x6536;&#x5230;&#x5B9A;&#x65F6;&#x4FE1;&#x53F7;
        case &lt;-t.ticker.C:
            // &#x6279;&#x91CF;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
            t.tick()
        // &#x63A5;&#x6536;&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x4FE1;&#x53F7;
        case task := &lt;-t.addTaskCh:
            t.addTask(task)
        // &#x63A5;&#x6536;&#x5230;&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x4FE1;&#x53F7;
        case removeKey := &lt;-t.removeTaskCh:
            t.removeTask(removeKey)
        }
    }
}</code></pre><p>&#x65F6;&#x95F4;&#x8F6E;&#x63D0;&#x4F9B;&#x4E86;&#x4E00;&#x4E2A; Stop &#x65B9;&#x6CD5;&#xFF0C;&#x7528;&#x4E8E;&#x624B;&#x52A8;&#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;&#xFF0C;&#x56DE;&#x6536;&#x5BF9;&#x5E94;&#x7684; goroutine &#x548C; ticker &#x8D44;&#x6E90;.</p><p>&#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x64CD;&#x4F5C;&#x662F;&#x901A;&#x8FC7;&#x5173;&#x95ED; stopc channel &#x5B8C;&#x6210;&#x7684;&#xFF0C;&#x7531;&#x4E8E; channel &#x4E0D;&#x5141;&#x8BB8;&#x88AB;&#x53CD;&#x590D;&#x5173;&#x95ED;&#xFF0C;&#x56E0;&#x6B64;&#x8FD9;&#x91CC;&#x901A;&#x8FC7; sync.Once &#x4FDD;&#x8BC1;&#x8BE5;&#x903B;&#x8F91;&#x53EA;&#x88AB;&#x8C03;&#x7528;&#x4E00;&#x6B21;.</p><pre><code class="language-text">// &#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;
func (t *TimeWheel) Stop() {
    // &#x901A;&#x8FC7;&#x5355;&#x4F8B;&#x5DE5;&#x5177;&#xFF0C;&#x4FDD;&#x8BC1; channel &#x53EA;&#x80FD;&#x88AB;&#x5173;&#x95ED;&#x4E00;&#x6B21;&#xFF0C;&#x907F;&#x514D; panic
    t.Do(func() {
        // &#x5B9A;&#x5236;&#x5B9A;&#x65F6;&#x5668; ticker
        t.ticker.Stop()
        // &#x5173;&#x95ED;&#x5B9A;&#x65F6;&#x5668;&#x8FD0;&#x884C;&#x7684; stopc
        close(t.stopc)
    })
}</code></pre><h2 id="24-%E5%88%9B%E5%BB%BA%E4%BB%BB%E5%8A%A1">2.4 &#x521B;&#x5EFA;&#x4EFB;&#x52A1;</h2><p>&#x521B;&#x5EFA;&#x4E00;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li>&#x4F7F;&#x7528;&#x65B9;&#x5F80; addTaskCh &#x4E2D;&#x6295;&#x9012;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x7531;&#x5E38;&#x9A7B; goroutine &#x63A5;&#x6536;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</li><li>&#x6839;&#x636E;&#x6267;&#x884C;&#x65F6;&#x95F4;&#xFF0C;&#x63A8;&#x7B97;&#x51FA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6240;&#x5904;&#x7684; slot &#x4F4D;&#x7F6E;&#x4EE5;&#x53CA;&#x9700;&#x8981;&#x5EF6;&#x8FDF;&#x7684;&#x8F6E;&#x6B21; cycle</li><li>&#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5305;&#x88C5;&#x6210;&#x4E00;&#x4E2A; list node&#xFF0C;&#x8FFD;&#x52A0;&#x5230;&#x5BF9;&#x5E94; slot &#x4F4D;&#x7F6E;&#x7684; list &#x5C3E;&#x90E8;</li><li>&#x4EE5;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x552F;&#x4E00;&#x952E;&#x4E3A; key&#xFF0C;list node &#x4E3A; value&#xFF0C;&#x5728; keyToETask map &#x4E2D;&#x5EFA;&#x7ACB;&#x6620;&#x5C04;&#x5173;&#x7CFB;&#xFF0C;&#x65B9;&#x4FBF;&#x540E;&#x7EED;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x65F6;&#x4F7F;&#x7528;</li></ul><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-7599033b0b9970ee853a04a9cd05abf2_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">// &#x6DFB;&#x52A0;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5230;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;
func (t *TimeWheel) AddTask(key string, task func(), executeAt time.Time) {
    // &#x6839;&#x636E;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x63A8;&#x7B97;&#x5F97;&#x5230;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4ECE;&#x5C5E;&#x7684; slot &#x4F4D;&#x7F6E;&#xFF0C;&#x4EE5;&#x53CA;&#x9700;&#x8981;&#x5EF6;&#x8FDF;&#x7684;&#x8F6E;&#x6B21;
    pos, cycle := t.getPosAndCircle(executeAt)
    // &#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x901A;&#x8FC7; channel &#x8FDB;&#x884C;&#x6295;&#x9012;
    t.addTaskCh &lt;- &amp;taskElement{
        pos:   pos,
        cycle: cycle,
        task:  task,
        key:   key,
    }
}</code></pre><pre><code class="language-text">// &#x6839;&#x636E;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x63A8;&#x7B97;&#x5F97;&#x5230;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4ECE;&#x5C5E;&#x7684; slot &#x4F4D;&#x7F6E;&#xFF0C;&#x4EE5;&#x53CA;&#x9700;&#x8981;&#x5EF6;&#x8FDF;&#x7684;&#x8F6E;&#x6B21;
func (t *TimeWheel) getPosAndCircle(executeAt time.Time) (int, int) {
    delay := int(time.Until(executeAt))
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5EF6;&#x8FDF;&#x8F6E;&#x6B21;
    cycle := delay / (len(t.slots) * int(t.interval))
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4ECE;&#x5C5E;&#x7684;&#x73AF;&#x72B6;&#x6570;&#x7EC4; index
    pos := (t.curSlot + delay/int(t.interval)) % len(t.slots)
    return pos, cycle
}</code></pre><pre><code class="language-text">// &#x5E38;&#x9A7B; goroutine &#x63A5;&#x6536;&#x5230;&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x540E;&#x7684;&#x5904;&#x7406;&#x903B;&#x8F91;
func (t *TimeWheel) addTask(task *taskElement) {
    // &#x83B7;&#x53D6;&#x5230;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4ECE;&#x5C5E;&#x7684;&#x73AF;&#x72B6;&#x6570;&#x7EC4; index &#x4EE5;&#x53CA;&#x5BF9;&#x5E94;&#x7684; list
    list := t.slots[task.pos]
    // &#x5018;&#x82E5;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; key &#x4E4B;&#x524D;&#x5DF2;&#x5B58;&#x5728;&#xFF0C;&#x5219;&#x9700;&#x8981;&#x5148;&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
    if _, ok := t.keyToETask[task.key]; ok {
        t.removeTask(task.key)
    }
    // &#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FFD;&#x52A0;&#x5230; list &#x5C3E;&#x90E8;
    eTask := list.PushBack(task)
    // &#x5EFA;&#x7ACB;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; key &#x5230;&#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6240;&#x5904;&#x7684;&#x8282;&#x70B9;
    t.keyToETask[task.key] = eTask
}</code></pre><h2 id="25-%E5%88%A0%E9%99%A4%E4%BB%BB%E5%8A%A1">2.5 &#x5220;&#x9664;&#x4EFB;&#x52A1;</h2><p>&#x5220;&#x9664;&#x4E00;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li>&#x4F7F;&#x7528;&#x65B9;&#x5F80; removeTaskCh &#x4E2D;&#x6295;&#x9012;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x7684; key&#xFF0C;&#x7531;&#x5E38;&#x9A7B; goroutine &#x63A5;&#x6536;&#x5904;&#x7406;</li><li>&#x4ECE; keyToETask map &#x4E2D;&#xFF0C;&#x627E;&#x5230;&#x8BE5;&#x4EFB;&#x52A1;&#x5BF9;&#x5E94;&#x7684; list node</li><li>&#x4ECE; keyToETask map &#x4E2D;&#x79FB;&#x9664;&#x8BE5;&#x7EC4; kv &#x5BF9;</li><li>&#x4ECE;&#x5BF9;&#x5E94; slot &#x7684; list &#x4E2D;&#x79FB;&#x9664;&#x8BE5; list node</li></ul><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-6eda26fcea1cae1123707cb69bd32741_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">// &#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x6295;&#x9012;&#x4FE1;&#x53F7;
func (t *TimeWheel) RemoveTask(key string) {
    t.removeTaskCh &lt;- key
}</code></pre><pre><code class="language-text">// &#x65F6;&#x95F4;&#x8F6E;&#x5E38;&#x9A7B; goroutine &#x63A5;&#x6536;&#x5230;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x4FE1;&#x53F7;&#x540E;&#xFF0C;&#x6267;&#x884C;&#x7684;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x903B;&#x8F91;
func (t *TimeWheel) removeTask(key string) {
    eTask, ok := t.keyToETask[key]
    if !ok {
        return
    }
    // &#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8282;&#x70B9;&#x4ECE;&#x6620;&#x5C04; map &#x4E2D;&#x79FB;&#x9664;
    delete(t.keyToETask, key)
    // &#x83B7;&#x53D6;&#x5230;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8282;&#x70B9;&#x540E;&#xFF0C;&#x5C06;&#x5176;&#x4ECE; list &#x4E2D;&#x79FB;&#x9664;
    task, _ := eTask.Value.(*taskElement)
    _ = t.slots[task.pos].Remove(eTask)
}</code></pre><h2 id="26-%E6%89%A7%E8%A1%8C%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1">2.6 &#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</h2><p>&#x6700;&#x540E;&#x6765;&#x634B;&#x4E00;&#x4E0B;&#x6700;&#x6838;&#x5FC3;&#x7684;&#x94FE;&#x8DEF;&#x2014;&#x2014;&#x68C0;&#x7D22;&#x5E76;&#x6279;&#x91CF;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6D41;&#x7A0B;.</p><p>&#x9996;&#x5148;&#xFF0C;&#x6BCF;&#x5F53;&#x63A5;&#x6536;&#x5230; ticker &#x4FE1;&#x53F7;&#x65F6;&#xFF0C;&#x4F1A;&#x6839;&#x636E;&#x5F53;&#x524D;&#x7684; curSlot &#x6307;&#x9488;&#xFF0C;&#x83B7;&#x53D6;&#x5230;&#x5BF9;&#x5E94; slot &#x4F4D;&#x7F6E;&#x6302;&#x8F7D;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; list&#xFF0C;&#x8C03;&#x7528; execute &#x65B9;&#x6CD5;&#x6267;&#x884C;&#x5176;&#x4E2D;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;. &#x6700;&#x540E;&#x901A;&#x8FC7; circularIncr &#x65B9;&#x6CD5;&#x63A8;&#x8FDB; curSlot &#x6307;&#x9488;&#x5411;&#x524D;&#x79FB;&#x52A8;.</p><pre><code class="language-text">// &#x5E38;&#x9A7B; goroutine &#x6BCF;&#x6B21;&#x63A5;&#x6536;&#x5230;&#x5B9A;&#x65F6;&#x4FE1;&#x53F7;&#x540E;&#x7528;&#x4E8E;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x903B;&#x8F91;
func (t *TimeWheel) tick() {
    // &#x6839;&#x636E; curSlot &#x83B7;&#x53D6;&#x5230;&#x5F53;&#x524D;&#x6240;&#x5904;&#x7684;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x7D22;&#x5F15;&#x4F4D;&#x7F6E;&#xFF0C;&#x53D6;&#x51FA;&#x5BF9;&#x5E94;&#x7684; list
    list := t.slots[t.curSlot]
     // &#x5728;&#x65B9;&#x6CD5;&#x8FD4;&#x56DE;&#x524D;&#xFF0C;&#x63A8;&#x8FDB; curSlot &#x6307;&#x9488;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;&#x8FDB;&#x884C;&#x73AF;&#x72B6;&#x904D;&#x5386;
    defer t.circularIncr()
    // &#x6279;&#x91CF;&#x5904;&#x7406;&#x6EE1;&#x8DB3;&#x6267;&#x884C;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
    t.execute(list)
}</code></pre><p>&#x5728; execute &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x4F1A;&#x5BF9; list &#x4E2D;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FDB;&#x884C;&#x904D;&#x5386;&#xFF1A;</p><ul><li>&#x5BF9;&#x4E8E; cycle &gt; 0 &#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x8BF4;&#x660E;&#x5F53;&#x524D;&#x8FD8;&#x672A;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x6761;&#x4EF6;&#xFF0C;&#x9700;&#x8981;&#x5C06;&#x5176; cycle &#x503C;&#x51CF; 1&#xFF0C;&#x7559;&#x5F85;&#x540E;&#x7EED;&#x8F6E;&#x6B21;&#x518D;&#x5904;&#x7406;</li><li>&#x5BF9;&#x4E8E; cycle = 0 &#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x5F00;&#x542F;&#x4E00;&#x4E2A; goroutine &#xFF0C;&#x6267;&#x884C;&#x5176;&#x4E2D;&#x7684;&#x95ED;&#x5305;&#x51FD;&#x6570; task&#xFF0C;&#x5E76;&#x5C06;&#x5176;&#x4ECE; list &#x548C; map &#x4E2D;&#x79FB;&#x9664;</li></ul><pre><code class="language-text">// &#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x6BCF;&#x6B21;&#x5904;&#x7406;&#x4E00;&#x4E2A; list
func (t *TimeWheel) execute(l *list.List) {
    // &#x904D;&#x5386; list
    for e := l.Front(); e != nil; {
        // &#x83B7;&#x53D6;&#x5230;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x5BF9;&#x5E94;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4FE1;&#x606F;
        taskElement, _ := e.Value.(*taskElement)
        // &#x5018;&#x82E5;&#x4EFB;&#x52A1;&#x8FD8;&#x5B58;&#x5728;&#x5EF6;&#x8FDF;&#x8F6E;&#x6B21;&#xFF0C;&#x5219;&#x53EA;&#x5BF9; cycle &#x8BA1;&#x6570;&#x5668;&#x8FDB;&#x884C;&#x6263;&#x51CF;&#xFF0C;&#x672C;&#x8F6E;&#x4E0D;&#x4F5C;&#x4EFB;&#x52A1;&#x7684;&#x6267;&#x884C;
        if taskElement.cycle &gt; 0 {
            taskElement.cycle--
            e = e.Next()
            continue
        }


        // &#x5F53;&#x524D;&#x8282;&#x70B9;&#x5BF9;&#x5E94;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5DF2;&#x8FBE;&#x6210;&#x6267;&#x884C;&#x6761;&#x4EF6;&#xFF0C;&#x5F00;&#x542F;&#x4E00;&#x4E2A; goroutine &#x8D1F;&#x8D23;&#x6267;&#x884C;&#x4EFB;&#x52A1;
        go func() {
            defer func() {
                if err := recover(); err != nil {
                    // ...
                }
            }()
            taskElement.task()
        }()


        // &#x4EFB;&#x52A1;&#x5DF2;&#x6267;&#x884C;&#xFF0C;&#x9700;&#x8981;&#x628A;&#x5BF9;&#x5E94;&#x7684;&#x4EFB;&#x52A1;&#x8282;&#x70B9;&#x4ECE; list &#x4E2D;&#x5220;&#x9664;
        next := e.Next()
        l.Remove(e)
        // &#x628A;&#x4EFB;&#x52A1; key &#x4ECE;&#x6620;&#x5C04; map &#x4E2D;&#x5220;&#x9664;
        delete(t.keyToETask, taskElement.key)
        e = next
    }
}</code></pre><p>&#x5728; circularIncr &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x547C;&#x5E94;&#x4E86;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#x7684;&#x903B;&#x8F91;&#x5904;&#x7406;&#x65B9;&#x5F0F;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-d18354ce2a6891fbc453462c60e75d2d_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">// &#x6BCF;&#x6B21; tick &#x540E;&#x9700;&#x8981;&#x63A8;&#x8FDB; curSlot &#x6307;&#x9488;&#x7684;&#x4F4D;&#x7F6E;&#xFF0C;slots &#x5728;&#x903B;&#x8F91;&#x610F;&#x4E49;&#x4E0A;&#x662F;&#x73AF;&#x72B6;&#x6570;&#x7EC4;&#xFF0C;&#x6240;&#x4EE5;&#x5728;&#x5230;&#x8FBE;&#x5C3E;&#x90E8;&#x65F6;&#x9700;&#x8981;&#x4ECE;&#x65B0;&#x56DE;&#x5230;&#x5934;&#x90E8; 
func (t *TimeWheel) circularIncr() {
    t.curSlot = (t.curSlot + 1) % len(t.slots)
}</code></pre><h2 id="3-%E5%88%86%E5%B8%83%E5%BC%8F%E7%89%88%E5%AE%9E%E7%8E%B0">3 &#x5206;&#x5E03;&#x5F0F;&#x7248;&#x5B9E;&#x73B0;</h2><p>&#x672C;&#x7AE0;&#x6211;&#x4EEC;&#x8BA8;&#x8BBA;&#x4E00;&#x4E0B;&#xFF0C;&#x5982;&#x4F55;&#x57FA;&#x4E8E; redis &#x5B9E;&#x73B0;&#x5206;&#x5E03;&#x5F0F;&#x7248;&#x672C;&#x7684;&#x65F6;&#x95F4;&#x8F6E;&#xFF0C;&#x4EE5;&#x8D34;&#x5408;&#x5B9E;&#x9645;&#x751F;&#x4EA7;&#x73AF;&#x5883;&#x5BF9;&#x5206;&#x5E03;&#x5F0F;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8C03;&#x5EA6;&#x7CFB;&#x7EDF;&#x7684;&#x8BC9;&#x6C42;.</p><p>redis &#x7248;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x5B9E;&#x73B0;&#x601D;&#x8DEF;&#x662F;&#x4F7F;&#x7528; redis &#x4E2D;&#x7684;&#x6709;&#x5E8F;&#x96C6;&#x5408; sorted set&#xFF08;&#x7B80;&#x79F0; zset&#xFF09; &#x8FDB;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5B58;&#x50A8;&#x7BA1;&#x7406;&#xFF0C;&#x5176;&#x4E2D;&#x4EE5;&#x6BCF;&#x4E2A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x5BF9;&#x5E94;&#x7684;&#x65F6;&#x95F4;&#x6233;&#x4F5C;&#x4E3A; zset &#x4E2D;&#x7684; score&#xFF0C;&#x5B8C;&#x6210;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6709;&#x5E8F;&#x6392;&#x5217;&#x7EC4;&#x5408;.</p><p>zset &#x6570;&#x636E;&#x7ED3;&#x6784;&#x7684; redis &#x5B98;&#x65B9;&#x6587;&#x6863;&#x94FE;&#x63A5;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//redis.io/docs/data-types/sorted-sets/" rel="nofollow noreferrer">https://redis.io/docs/data-types/sorted-sets/</a></p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-fda469f364d090eaf48b0f38b62588ee_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x8FD9;&#x91CC;&#x6709;&#x4E24;&#x4E2A;&#x7684;&#x6280;&#x672F;&#x7EC6;&#x8282;&#x9700;&#x8981;&#x63D0;&#x524D;&#x548C;&#x5927;&#x5BB6;&#x540C;&#x6B65;&#xFF1A;</p><ul><li><strong>&#x5206;&#x949F;&#x7EA7;&#x65F6;&#x95F4;&#x5206;&#x7247;&#xFF1A;</strong>&#x4E3A;&#x4E86;&#x907F;&#x514D;&#x4EA7;&#x751F; redis &#x5927; key &#x95EE;&#x9898;&#xFF0C;&#x6B64;&#x5904;&#x91C7;&#x7528;&#x672C;&#x6587; 1.2 &#x5C0F;&#x8282;&#x4E2D;&#x63D0;&#x5230;&#x7684;&#x591A;&#x7EA7;&#x65F6;&#x95F4;&#x8F6E;&#x7B49;&#x7EA7;&#x5236;&#x5EA6;&#xFF0C;&#x4EE5;&#x5206;&#x949F;&#x7684;&#x7EF4;&#x5EA6;&#x8FDB;&#x884C;&#x65F6;&#x95F4;&#x7247;&#x7684;&#x7EB5;&#x5411;&#x5212;&#x5206;&#xFF0C;&#x6BCF;&#x4E2A;&#x5206;&#x949F;&#x7EA7;&#x65F6;&#x95F4;&#x7247;&#x5BF9;&#x5E94;&#x4E00;&#x4E2A;&#x72EC;&#x7ACB;&#x7684; zset &#x6709;&#x5E8F;&#x8868;&#xFF0C;&#x4FDD;&#x8BC1;&#x6BCF;&#x6B21;&#x6267;&#x884C;&#x4EFB;&#x52A1;&#x65F6;&#x5904;&#x7406;&#x7684;&#x6570;&#x636E;&#x89C4;&#x6A21;&#x4EC5;&#x4E3A;&#x5206;&#x949F;&#x7684;&#x91CF;&#x7EA7;</li><li><strong>&#x60F0;&#x6027;&#x5220;&#x9664;&#x673A;&#x5236;&#xFF1A;</strong>&#x4E3A;&#x4E86;&#x7B80;&#x5316;&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x6D41;&#x7A0B;. &#x5728;&#x4F7F;&#x7528;&#x65B9;&#x6307;&#x5B9A;&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x6211;&#x4EEC;&#x4E0D;&#x76F4;&#x63A5;&#x4ECE; zset &#x4E2D;&#x5220;&#x9664;&#x6570;&#x636E;&#xFF0C;&#x800C;&#x662F;&#x989D;&#x5916;&#x8BB0;&#x5F55;&#x4E00;&#x4E2A;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x7684; set. &#x540E;&#x7EED;&#x5728;&#x68C0;&#x7D22;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x901A;&#x8FC7;&#x4F7F;&#x7528; set &#x8FDB;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x8FC7;&#x6EE4;&#xFF0C;&#x5B9E;&#x73B0;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x60F0;&#x6027;&#x5220;&#x9664;.</li></ul><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-634aa85d3818248571212651bddad7b6_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="31-%E6%A0%B8%E5%BF%83%E7%B1%BB">3.1 &#x6838;&#x5FC3;&#x7C7B;</h2><h3 id="311-redis-%E6%97%B6%E9%97%B4%E8%BD%AE">3.1.1 redis &#x65F6;&#x95F4;&#x8F6E;</h3><p>&#x5728; redis &#x7248;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x6709;&#x4E24;&#x4E2A;&#x6838;&#x5FC3;&#x7C7B;&#xFF0C;&#x7B2C;&#x4E00;&#x4E2A;&#x662F;&#x5173;&#x4E8E;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;&#xFF1A;</p><ul><li>redisClient&#xFF1A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x5B58;&#x50A8;&#x662F;&#x57FA;&#x4E8E; redis zset &#x5B9E;&#x73B0;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x9700;&#x8981;&#x5185;&#x7F6E;&#x4E00;&#x4E2A; redis &#x5BA2;&#x6237;&#x7AEF;&#xFF0C;&#x8FD9;&#x90E8;&#x5206;&#x5728; 3.2 &#x5C0F;&#x8282;&#x5C55;&#x5F00;&#xFF1B;</li><li>httpClient&#xFF1A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6267;&#x884C;&#x65F6;&#xFF0C;&#x662F;&#x901A;&#x8FC7;&#x8BF7;&#x6C42;&#x4F7F;&#x7528;&#x65B9;&#x9884;&#x7559;&#x56DE;&#x8C03;&#x5730;&#x5740;&#x7684;&#x65B9;&#x5F0F;&#x5B9E;&#x73B0;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x9700;&#x8981;&#x5185;&#x7F6E;&#x4E00;&#x4E2A; http &#x5BA2;&#x6237;&#x7AEF;</li><li>channel &#xD7; 2&#xFF1A;ticker &#x548C; stopc &#x5BF9;&#x5E94;&#x4E3A; golang &#x6807;&#x51C6;&#x5E93;&#x5B9A;&#x65F6;&#x5668;&#x4EE5;&#x53CA;&#x505C;&#x6B62; goroutine &#x7684;&#x63A7;&#x5236;&#x5668;</li></ul><pre><code class="language-text">// &#x57FA;&#x4E8E; redis &#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x7248;&#x65F6;&#x95F4;&#x8F6E;
type RTimeWheel struct {
    // &#x5185;&#x7F6E;&#x7684;&#x5355;&#x4F8B;&#x5DE5;&#x5177;&#xFF0C;&#x7528;&#x4E8E;&#x4FDD;&#x8BC1; stopc &#x53EA;&#x88AB;&#x5173;&#x95ED;&#x4E00;&#x6B21;
    sync.Once
    // redis &#x5BA2;&#x6237;&#x7AEF;
    redisClient *redis.Client
    // http &#x5BA2;&#x6237;&#x7AEF;. &#x5728;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x5230;.
    httpClient  *thttp.Client
    // &#x7528;&#x4E8E;&#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x63A7;&#x5236;&#x5668; channel
    stopc       chan struct{
    // &#x89E6;&#x53D1;&#x5B9A;&#x65F6;&#x626B;&#x63CF;&#x4EFB;&#x52A1;&#x7684;&#x5B9A;&#x65F6;&#x5668; 
    ticker      *time.Ticker
}</code></pre><h3 id="312-%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1">3.1.2 &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</h3><p>&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x7C7B;&#x578B;&#x5B9A;&#x4E49;&#x5982;&#x4E0B;&#xFF0C;&#x5176;&#x4E2D;&#x5305;&#x62EC;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x552F;&#x4E00;&#x952E; key&#xFF0C;&#x4EE5;&#x53CA;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x56DE;&#x8C03;&#x65F6;&#x9700;&#x8981;&#x4F7F;&#x7528;&#x5230;&#x7684; http &#x534F;&#x8BAE;&#x53C2;&#x6570;.</p><pre><code class="language-text">// &#x4F7F;&#x7528;&#x65B9;&#x63D0;&#x4EA4;&#x7684;&#x6BCF;&#x4E00;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
type RTaskElement struct {
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5168;&#x5C40;&#x552F;&#x4E00; key
    Key         string            `json:&quot;key&quot;`
    // &#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6267;&#x884C;&#x65F6;&#xFF0C;&#x56DE;&#x8C03;&#x7684; http url
    CallbackURL string            `json:&quot;callback_url&quot;`
    // &#x56DE;&#x8C03;&#x65F6;&#x4F7F;&#x7528;&#x7684; http &#x65B9;&#x6CD5;
    Method      string            `json:&quot;method&quot;`
    // &#x56DE;&#x8C03;&#x65F6;&#x4F20;&#x9012;&#x7684;&#x8BF7;&#x6C42;&#x53C2;&#x6570;
    Req         interface{}       `json:&quot;req&quot;`
    // &#x56DE;&#x8C03;&#x65F6;&#x4F7F;&#x7528;&#x7684; http &#x8BF7;&#x6C42;&#x5934;
    Header      map[string]string `json:&quot;header&quot;`
}</code></pre><h2 id="32-redis-lua-%E4%BD%BF%E7%94%A8%E4%BA%8B%E9%A1%B9">3.2 redis lua &#x4F7F;&#x7528;&#x4E8B;&#x9879;</h2><p>&#x672C;&#x9879;&#x76EE;&#x4F7F;&#x7528;&#x7684; redis &#x5BA2;&#x6237;&#x7AEF;&#x662F;&#x6211;&#x4E2A;&#x4EBA;&#x57FA;&#x4E8E; golang-redis &#x5BA2;&#x6237;&#x7AEF; sdk&#x2014;&#x2014;redigo &#x8FDB;&#x4E00;&#x6B65;&#x5C01;&#x88C5;&#x5B9E;&#x73B0;&#x7684;&#xFF0C;redigo &#x7684;&#x5F00;&#x6E90;&#x5730;&#x5740;&#x4E3A;&#xFF1A; <a href="https://link.zhihu.com/?target=https%3A//github.com/gomodule/redigo" rel="nofollow noreferrer">https://github.com/gomodule/redigo</a></p><p>&#x6B64;&#x5904;&#x4E3B;&#x8981;&#x5728; redisClient &#x4E2D;&#x5C01;&#x88C5;&#x4E86;&#x4E00;&#x4E2A; Eval &#x65B9;&#x6CD5;&#xFF0C;&#x4FBF;&#x4E8E;&#x4F7F;&#x7528; redis lua &#x811A;&#x672C;&#x6267;&#x884C;&#x590D;&#x5408;&#x6307;&#x4EE4;.</p><pre><code class="language-text">// Eval&#xFF1A;&#x6267;&#x884C; lua &#x811A;&#x672C;.
// src&#x2014;&#x2014;lua &#x811A;&#x672C;&#x5185;&#x5BB9; keyCount&#x2014;&#x2014;key &#x7684;&#x6570;&#x91CF; keysAndArgs&#x2014;&#x2014;&#x7531; key &#x548C; args &#x7EC4;&#x6210;&#x7684;&#x5217;&#x8868;
func (c *Client) Eval(ctx context.Context, src string, keyCount int, keysAndArgs []interface{}) (interface{}, error) {
    args := make([]interface{}, 2+len(keysAndArgs))
    args[0] = src
    args[1] = keyCount
    copy(args[2:], keysAndArgs)


    // &#x4ECE; redis &#x94FE;&#x63A5;&#x6C60;&#x4E2D;&#x83B7;&#x53D6;&#x4E00;&#x4E2A;&#x8FDE;&#x63A5;
    conn, err := c.pool.GetContext(ctx)
    if err != nil {
        return -1, err
    }
    // &#x4F7F;&#x7528;&#x5B8C;&#x6210;&#x540E;&#x5C06;&#x8FDE;&#x63A5;&#x653E;&#x56DE;&#x6C60;&#x5B50;
    defer conn.Close()
    // &#x6267;&#x884C; lua &#x811A;&#x672C;
    return conn.Do(&quot;EVAL&quot;, args...)
}</code></pre><p>lua &#x811A;&#x672C;&#x662F; redis &#x7684;&#x9AD8;&#x7EA7;&#x529F;&#x80FD;&#xFF0C;&#x80FD;&#x591F;&#x4FDD;&#x8BC1;&#x9488;&#x5728;&#x5355;&#x4E2A; redis &#x8282;&#x70B9;&#x5185;&#x6267;&#x884C;&#x7684;&#x4E00;&#x7CFB;&#x5217;&#x6307;&#x4EE4;&#x5177;&#x5907;&#x539F;&#x5B50;&#x6027;&#xFF0C;&#x4E2D;&#x9014;&#x4E0D;&#x4F1A;&#x88AB;&#x5176;&#x4ED6;&#x64CD;&#x4F5C;&#x8005;&#x6253;&#x65AD;.</p><p>redis lua &#x529F;&#x80FD;&#x4ECB;&#x7ECD;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//redis.io/docs/interact/programmability/eval-intro/" rel="nofollow noreferrer">https://redis.io/docs/interact/programmability/eval-intro/</a></p><p>lua &#x8BED;&#x6CD5;&#x6559;&#x7A0B;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//www.runoob.com/lua/lua-tutorial.html" rel="nofollow noreferrer">https://www.runoob.com/lua/lua-tutorial.html</a></p><p>&#x6B64;&#x5904;&#x4E4B;&#x6240;&#x4EE5;&#x9700;&#x8981;&#x4F7F;&#x7528; lua &#x811A;&#x672C;&#xFF0C;&#x662F;&#x56E0;&#x4E3A;&#x5728;&#x5B9E;&#x73B0;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x5B58;&#x5728;&#x4E00;&#x7CFB;&#x5217;&#x672C;&#x8EAB;&#x4E0D;&#x5177;&#x5907;&#x539F;&#x5B50;&#x6027;&#x4F46;&#x5728;&#x4E1A;&#x52A1;&#x6D41;&#x7A0B;&#x4E2D;&#x4E0D;&#x53EF;&#x62C6;&#x89E3;&#x7684;&#x590D;&#x5408;&#x64CD;&#x4F5C;&#xFF0C;&#x9700;&#x8981;&#x7531; lua &#x811A;&#x672C;&#x8D4B;&#x4E88;&#x5176;&#x539F;&#x5B50;&#x6027;&#x8D28;.</p><p>&#x5728;&#x4F7F;&#x7528; lua &#x65F6;&#xFF0C;&#x5C24;&#x5176;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x70B9;&#x662F;&#xFF0C;&#x53EA;&#x6709;&#x64CD;&#x4F5C;&#x7684;&#x6570;&#x636E;&#x5C5E;&#x4E8E;&#x5355;&#x4E2A; redis &#x8282;&#x70B9;&#x65F6;&#xFF0C;&#x624D;&#x80FD;&#x4FDD;&#x8BC1;&#x5176;&#x539F;&#x5B50;&#x6027;. &#x7136;&#x800C;&#x5728;&#x751F;&#x4EA7;&#x73AF;&#x5883;&#x4E2D;&#xFF0C;redis &#x901A;&#x5E38;&#x91C7;&#x7528;&#x7EB5;&#x5411;&#x5206;&#x6CBB;&#x7684;&#x96C6;&#x7FA4;&#x6A21;&#x5F0F;&#xFF0C;&#x8FD9;&#x4F7F;&#x5F97; key &#x4E0D;&#x540C;&#x7684;&#x6570;&#x636E;&#x53EF;&#x80FD;&#x88AB;&#x5206;&#x53D1;&#x5728;&#x4E0D;&#x540C;&#x7684; redis &#x8282;&#x70B9;&#x4E0A;&#xFF0C;&#x6B64;&#x65F6; lua &#x811A;&#x672C;&#x7684;&#x6027;&#x8D28;&#x5C31;&#x65E0;&#x6CD5;&#x4FDD;&#x8BC1;.</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-f0b0ce17052690688a86a5f71bbca728_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5728;&#x4F7F;&#x7528; lua &#x811A;&#x672C;&#x65F6;&#xFF0C;&#x5018;&#x82E5;&#x4E00;&#x7CFB;&#x5217;&#x590D;&#x5408;&#x64CD;&#x4F5C;&#x90FD;&#x662F;&#x9488;&#x5BF9;&#x4E8E;&#x540C;&#x4E00;&#x4E2A; key&#xFF0C;&#x90A3;&#x4E48;&#x6570;&#x636E;&#x5FC5;&#x7136;&#x4F4D;&#x4E8E;&#x540C;&#x4E00;&#x4E2A;&#x8282;&#x70B9;&#xFF0C;&#x6CA1;&#x6709;&#x4EFB;&#x4F55;&#x7591;&#x8BAE;. &#x5018;&#x82E5;&#x6211;&#x4EEC;&#x5728; lua &#x4E2D;&#x6D89;&#x53CA;&#x5230;&#x5BF9;&#x591A;&#x4E2A; key &#x7684;&#x64CD;&#x4F5C;&#xFF0C;&#x90A3;&#x4E48;&#x8FD9;&#x4E9B; key &#x5BF9;&#x5E94;&#x7684;&#x6570;&#x636E;&#x5C31;&#x53EF;&#x80FD;&#x4ECE;&#x5C5E;&#x4E8E;&#x4E0D;&#x540C;&#x7684; redis &#x8282;&#x70B9;&#xFF0C;&#x6B64;&#x65F6; lua &#x811A;&#x672C;&#x5B58;&#x5728;&#x5931;&#x6548;&#x7684;&#x98CE;&#x9669;.</p><p>&#x9488;&#x5BF9;&#x8FD9;&#x4E2A;&#x95EE;&#x9898;&#xFF0C;&#x672C;&#x9879;&#x76EE;&#x91C7;&#x53D6;&#x7684;&#x662F;&#x5B9A;&#x5236;&#x7684;&#x5206;&#x533A;&#x7B56;&#x7565;&#xFF0C;&#x6765;&#x4FDD;&#x8BC1;&#x6307;&#x5B9A;&#x7684; key &#x4E00;&#x5B9A;&#x88AB;&#x5206;&#x53D1;&#x5230;&#x76F8;&#x540C;&#x7684; redis &#x8282;&#x70B9;&#x4E0A;. &#x6B64;&#x5904;&#x4F7F;&#x7528;&#x7684;&#x65B9;&#x5F0F;&#x662F;&#x901A;&#x8FC7; &quot;{}&quot; &#x8FDB;&#x884C; hash_tag &#x7684;&#x6807;&#x8BC6;&#xFF0C;&#x6240;&#x6709;&#x62E5;&#x6709;&#x76F8;&#x540C; hash_tag &#x7684; key &#x90FD;&#x4E00;&#x5B9A;&#x4F1A;&#x88AB;&#x5206;&#x53D1;&#x5230;&#x76F8;&#x540C;&#x7684;&#x8282;&#x70B9;&#x4E0A;.</p><p>&#x8BE5;&#x5206;&#x533A;&#x7B56;&#x7565;&#x53EF;&#x53C2;&#x89C1; redis &#x5B98;&#x65B9;&#x6587;&#x6863;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//redis.io/commands/cluster-keyslot/" rel="nofollow noreferrer">https://redis.io/commands/cluster-keyslot/</a></p><p>&#x6307;&#x4EE4;&#x793A;&#x4F8B;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">&gt; CLUSTER KEYSLOT somekey
(integer) 11058
&gt; CLUSTER KEYSLOT foo{hash_tag}
(integer) 2515
&gt; CLUSTER KEYSLOT bar{hash_tag}
(integer) 2515</code></pre><h2 id="33-%E6%9E%84%E9%80%A0%E5%99%A8">3.3 &#x6784;&#x9020;&#x5668;</h2><p>&#x5728;&#x6784;&#x9020;&#x65F6;&#x95F4;&#x8F6E;&#x5B9E;&#x4F8B;&#x65F6;&#xFF0C;&#x4F7F;&#x7528;&#x65B9;&#x9700;&#x8981;&#x6CE8;&#x5165; redis &#x5BA2;&#x6237;&#x7AEF;&#x4EE5;&#x53CA; http &#x5BA2;&#x6237;&#x7AEF;.</p><p>&#x5728;&#x521D;&#x59CB;&#x5316;&#x6D41;&#x7A0B;&#x4E2D;&#xFF0C;ticker &#x4E3A; golang &#x6807;&#x51C6;&#x5E93;&#x5B9E;&#x73B0;&#x7684;&#x5B9A;&#x65F6;&#x5668;&#xFF0C;&#x5B9A;&#x65F6;&#x5668;&#x7684;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x95F4;&#x9694;&#x56FA;&#x5B9A;&#x4E3A; 1 s. &#x6B64;&#x5916;&#x4F1A;&#x5F02;&#x6B65;&#x8FD0;&#x884C; run &#x65B9;&#x6CD5;&#xFF0C;&#x542F;&#x52A8;&#x4E00;&#x4E2A;&#x5E38;&#x9A7B; goroutine&#xFF0C;&#x751F;&#x547D;&#x5468;&#x671F;&#x4F1A;&#x901A;&#x8FC7; stopc channel &#x8FDB;&#x884C;&#x63A7;&#x5236;.</p><pre><code class="language-text">// &#x6784;&#x9020; redis &#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x65F6;&#x95F4;&#x8F6E;
func NewRTimeWheel(redisClient *redis.Client, httpClient *thttp.Client) *RTimeWheel {
    // &#x521B;&#x5EFA;&#x65F6;&#x95F4;&#x8F6E;&#x5B9E;&#x4F8B;
    r := RTimeWheel{
        // &#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x5668;&#xFF0C;&#x6BCF;&#x9694; 1 s &#x6267;&#x884C;&#x4E00;&#x6B21;
        ticker:      time.NewTicker(time.Second),
        redisClient: redisClient,
        httpClient:  httpClient,
        stopc:       make(chan struct{}),
    }


    // &#x5F02;&#x6B65;&#x542F;&#x52A8;&#x65F6;&#x95F4;&#x8F6E;
    go r.run()
    return &amp;r
}</code></pre><h2 id="34-%E5%90%AF%E5%8A%A8%E4%B8%8E%E5%81%9C%E6%AD%A2">3.4 &#x542F;&#x52A8;&#x4E0E;&#x505C;&#x6B62;</h2><p>&#x65F6;&#x95F4;&#x8F6E;&#x5E38;&#x9A7B; goroutine &#x8FD0;&#x884C;&#x6D41;&#x7A0B;&#x540C;&#x6837;&#x901A;&#x8FC7; for + select &#x7684;&#x5F62;&#x5F0F;&#x8FD0;&#x884C;&#xFF1A;</p><ul><li>&#x63A5;&#x6536;&#x5230; stopc &#x4FE1;&#x53F7;&#x65F6;&#xFF0C;goroutine &#x9000;&#x51FA;&#xFF0C;&#x65F6;&#x95F4;&#x8F6E;&#x505C;&#x6B62;&#x8FD0;&#x884C;</li><li>&#x63A5;&#x6536;&#x5230; ticker &#x4FE1;&#x53F7;&#x65F6;&#xFF0C;&#x5F00;&#x542F;&#x4E00;&#x4E2A;&#x5F02;&#x6B65; goroutine &#x7528;&#x4E8E;&#x6267;&#x884C;&#x5F53;&#x524D;&#x6279;&#x6B21;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</li></ul><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-04483ec99f7816f616315b076d699f8f_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">// &#x8FD0;&#x884C;&#x65F6;&#x95F4;&#x8F6E;
func (r *RTimeWheel) run() {
    // &#x901A;&#x8FC7; for + select &#x7684;&#x4EE3;&#x7801;&#x7ED3;&#x6784;&#x8FD0;&#x884C;&#x4E00;&#x4E2A;&#x5E38;&#x9A7B; goroutine &#x662F;&#x5E38;&#x89C4;&#x64CD;&#x4F5C;
    for {
        select {
        // &#x63A5;&#x6536;&#x5230;&#x7EC8;&#x6B62;&#x4FE1;&#x53F7;&#xFF0C;&#x5219;&#x9000;&#x51FA; goroutine
        case &lt;-r.stopc:
            return
        // &#x6BCF;&#x6B21;&#x63A5;&#x6536;&#x5230;&#x6765;&#x81EA;&#x5B9A;&#x65F6;&#x5668;&#x7684;&#x4FE1;&#x53F7;&#xFF0C;&#x5219;&#x6279;&#x91CF;&#x626B;&#x63CF;&#x5E76;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
        case &lt;-r.ticker.C:
            // &#x6BCF;&#x6B21; tick &#x83B7;&#x53D6;&#x4EFB;&#x52A1;
            go r.executeTasks()
        }
    }
}</code></pre><p>&#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;&#x7684; Stop &#x65B9;&#x6CD5;&#x901A;&#x8FC7;&#x5173;&#x95ED; stopc &#x4FDD;&#x8BC1;&#x5E38;&#x9A7B; goroutine &#x80FD;&#x591F;&#x53CA;&#x65F6;&#x9000;&#x51FA;.</p><pre><code class="language-text">// &#x505C;&#x6B62;&#x65F6;&#x95F4;&#x8F6E;
func (r *RTimeWheel) Stop() {
    // &#x57FA;&#x4E8E;&#x5355;&#x4F8B;&#x5DE5;&#x5177;&#xFF0C;&#x4FDD;&#x8BC1; stopc &#x53EA;&#x80FD;&#x88AB;&#x5173;&#x95ED;&#x4E00;&#x6B21;
    r.Do(func() {
        // &#x5173;&#x95ED; stopc&#xFF0C;&#x4F7F;&#x5F97;&#x5E38;&#x9A7B; goroutine &#x505C;&#x6B62;&#x8FD0;&#x884C;
        close(r.stopc)
        // &#x7EC8;&#x6B62;&#x5B9A;&#x65F6;&#x5668; ticker
        r.ticker.Stop()
    })
}</code></pre><h2 id="35-%E5%88%9B%E5%BB%BA%E4%BB%BB%E5%8A%A1">3.5 &#x521B;&#x5EFA;&#x4EFB;&#x52A1;</h2><p>&#x5728;&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x6BCF;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x9700;&#x8981;&#x6839;&#x636E;&#x5176;&#x6267;&#x884C;&#x7684;&#x65F6;&#x95F4;&#x627E;&#x5230;&#x4ECE;&#x5C5E;&#x7684;&#x5206;&#x949F;&#x65F6;&#x95F4;&#x7247;.</p><p>&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x771F;&#x6B63;&#x7684;&#x5B58;&#x50A8;&#x903B;&#x8F91;&#x5B9A;&#x4E49;&#x5728;&#x4E00;&#x6BB5; lua &#x811A;&#x672C;&#x4E2D;&#xFF0C;&#x901A;&#x8FC7; redis &#x5BA2;&#x6237;&#x7AEF;&#x7684; Eval &#x65B9;&#x6CD5;&#x6267;&#x884C;.</p><pre><code class="language-text">// &#x6DFB;&#x52A0;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
func (r *RTimeWheel) AddTask(ctx context.Context, key string, task *RTaskElement, executeAt time.Time) error {
    // &#x524D;&#x7F6E;&#x5BF9;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x53C2;&#x6570;&#x8FDB;&#x884C;&#x6821;&#x9A8C;
    if err := r.addTaskPrecheck(task); err != nil {
        return err
    }


    task.Key = key
    // &#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5E8F;&#x5217;&#x5316;&#x6210;&#x5B57;&#x8282;&#x6570;&#x7EC4;
    taskBody, _ := json.Marshal(task)
    // &#x901A;&#x8FC7;&#x6267;&#x884C; lua &#x811A;&#x672C;&#xFF0C;&#x5B9E;&#x73B0;&#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6DFB;&#x52A0; redis zset &#x4E2D;. &#x672C;&#x8D28;&#x4E0A;&#x5E95;&#x5C42;&#x4F7F;&#x7528;&#x7684;&#x662F; zadd &#x6307;&#x4EE4;.
    _, err := r.redisClient.Eval(ctx, LuaAddTasks, 2, []interface{}{
        // &#x5206;&#x949F;&#x7EA7; zset &#x65F6;&#x95F4;&#x7247;
        r.getMinuteSlice(executeAt),
        // &#x6807;&#x8BC6;&#x4EFB;&#x52A1;&#x5220;&#x9664;&#x7684;&#x96C6;&#x5408;
        r.getDeleteSetKey(executeAt),
        // &#x4EE5;&#x6267;&#x884C;&#x65F6;&#x523B;&#x7684;&#x79D2;&#x7EA7;&#x65F6;&#x95F4;&#x6233;&#x4F5C;&#x4E3A; zset &#x4E2D;&#x7684; score
        executeAt.Unix(),
        // &#x4EFB;&#x52A1;&#x660E;&#x7EC6;
        string(taskBody),
        // &#x4EFB;&#x52A1; key&#xFF0C;&#x7528;&#x4E8E;&#x5B58;&#x653E;&#x5728;&#x5220;&#x9664;&#x96C6;&#x5408;&#x4E2D;
        key,
    })
    return err
}</code></pre><p>&#x4E0B;&#x9762;&#x5C55;&#x793A;&#x7684;&#x662F;&#x83B7;&#x53D6;&#x5206;&#x949F;&#x7EA7;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6709;&#x5E8F;&#x8868; minuteSlice &#x4EE5;&#x53CA;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x96C6;&#x5408; deleteSet &#x7684;&#x7EC6;&#x8282;.</p><p>&#x6B64;&#x5904;&#x547C;&#x5E94;&#x4E86; 3.3 &#x5C0F;&#x8282;&#xFF0C;&#x901A;&#x8FC7;&#x4EE5;&#x5206;&#x949F;&#x7EA7;&#x8868;&#x8FBE;&#x5F0F;&#x4F5C;&#x4E3A; {hash_tag} &#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x786E;&#x4FDD; minuteSlice &#x548C; deleteSet &#x4E00;&#x5B9A;&#x4F1A;&#x5206;&#x53D1;&#x5230;&#x76F8;&#x540C;&#x7684; redis &#x8282;&#x70B9;&#x4E4B;&#x4E0A;&#xFF0C;&#x8FDB;&#x4E00;&#x6B65;&#x4FDD;&#x8BC1; lua &#x811A;&#x672C;&#x7684;&#x539F;&#x5B50;&#x6027;&#x80FD;&#x591F;&#x751F;&#x6548;.</p><ul><li>&#x83B7;&#x53D6;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6709;&#x5E8F;&#x8868; key &#x7684;&#x65B9;&#x6CD5;&#xFF1A;</li></ul><pre><code class="language-text">func (r *RTimeWheel) getMinuteSlice(executeAt time.Time) string {
    return fmt.Sprintf(&quot;xiaoxu_timewheel_task_{%s}&quot;, util.GetTimeMinuteStr(executeAt))
}</code></pre><ul><li>&#x83B7;&#x53D6;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x96C6;&#x5408; key &#x7684;&#x65B9;&#x6CD5;&#xFF1A;</li></ul><pre><code class="language-text">func (r *RTimeWheel) getDeleteSetKey(executeAt time.Time) string {
    return fmt.Sprintf(&quot;xiaoxu_timewheel_delset_{%s}&quot;, util.GetTimeMinuteStr(executeAt))
}</code></pre><p>&#x4E0B;&#x9762;&#x5C55;&#x793A;&#x4E00;&#x4E0B;&#x521B;&#x5EFA;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6D41;&#x7A0B;&#x4E2D; lua &#x811A;&#x672C;&#x7684;&#x6267;&#x884C;&#x903B;&#x8F91;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-897ee3fa422a897d26f19ded52bfddb4_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">const (
    // &#x6DFB;&#x52A0;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x5982;&#x679C;&#x5B58;&#x5728;&#x5220;&#x9664; key &#x7684;&#x6807;&#x8BC6;&#xFF0C;&#x5219;&#x5C06;&#x5176;&#x5220;&#x9664;
    // &#x6DFB;&#x52A0;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x6839;&#x636E;&#x65F6;&#x95F4;&#xFF08;&#x6240;&#x5C5E;&#x7684; min&#xFF09;&#x51B3;&#x5B9A;&#x6570;&#x636E;&#x4ECE;&#x5C5E;&#x4E8E;&#x54EA;&#x4E2A;&#x5206;&#x7247;{}
    LuaAddTasks = `
       -- &#x83B7;&#x53D6;&#x7684;&#x9996;&#x4E2A; key &#x4E3A; zset &#x7684; key
       local zsetKey = KEYS[1]
       -- &#x83B7;&#x53D6;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A; key &#x4E3A;&#x6807;&#x8BC6;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1; set &#x7684; key
       local deleteSetKey = KEYS[2]
       -- &#x83B7;&#x53D6;&#x7684;&#x7B2C;&#x4E00;&#x4E2A; arg &#x4E3A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5728; zset &#x4E2D;&#x7684; score
       local score = ARGV[1]
       -- &#x83B7;&#x53D6;&#x7684;&#x7B2C;&#x4E8C;&#x4E2A; arg &#x4E3A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x660E;&#x7EC6;&#x6570;&#x636E;
       local task = ARGV[2]
       -- &#x83B7;&#x53D6;&#x7684;&#x7B2C;&#x4E09;&#x4E2A; arg &#x4E3A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x552F;&#x4E00;&#x952E;&#xFF0C;&#x7528;&#x4E8E;&#x5C06;&#x5176;&#x4ECE;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1; set &#x4E2D;&#x79FB;&#x9664;
       local taskKey = ARGV[3]
       -- &#x6BCF;&#x6B21;&#x6DFB;&#x52A0;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x90FD;&#x76F4;&#x63A5;&#x5C06;&#x5176;&#x4ECE;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1; set &#x4E2D;&#x79FB;&#x9664;&#xFF0C;&#x4E0D;&#x7BA1;&#x4E4B;&#x524D;&#x662F;&#x5426;&#x5728; set &#x4E2D;
       redis.call(&apos;srem&apos;,deleteSetKey,taskKey)
       -- &#x8C03;&#x7528; zadd &#x6307;&#x4EE4;&#xFF0C;&#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x6DFB;&#x52A0;&#x5230; zset &#x4E2D;
       return redis.call(&apos;zadd&apos;,zsetKey,score,task)
    `
)</code></pre><h2 id="36-%E5%88%A0%E9%99%A4%E4%BB%BB%E5%8A%A1">3.6 &#x5220;&#x9664;&#x4EFB;&#x52A1;</h2><p>&#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x65B9;&#x5F0F;&#x662F;&#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FFD;&#x52A0;&#x5230;&#x5206;&#x949F;&#x7EA7;&#x7684;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1; set &#x4E2D;. &#x4E4B;&#x540E;&#x5728;&#x68C0;&#x7D22;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x4F1A;&#x6839;&#x636E;&#x8FD9;&#x4E2A; set &#x5BF9;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FDB;&#x884C;&#x8FC7;&#x6EE4;&#xFF0C;&#x5B9E;&#x73B0;&#x60F0;&#x6027;&#x5220;&#x9664;&#x673A;&#x5236;.</p><pre><code class="language-text">// &#x4ECE; redis &#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x5220;&#x9664;&#x4E00;&#x4E2A;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
func (r *RTimeWheel) RemoveTask(ctx context.Context, key string, executeAt time.Time) error {
    // &#x6267;&#x884C; lua &#x811A;&#x672C;&#xFF0C;&#x5C06;&#x88AB;&#x5220;&#x9664;&#x7684;&#x4EFB;&#x52A1;&#x8FFD;&#x52A0;&#x5230; set &#x4E2D;.
    _, err := r.redisClient.Eval(ctx, LuaDeleteTask, 1, []interface{}{
        r.getDeleteSetKey(executeAt),
        key,
    })
    return err
}</code></pre><p>lua &#x6267;&#x884C;&#x903B;&#x8F91;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-341448f1cddde19abed4ceb7df02a6ed_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">const(    
    // &#x5220;&#x9664;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; lua &#x811A;&#x672C;
    LuaDeleteTask = `
       -- &#x83B7;&#x53D6;&#x6807;&#x8BC6;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x7684; set &#x96C6;&#x5408;&#x7684; key
       local deleteSetKey = KEYS[1]
       -- &#x83B7;&#x53D6;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x552F;&#x4E00;&#x952E;
       local taskKey = ARGV[1]
       -- &#x5C06;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x552F;&#x4E00;&#x952E;&#x6DFB;&#x52A0;&#x5230; set &#x4E2D;
       redis.call(&apos;sadd&apos;,deleteSetKey,taskKey)
       -- &#x5018;&#x82E5;&#x662F; set &#x4E2D;&#x7684;&#x9996;&#x4E2A;&#x5143;&#x7D20;&#xFF0C;&#x5219;&#x5BF9; set &#x8BBE;&#x7F6E; 120 s &#x7684;&#x8FC7;&#x671F;&#x65F6;&#x95F4;
       local scnt = redis.call(&apos;scard&apos;,deleteSetKey)
       if (tonumber(scnt) == 1)
       then
           redis.call(&apos;expire&apos;,deleteSetKey,120)
       end
       return scnt
)    `</code></pre><h2 id="37-%E6%89%A7%E8%A1%8C%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1">3.7 &#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</h2><p>&#x5728;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x65F6;&#xFF0C;&#x4F1A;&#x901A;&#x8FC7; getExecutableTasks &#x65B9;&#x6CD5;&#x6279;&#x91CF;&#x83B7;&#x53D6;&#x5230;&#x6EE1;&#x8DB3;&#x6267;&#x884C;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; list&#xFF0C;&#x7136;&#x540E;&#x5E76;&#x53D1;&#x8C03;&#x7528; execute &#x65B9;&#x6CD5;&#x5B8C;&#x6210;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684;&#x56DE;&#x8C03;&#x6267;&#x884C;.</p><pre><code class="language-text">// &#x6279;&#x91CF;&#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
func (r *RTimeWheel) executeTasks() {
    defer func() {
        if err := recover(); err != nil {
            // log
        }
    }()


    // &#x5E76;&#x53D1;&#x63A7;&#x5236;&#xFF0C;&#x4FDD;&#x8BC1; 30 s &#x4E4B;&#x5185;&#x5B8C;&#x6210;&#x8BE5;&#x6279;&#x6B21;&#x5168;&#x91CF;&#x4EFB;&#x52A1;&#x7684;&#x6267;&#x884C;&#xFF0C;&#x53CA;&#x65F6;&#x56DE;&#x6536; goroutine&#xFF0C;&#x907F;&#x514D;&#x53D1;&#x751F; goroutine &#x6CC4;&#x6F0F;
    tctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
    defer cancel()
    // &#x6839;&#x636E;&#x5F53;&#x524D;&#x65F6;&#x95F4;&#x6761;&#x4EF6;&#x626B;&#x63CF; redis zset&#xFF0C;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x6EE1;&#x8DB3;&#x6267;&#x884C;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
    tasks, err := r.getExecutableTasks(tctx)
    if err != nil {
        // log
        return
    }


    // &#x5E76;&#x53D1;&#x6267;&#x884C;&#x4EFB;&#x52A1;&#xFF0C;&#x901A;&#x8FC7; waitGroup &#x8FDB;&#x884C;&#x805A;&#x5408;&#x6536;&#x53E3;
    var wg sync.WaitGroup
    for _, task := range tasks {
        wg.Add(1)
        // shadow
        task := task
        go func() {
            defer func() {
                if err := recover(); err != nil {
                }
                wg.Done()
            }()
            // &#x6267;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
            if err := r.executeTask(tctx, task); err != nil {
                // log
            }
        }()
    }
    wg.Wait()
}</code></pre><h2 id="38-%E6%A3%80%E7%B4%A2%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1">3.8 &#x68C0;&#x7D22;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</h2><p>&#x6700;&#x540E;&#x4ECB;&#x7ECD;&#x4E00;&#x4E0B;&#xFF0C;&#x5982;&#x4F55;&#x6839;&#x636E;&#x5F53;&#x524D;&#x65F6;&#x95F4;&#x83B7;&#x53D6;&#x5230;&#x6EE1;&#x8DB3;&#x6267;&#x884C;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x5217;&#x8868;&#xFF1A;</p><ul><li>&#x6BCF;&#x6B21;&#x68C0;&#x7D22;&#x65F6;&#xFF0C;&#x9996;&#x5148;&#x6839;&#x636E;&#x5F53;&#x524D;&#x65F6;&#x523B;&#xFF0C;&#x63A8;&#x7B97;&#x51FA;&#x6240;&#x4ECE;&#x5C5E;&#x7684;&#x5206;&#x949F;&#x7EA7;&#x65F6;&#x95F4;&#x7247;</li><li>&#x7136;&#x540E;&#x83B7;&#x5F97;&#x5F53;&#x524D;&#x7684;&#x79D2;&#x7EA7;&#x65F6;&#x95F4;&#x6233;&#xFF0C;&#x4F5C;&#x4E3A; zrange &#x6307;&#x4EE4;&#x68C0;&#x7D22;&#x7684; score &#x8303;&#x56F4;</li><li>&#x8C03;&#x7528; lua &#x811A;&#x672C;&#xFF0C;&#x540C;&#x65F6;&#x83B7;&#x53D6;&#x5230;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1; set &#x4EE5;&#x53CA; score &#x8303;&#x56F4;&#x5185;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1; list.</li><li>&#x901A;&#x8FC7; set &#x8FC7;&#x6EE4;&#x6389;&#x88AB;&#x5220;&#x9664;&#x7684;&#x4EFB;&#x52A1;&#xFF0C;&#x7136;&#x540E;&#x8FD4;&#x56DE;&#x6EE1;&#x8DB3;&#x6267;&#x884C;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;</li></ul><pre><code class="language-text">func (r *RTimeWheel) getExecutableTasks(ctx context.Context) ([]*RTaskElement, error) {
    now := time.Now()
    // &#x6839;&#x636E;&#x5F53;&#x524D;&#x65F6;&#x95F4;&#xFF0C;&#x63A8;&#x7B97;&#x51FA;&#x5176;&#x4ECE;&#x5C5E;&#x7684;&#x5206;&#x949F;&#x7EA7;&#x65F6;&#x95F4;&#x7247;
    minuteSlice := r.getMinuteSlice(now)
    // &#x63A8;&#x7B97;&#x51FA;&#x5176;&#x5BF9;&#x5E94;&#x7684;&#x5206;&#x949F;&#x7EA7;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x96C6;&#x5408;
    deleteSetKey := r.getDeleteSetKey(now)
    nowSecond := util.GetTimeSecond(now)
    // &#x4EE5;&#x79D2;&#x7EA7;&#x65F6;&#x95F4;&#x6233;&#x4F5C;&#x4E3A; score &#x8FDB;&#x884C; zset &#x68C0;&#x7D22;
    score1 := nowSecond.Unix()
    score2 := nowSecond.Add(time.Second).Unix()
    // &#x6267;&#x884C; lua &#x811A;&#x672C;&#xFF0C;&#x672C;&#x8D28;&#x4E0A;&#x662F;&#x901A;&#x8FC7; zrange &#x6307;&#x4EE4;&#x7ED3;&#x5408;&#x79D2;&#x7EA7;&#x65F6;&#x95F4;&#x6233;&#x5BF9;&#x5E94;&#x7684; score &#x8FDB;&#x884C;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x68C0;&#x7D22;
    rawReply, err := r.redisClient.Eval(ctx, LuaZrangeTasks, 2, []interface{}{
        minuteSlice, deleteSetKey, score1, score2,
    })
    if err != nil {
        return nil, err
    }


    // &#x7ED3;&#x679C;&#x4E2D;&#xFF0C;&#x9996;&#x4E2A;&#x5143;&#x7D20;&#x5BF9;&#x5E94;&#x4E3A;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x7684; key &#x96C6;&#x5408;&#xFF0C;&#x540E;&#x7EED;&#x5143;&#x7D20;&#x5BF9;&#x5E94;&#x4E3A;&#x5404;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
    replies := gocast.ToInterfaceSlice(rawReply)
    if len(replies) == 0 {
        return nil, fmt.Errorf(&quot;invalid replies: %v&quot;, replies)
    }


    deleteds := gocast.ToStringSlice(replies[0])
    deletedSet := make(map[string]struct{}, len(deleteds))
    for _, deleted := range deleteds {
        deletedSet[deleted] = struct{}{}
    }


    // &#x904D;&#x5386;&#x5404;&#x7B14;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#xFF0C;&#x5018;&#x82E5;&#x5176;&#x5B58;&#x5728;&#x4E8E;&#x5220;&#x9664;&#x96C6;&#x5408;&#x4E2D;&#xFF0C;&#x5219;&#x8DF3;&#x8FC7;&#xFF0C;&#x5426;&#x5219;&#x8FFD;&#x52A0;&#x5230; list &#x4E2D;&#x8FD4;&#x56DE;&#xFF0C;&#x7528;&#x4E8E;&#x540E;&#x7EED;&#x6267;&#x884C;
    tasks := make([]*RTaskElement, 0, len(replies)-1)
    for i := 1; i &lt; len(replies); i++ {
        var task RTaskElement
        if err := json.Unmarshal([]byte(gocast.ToString(replies[i])), &amp;task); err != nil {
            // log
            continue
        }


        if _, ok := deletedSet[task.Key]; ok {
            continue
        }
        tasks = append(tasks, &amp;task)
    }


    return tasks, nil
}</code></pre><p>lua &#x811A;&#x672C;&#x7684;&#x6267;&#x884C;&#x903B;&#x8F91;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-0bfe7c7af2d8c0c92e6af27e311571c2_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><pre><code class="language-text">(    
    // &#x626B;&#x63CF; redis &#x65F6;&#x95F4;&#x8F6E;. &#x83B7;&#x53D6;&#x5206;&#x949F;&#x8303;&#x56F4;&#x5185;,&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x96C6;&#x5408; &#x4EE5;&#x53CA;&#x5728;&#x65F6;&#x95F4;&#x4E0A;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FDB;&#x884C;&#x8FD4;&#x56DE;
    LuaZrangeTasks = `
       -- &#x7B2C;&#x4E00;&#x4E2A; key &#x4E3A;&#x5B58;&#x50A8;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x7684; zset key
       local zsetKey = KEYS[1]
       -- &#x7B2C;&#x4E8C;&#x4E2A; key &#x4E3A;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1; set &#x7684; key
       local deleteSetKey = KEYS[2]
       -- &#x7B2C;&#x4E00;&#x4E2A; arg &#x4E3A; zrange &#x68C0;&#x7D22;&#x7684; score &#x5DE6;&#x8FB9;&#x754C;
       local score1 = ARGV[1]
       -- &#x7B2C;&#x4E8C;&#x4E2A; arg &#x4E3A; zrange &#x68C0;&#x7D22;&#x7684; score &#x53F3;&#x8FB9;&#x754C;
       local score2 = ARGV[2]
       -- &#x83B7;&#x53D6;&#x5230;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x7684;&#x96C6;&#x5408;
       local deleteSet = redis.call(&apos;smembers&apos;,deleteSetKey)
       -- &#x6839;&#x636E;&#x79D2;&#x7EA7;&#x65F6;&#x95F4;&#x6233;&#x5BF9; zset &#x8FDB;&#x884C; zrange &#x68C0;&#x7D22;&#xFF0C;&#x83B7;&#x53D6;&#x5230;&#x6EE1;&#x8DB3;&#x65F6;&#x95F4;&#x6761;&#x4EF6;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;
       local targets = redis.call(&apos;zrange&apos;,zsetKey,score1,score2,&apos;byscore&apos;)
       -- &#x68C0;&#x7D22;&#x5230;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x76F4;&#x63A5;&#x4ECE;&#x65F6;&#x95F4;&#x8F6E;&#x4E2D;&#x79FB;&#x9664;&#xFF0C;&#x4FDD;&#x8BC1;&#x5206;&#x5E03;&#x5F0F;&#x573A;&#x666F;&#x4E0B;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x4E0D;&#x88AB;&#x91CD;&#x590D;&#x83B7;&#x53D6;
       redis.call(&apos;zremrangebyscore&apos;,zsetKey,score1,score2)
       -- &#x8FD4;&#x56DE;&#x7684;&#x7ED3;&#x679C;&#x662F;&#x4E00;&#x4E2A; table
       local reply = {}
       -- table &#x7684;&#x9996;&#x4E2A;&#x5143;&#x7D20;&#x4E3A;&#x5DF2;&#x5220;&#x9664;&#x4EFB;&#x52A1;&#x96C6;&#x5408;
       reply[1] = deleteSet
       -- &#x4F9D;&#x6B21;&#x5C06;&#x68C0;&#x7D22;&#x5230;&#x7684;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8FFD;&#x52A0;&#x5230; table &#x4E2D;
       for i, v in ipairs(targets) do
           reply[#reply+1]=v
       end
       return reply
    `
)</code></pre><h2 id="4-%E6%80%BB%E7%BB%93">4 &#x603B;&#x7ED3;</h2><p>&#x672C;&#x671F;&#x548C;&#x5927;&#x5BB6;&#x63A2;&#x8BA8;&#x4E86;&#x5982;&#x4F55;&#x57FA;&#x4E8E; golang &#x4ECE;&#x96F6;&#x5230;&#x4E00;&#x5B9E;&#x73B0;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#xFF0C;&#x901A;&#x8FC7;&#x539F;&#x7406;&#x7ED3;&#x5408;&#x6E90;&#x7801;&#xFF0C;&#x8BE6;&#x7EC6;&#x5C55;&#x793A;&#x4E86;&#x5355;&#x673A;&#x7248;&#x548C; redis &#x5206;&#x5E03;&#x5F0F;&#x7248;&#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x5B9E;&#x73B0;&#x65B9;&#x5F0F;.</p><p>&#x6700;&#x540E;&#x6211;&#x4EEC;&#x5C55;&#x671B;&#x4E00;&#x4E0B;&#xFF0C;&#x65F6;&#x95F4;&#x8F6E;&#x7B97;&#x6CD5;&#x5728;&#x5DE5;&#x7A0B;&#x5B9E;&#x8DF5;&#x4E2D;&#x5177;&#x4F53;&#x80FD;&#x5F97;&#x5230;&#x600E;&#x6837;&#x7684;&#x5E94;&#x7528;&#x5462;&#xFF1F;</p><p>&#x6B64;&#x524D;&#x6211;&#x57FA;&#x4E8E; redis zset &#x65F6;&#x95F4;&#x8F6E;&#x7684;&#x6A21;&#x578B;&#x5B9E;&#x73B0;&#x4E86;&#x4E00;&#x4E2A;&#x5206;&#x5E03;&#x5F0F;&#x5B9A;&#x65F6;&#x4EFB;&#x52A1;&#x8C03;&#x5EA6;&#x7CFB;&#x7EDF; xtimer&#xFF0C;&#x5927;&#x5BB6;&#x611F;&#x5174;&#x8DA3;&#x7684;&#x8BDD;&#x53EF;&#x4EE5;&#x9605;&#x8BFB;&#x4E00;&#x4E0B;&#x6211;&#x4E4B;&#x524D;&#x5206;&#x4EAB;&#x7684;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#xFF1A;&#x57FA;&#x4E8E;&#x534F;&#x7A0B;&#x6C60;&#x67B6;&#x6784;&#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x5B9A;&#x65F6;&#x5668; XTimer.</p><p>&#x8BE5;&#x9879;&#x76EE;&#x6E90;&#x7801;&#x5DF2;&#x4E8E; github &#x5F00;&#x6E90;&#xFF1A;<a href="https://link.zhihu.com/?target=http%3A//github.com/xiaoxuxiansheng/xtimer" rel="nofollow noreferrer">http://github.com/xiaoxuxiansheng/xtimer</a></p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-8aef261c6597431d07088ea129afc438_720w.webp" class="kg-image" alt loading="lazy"></figure>]]></content:encoded></item><item><title><![CDATA[Linux文本三剑客超详细教程---grep、sed、awk]]></title><description><![CDATA[<p>awk&#x3001;grep&#x3001;sed&#x662F;linux&#x64CD;&#x4F5C;&#x6587;&#x672C;&#x7684;&#x4E09;&#x5927;&#x5229;&#x5668;&#xFF0C;&#x5408;&#x79F0;&#x6587;&#x672C;&#x4E09;&#x5251;&#x5BA2;&#xFF0C;&#x4E5F;&#x662F;&#x5FC5;&#x987B;&#x638C;&#x63E1;&#x7684;linux&#x547D;&#x4EE4;&#x4E4B;&#x4E00;&#x3002;&#x4E09;&#x8005;&#x7684;&#x529F;&#x80FD;&#x90FD;&#x662F;&#x5904;&#x7406;&#x6587;&#x672C;&#xFF0C;</p>]]></description><link>http://www.net-e.cn/linuxwen-ben-san-jian-ke-chao-xiang-xi-jiao-cheng-grep-sed-awk/</link><guid isPermaLink="false">65824c311cca100001bb3f76</guid><dc:creator><![CDATA[Liang Wang]]></dc:creator><pubDate>Wed, 20 Dec 2023 02:07:52 GMT</pubDate><content:encoded><![CDATA[<p>awk&#x3001;grep&#x3001;sed&#x662F;linux&#x64CD;&#x4F5C;&#x6587;&#x672C;&#x7684;&#x4E09;&#x5927;&#x5229;&#x5668;&#xFF0C;&#x5408;&#x79F0;&#x6587;&#x672C;&#x4E09;&#x5251;&#x5BA2;&#xFF0C;&#x4E5F;&#x662F;&#x5FC5;&#x987B;&#x638C;&#x63E1;&#x7684;linux&#x547D;&#x4EE4;&#x4E4B;&#x4E00;&#x3002;&#x4E09;&#x8005;&#x7684;&#x529F;&#x80FD;&#x90FD;&#x662F;&#x5904;&#x7406;&#x6587;&#x672C;&#xFF0C;&#x4F46;&#x4FA7;&#x91CD;&#x70B9;&#x5404;&#x4E0D;&#x76F8;&#x540C;&#xFF0C;&#x5176;&#x4E2D;&#x5C5E;awk&#x529F;&#x80FD;&#x6700;&#x5F3A;&#x5927;&#xFF0C;&#x4F46;&#x4E5F;&#x6700;&#x590D;&#x6742;&#x3002;grep&#x66F4;&#x9002;&#x5408;&#x5355;&#x7EAF;&#x7684;&#x67E5;&#x627E;&#x6216;&#x5339;&#x914D;&#x6587;&#x672C;&#xFF0C;sed&#x66F4;&#x9002;&#x5408;&#x7F16;&#x8F91;&#x5339;&#x914D;&#x5230;&#x7684;&#x6587;&#x672C;&#xFF0C;awk&#x66F4;&#x9002;&#x5408;&#x683C;&#x5F0F;&#x5316;&#x6587;&#x672C;&#xFF0C;&#x5BF9;&#x6587;&#x672C;&#x8FDB;&#x884C;&#x8F83;&#x590D;&#x6742;&#x683C;&#x5F0F;&#x5904;&#x7406;&#x3002;</p><h2 id="1%E3%80%81grep">1&#x3001;grep</h2><h3 id="11-%E4%BB%80%E4%B9%88%E6%98%AFgrep%E5%92%8Cegrep"><strong>1.1 &#x4EC0;&#x4E48;&#x662F;grep&#x548C;egrep</strong></h3><p>Linux&#x7CFB;&#x7EDF;&#x4E2D;grep&#x547D;&#x4EE4;&#x662F;&#x4E00;&#x79CD;&#x5F3A;&#x5927;&#x7684;&#x6587;&#x672C;&#x641C;&#x7D22;&#x5DE5;&#x5177;&#xFF0C;&#x5B83;&#x80FD;&#x4F7F;&#x7528;<strong>&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;</strong>&#x641C;&#x7D22;&#x6587;&#x672C;&#xFF0C;&#x5E76;&#x628A;&#x5339;&#x914D;&#x7684;&#x884C;&#x6253;&#x5370;&#x51FA;&#x6765;&#xFF08;&#x5339;&#x914D;&#x5230;&#x7684;&#x6807;&#x7EA2;&#xFF09;&#x3002;grep&#x5168;&#x79F0;&#x662F;Global Regular Expression Print&#xFF0C;&#x8868;&#x793A;&#x5168;&#x5C40;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x7248;&#x672C;&#xFF0C;&#x5B83;&#x7684;&#x4F7F;&#x7528;&#x6743;&#x9650;&#x662F;&#x6240;&#x6709;&#x7528;&#x6237;&#x3002;</p><p>grep&#x7684;&#x5DE5;&#x4F5C;&#x65B9;&#x5F0F;&#x662F;&#x8FD9;&#x6837;&#x7684;&#xFF0C;&#x5B83;&#x5728;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;&#x6587;&#x4EF6;&#x4E2D;&#x641C;&#x7D22;&#x5B57;&#x7B26;&#x4E32;&#x6A21;&#x677F;&#x3002;&#x5982;&#x679C;&#x6A21;&#x677F;&#x5305;&#x62EC;&#x7A7A;&#x683C;&#xFF0C;&#x5219;&#x5FC5;&#x987B;&#x88AB;&#x5F15;&#x7528;&#xFF0C;&#x6A21;&#x677F;&#x540E;&#x7684;&#x6240;&#x6709;&#x5B57;&#x7B26;&#x4E32;&#x88AB;&#x770B;&#x4F5C;&#x6587;&#x4EF6;&#x540D;&#x3002;&#x641C;&#x7D22;&#x7684;&#x7ED3;&#x679C;&#x88AB;&#x9001;&#x5230;&#x6807;&#x51C6;&#x8F93;&#x51FA;&#xFF0C;&#x4E0D;&#x5F71;&#x54CD;&#x539F;&#x6587;&#x4EF6;&#x5185;&#x5BB9;&#x3002;</p><p>grep&#x53EF;&#x7528;&#x4E8E;shell&#x811A;&#x672C;&#xFF0C;&#x56E0;&#x4E3A;grep&#x901A;&#x8FC7;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x72B6;&#x6001;&#x503C;&#x6765;&#x8BF4;&#x660E;&#x641C;&#x7D22;&#x7684;&#x72B6;&#x6001;&#xFF0C;&#x5982;&#x679C;&#x6A21;&#x677F;&#x641C;&#x7D22;&#x6210;&#x529F;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;0&#xFF0C;&#x5982;&#x679C;&#x641C;&#x7D22;&#x4E0D;&#x6210;&#x529F;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;1&#xFF0C;&#x5982;&#x679C;&#x641C;&#x7D22;&#x7684;&#x6587;&#x4EF6;&#x4E0D;&#x5B58;&#x5728;&#xFF0C;&#x5219;&#x8FD4;&#x56DE;2&#x3002;&#x6211;&#x4EEC;&#x5229;&#x7528;&#x8FD9;&#x4E9B;&#x8FD4;&#x56DE;&#x503C;&#x5C31;&#x53EF;&#x8FDB;&#x884C;&#x4E00;&#x4E9B;&#x81EA;&#x52A8;&#x5316;&#x7684;&#x6587;&#x672C;&#x5904;&#x7406;&#x5DE5;&#x4F5C;&#x3002;</p><p><strong>egrep = grep -E&#xFF1A;&#x6269;&#x5C55;&#x7684;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;</strong> &#xFF08;&#x9664;&#x4E86;<strong>\&lt; , \&gt; , \b </strong>&#x4F7F;&#x7528;&#x5176;&#x4ED6;&#x6B63;&#x5219;&#x90FD;&#x53EF;&#x4EE5;&#x53BB;&#x6389;\&#xFF09;</p><h3 id="12-%E4%BD%BF%E7%94%A8grep"><strong>1.2 &#x4F7F;&#x7528;grep</strong></h3><h3 id="121-%E5%91%BD%E4%BB%A4%E6%A0%BC%E5%BC%8F"><strong>1.2.1 &#x547D;&#x4EE4;&#x683C;&#x5F0F;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">1</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">grep [option] pattern file</td></tr></tbody></table><!--kg-card-end: html--><h3 id="122-%E5%91%BD%E4%BB%A4%E5%8A%9F%E8%83%BD"><strong>1.2.2 &#x547D;&#x4EE4;&#x529F;&#x80FD;</strong></h3><p>&#x7528;&#x4E8E;&#x8FC7;&#x6EE4;/&#x641C;&#x7D22;&#x7684;&#x7279;&#x5B9A;&#x5B57;&#x7B26;&#x3002;&#x53EF;&#x4F7F;&#x7528;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x80FD;&#x591A;&#x79CD;&#x547D;&#x4EE4;&#x914D;&#x5408;&#x4F7F;&#x7528;&#xFF0C;&#x4F7F;&#x7528;&#x4E0A;&#x5341;&#x5206;&#x7075;&#x6D3B;&#x3002;</p><h3 id="123-%E5%91%BD%E4%BB%A4%E5%8F%82%E6%95%B0"><strong>1.2.3 &#x547D;&#x4EE4;&#x53C2;&#x6570;</strong></h3><p>&#x5E38;&#x7528;&#x53C2;&#x6570;&#x5DF2;&#x52A0;&#x7C97;</p><ul><li>-A&lt;&#x663E;&#x793A;&#x884C;&#x6570;&gt;&#xFF1A;&#x9664;&#x4E86;&#x663E;&#x793A;&#x7B26;&#x5408;&#x8303;&#x672C;&#x6837;&#x5F0F;&#x7684;&#x90A3;&#x4E00;&#x5217;&#x4E4B;&#x5916;&#xFF0C;&#x5E76;&#x663E;&#x793A;&#x8BE5;&#x884C;&#x4E4B;&#x540E;&#x7684;&#x5185;&#x5BB9;&#x3002;</li><li>-B&lt;&#x663E;&#x793A;&#x884C;&#x6570;&gt;&#xFF1A;&#x9664;&#x4E86;&#x663E;&#x793A;&#x7B26;&#x5408;&#x6837;&#x5F0F;&#x7684;&#x90A3;&#x4E00;&#x884C;&#x4E4B;&#x5916;&#xFF0C;&#x5E76;&#x663E;&#x793A;&#x8BE5;&#x884C;&#x4E4B;&#x524D;&#x7684;&#x5185;&#x5BB9;&#x3002;</li><li>-C&lt;&#x663E;&#x793A;&#x884C;&#x6570;&gt;&#xFF1A;&#x9664;&#x4E86;&#x663E;&#x793A;&#x7B26;&#x5408;&#x6837;&#x5F0F;&#x7684;&#x90A3;&#x4E00;&#x884C;&#x4E4B;&#x5916;&#xFF0C;&#x5E76;&#x663E;&#x793A;&#x8BE5;&#x884C;&#x4E4B;&#x524D;&#x540E;&#x7684;&#x5185;&#x5BB9;&#x3002;</li><li>-c&#xFF1A;&#x7EDF;&#x8BA1;&#x5339;&#x914D;&#x7684;&#x884C;&#x6570;</li><li><strong>-e &#xFF1A;&#x5B9E;&#x73B0;&#x591A;&#x4E2A;&#x9009;&#x9879;&#x95F4;&#x7684;&#x903B;&#x8F91;or &#x5173;&#x7CFB;</strong></li><li><strong>-E&#xFF1A;&#x6269;&#x5C55;&#x7684;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;</strong></li><li>-f FILE&#xFF1A;&#x4ECE;FILE&#x83B7;&#x53D6;PATTERN&#x5339;&#x914D;</li><li>-F &#xFF1A;&#x76F8;&#x5F53;&#x4E8E;fgrep</li><li>-i --ignore-case #&#x5FFD;&#x7565;&#x5B57;&#x7B26;&#x5927;&#x5C0F;&#x5199;&#x7684;&#x5DEE;&#x522B;&#x3002;</li><li>-n&#xFF1A;&#x663E;&#x793A;&#x5339;&#x914D;&#x7684;&#x884C;&#x53F7;</li><li>-o&#xFF1A;&#x4EC5;&#x663E;&#x793A;&#x5339;&#x914D;&#x5230;&#x7684;&#x5B57;&#x7B26;&#x4E32;</li><li>-q&#xFF1A;&#x9759;&#x9ED8;&#x6A21;&#x5F0F;&#xFF0C;&#x4E0D;&#x8F93;&#x51FA;&#x4EFB;&#x4F55;&#x4FE1;&#x606F;</li><li>-s&#xFF1A;&#x4E0D;&#x663E;&#x793A;&#x9519;&#x8BEF;&#x4FE1;&#x606F;&#x3002;</li><li><strong>-v&#xFF1A;&#x663E;&#x793A;&#x4E0D;&#x88AB;pattern &#x5339;&#x914D;&#x5230;&#x7684;&#x884C;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;[^] &#x53CD;&#x5411;&#x5339;&#x914D;</strong></li><li>-w &#xFF1A;&#x5339;&#x914D; &#x6574;&#x4E2A;&#x5355;&#x8BCD;</li></ul><h3 id="13-grep%E5%AE%9E%E6%88%98%E6%BC%94%E7%A4%BA"><strong>1.3 grep&#x5B9E;&#x6218;&#x6F14;&#x793A;</strong></h3><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-f11ad2ebe0725b97172ce591efb0bd40_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="2%E3%80%81%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F">2&#x3001;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;</h2><h3 id="21-%E8%AE%A4%E8%AF%86%E6%AD%A3%E5%88%99"><strong>2.1 &#x8BA4;&#x8BC6;&#x6B63;&#x5219;</strong></h3><p>&#xFF08;1&#xFF09;&#x4ECB;&#x7ECD;</p><p>&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x5E94;&#x7528;&#x5E7F;&#x6CDB;&#xFF0C;&#x5728;&#x7EDD;&#x5927;&#x591A;&#x6570;&#x7684;&#x7F16;&#x7A0B;&#x8BED;&#x8A00;&#x90FD;&#x53EF;&#x4EE5;&#x5B8C;&#x7F8E;&#x5E94;&#x7528;&#xFF0C;&#x5728;Linux&#x4E2D;&#xFF0C;&#x4E5F;&#x6709;&#x7740;&#x6781;&#x5927;&#x7684;&#x7528;&#x5904;&#x3002;</p><p>&#x4F7F;&#x7528;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF0C;&#x53EF;&#x4EE5;&#x6709;&#x6548;&#x7684;&#x7B5B;&#x9009;&#x51FA;&#x9700;&#x8981;&#x7684;&#x6587;&#x672C;&#xFF0C;&#x7136;&#x540E;&#x7ED3;&#x5408;&#x76F8;&#x5E94;&#x7684;&#x652F;&#x6301;&#x7684;&#x5DE5;&#x5177;&#x6216;&#x8BED;&#x8A00;&#xFF0C;&#x5B8C;&#x6210;&#x4EFB;&#x52A1;&#x9700;&#x6C42;&#x3002;</p><p>&#x5728;&#x672C;&#x7BC7;&#x535A;&#x5BA2;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x4F7F;&#x7528;grep/egrep&#x6765;&#x5B8C;&#x6210;&#x5BF9;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x7684;&#x8C03;&#x7528;</p><p>&#xFF08;2&#xFF09;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x7C7B;&#x578B;</p><p>&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x5F15;&#x64CE;&#x5B9E;&#x73B0;&#xFF0C;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x5F15;&#x64CE;&#x662F;&#x89E3;&#x91CA;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x6A21;&#x5F0F;&#x5E76;&#x4F7F;&#x7528;&#x8FD9;&#x4E9B;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x6587;&#x672C;&#x7684;&#x57FA;&#x7840;&#x8F6F;&#x4EF6;&#x3002;</p><p>&#x5728;Linux&#x4E2D;&#xFF0C;&#x5E38;&#x7528;&#x7684;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x6709;&#xFF1A;</p><ul><li>POSIX &#x57FA;&#x672C;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF08;BRE&#xFF09;&#x5F15;&#x64CE;</li><li>POSIX &#x6269;&#x5C55;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF08;BRE&#xFF09;&#x5F15;&#x64CE;</li></ul><h3 id="22-%E5%9F%BA%E6%9C%AC%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F"><strong>2.2 &#x57FA;&#x672C;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;</strong></h3><h3 id="221-%E5%8C%B9%E9%85%8D%E5%AD%97%E7%AC%A6"><strong>2.2.1 &#x5339;&#x914D;&#x5B57;&#x7B26;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;</p><ul><li>. &#x5339;&#x914D;&#x4EFB;&#x610F;&#x5355;&#x4E2A;&#x5B57;&#x7B26;&#xFF0C;&#x4E0D;&#x80FD;&#x5339;&#x914D;&#x7A7A;&#x884C;</li><li>[] &#x5339;&#x914D;&#x6307;&#x5B9A;&#x8303;&#x56F4;&#x5185;&#x7684;&#x4EFB;&#x610F;&#x5355;&#x4E2A;&#x5B57;&#x7B26;</li><li>[^] &#x53D6;&#x53CD;</li><li>[:alnum:] &#x6216; [0-9a-zA-Z]</li><li>[:alpha:] &#x6216; [a-zA-Z]</li><li>[:upper:] &#x6216; [A-Z]</li><li>[:lower:] &#x6216; [a-z]</li><li>[:blank:] &#x7A7A;&#x767D;&#x5B57;&#x7B26;&#xFF08;&#x7A7A;&#x683C;&#x548C;&#x5236;&#x8868;&#x7B26;&#xFF09;</li><li>[:space:] &#x6C34;&#x5E73;&#x548C;&#x5782;&#x76F4;&#x7684;&#x7A7A;&#x767D;&#x5B57;&#x7B26;&#xFF08;&#x6BD4;[:blank:]&#x5305;&#x542B;&#x7684;&#x8303;&#x56F4;&#x5E7F;&#xFF09;</li><li>[:cntrl:] &#x4E0D;&#x53EF;&#x6253;&#x5370;&#x7684;&#x63A7;&#x5236;&#x5B57;&#x7B26;&#xFF08;&#x9000;&#x683C;&#x3001;&#x5220;&#x9664;&#x3001;&#x8B66;&#x94C3;...&#xFF09;</li><li>[:digit:] &#x5341;&#x8FDB;&#x5236;&#x6570;&#x5B57; &#x6216;[0-9]</li><li>[:xdigit:]&#x5341;&#x516D;&#x8FDB;&#x5236;&#x6570;&#x5B57;</li><li>[:graph:] &#x53EF;&#x6253;&#x5370;&#x7684;&#x975E;&#x7A7A;&#x767D;&#x5B57;&#x7B26;</li><li>[:print:] &#x53EF;&#x6253;&#x5370;&#x5B57;&#x7B26;</li><li>[:punct:] &#x6807;&#x70B9;&#x7B26;&#x53F7;</li></ul><p>&#xFF08;2&#xFF09;&#x6F14;&#x793A;</p><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-9eb2f313a40d43ac3cc7b2fdd241e30e_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h3 id="222-%E9%85%8D%E7%BD%AE%E6%AC%A1%E6%95%B0"><strong>2.2.2 &#x914D;&#x7F6E;&#x6B21;&#x6570;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;</p><ul><li><strong>* </strong>&#x5339;&#x914D;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;&#x4EFB;&#x610F;&#x6B21;&#xFF0C;<strong>&#x5305;&#x62EC;0&#x6B21;</strong>&#xFF0C;&#x8D2A;&#x5A6A;&#x6A21;&#x5F0F;&#xFF1A;&#x5C3D;&#x53EF;&#x80FD;&#x957F;&#x7684;&#x5339;&#x914D;</li><li><strong>.* </strong>&#x4EFB;&#x610F;&#x957F;&#x5EA6;&#x7684;&#x4EFB;&#x610F;&#x5B57;&#x7B26;&#xFF0C;<strong>&#x4E0D;&#x5305;&#x62EC;0&#x6B21;</strong></li><li><strong>\? </strong>&#x5339;&#x914D;&#x5176;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;<strong>0 &#x6216; 1&#x6B21;</strong></li><li><strong>\+</strong> &#x5339;&#x914D;&#x5176;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;<strong>&#x81F3;&#x5C11;1&#x6B21;</strong></li><li>\{n\} &#x5339;&#x914D;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;n&#x6B21;</li><li>\{m,n\} &#x5339;&#x914D;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;&#x81F3;&#x5C11;m &#x6B21;&#xFF0C;&#x81F3;&#x591A;n&#x6B21;</li><li>\{,n\} &#x5339;&#x914D;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;&#x81F3;&#x591A;n&#x6B21;</li><li>\{n,\} &#x5339;&#x914D;&#x524D;&#x9762;&#x7684;&#x5B57;&#x7B26;&#x81F3;&#x5C11;n&#x6B21;</li></ul><p>&#xFF08;2&#xFF09;&#x6F14;&#x793A;</p><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-bf4926f251492f647aea3b20ffa8a342_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h3 id="223-%E4%BD%8D%E7%BD%AE%E9%94%9A%E5%AE%9A%EF%BC%9A%E5%AE%9A%E4%BD%8D%E5%87%BA%E7%8E%B0%E7%9A%84%E4%BD%8D%E7%BD%AE"><strong>2.2.3 &#x4F4D;&#x7F6E;&#x951A;&#x5B9A;&#xFF1A;&#x5B9A;&#x4F4D;&#x51FA;&#x73B0;&#x7684;&#x4F4D;&#x7F6E;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;</p><ul><li>^ &#x884C;&#x9996;&#x951A;&#x5B9A;&#xFF0C;&#x7528;&#x4E8E;&#x6A21;&#x5F0F;&#x7684;&#x6700;&#x5DE6;&#x4FA7;</li><li>$ &#x884C;&#x5C3E;&#x951A;&#x5B9A;&#xFF0C;&#x7528;&#x4E8E;&#x6A21;&#x5F0F;&#x7684;&#x6700;&#x53F3;&#x4FA7;</li><li>^PATTERN$&#xFF0C;&#x7528;&#x4E8E;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x6574;&#x884C;</li><li>^$ &#x7A7A;&#x884C;</li><li>^[[:space:]].*$ &#x7A7A;&#x767D;&#x884C;</li><li>\&lt; &#x6216; \b &#x8BCD;&#x9996;&#x951A;&#x5B9A;&#xFF0C;&#x7528;&#x4E8E;&#x5355;&#x8BCD;&#x6A21;&#x5F0F;&#x7684;&#x5DE6;&#x4FA7;</li><li>\&gt; &#x6216; \b &#x8BCD;&#x5C3E;&#x951A;&#x5B9A;&#xFF1B;&#x7528;&#x4E8E;&#x5355;&#x8BCD;&#x6A21;&#x5F0F;&#x7684;&#x53F3;&#x4FA7;</li><li>\&lt;PATTERN\&gt;</li></ul><p>&#xFF08;2&#xFF09;&#x6F14;&#x793A;</p><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-68ad55b8c3be0694ba58dd4027df9354_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h3 id="224-%E5%88%86%E7%BB%84%E5%92%8C%E5%90%8E%E5%90%91%E5%BC%95%E7%94%A8"><strong>2.2.4 &#x5206;&#x7EC4;&#x548C;&#x540E;&#x5411;&#x5F15;&#x7528;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;</p><p>&#x2460; &#x5206;&#x7EC4;&#xFF1A;\(\) &#x5C06;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;&#x5B57;&#x7B26;&#x6346;&#x7ED1;&#x5728;&#x4E00;&#x8D77;&#xFF0C;&#x5F53;&#x4F5C;&#x4E00;&#x4E2A;&#x6574;&#x4F53;&#x8FDB;&#x884C;&#x5904;&#x7406;</p><p>&#x5206;&#x7EC4;&#x62EC;&#x53F7;&#x4E2D;&#x7684;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x5230;&#x7684;&#x5185;&#x5BB9;&#x4F1A;&#x88AB;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x5F15;&#x64CE;&#x8BB0;&#x5F55;&#x4E8E;&#x5185;&#x90E8;&#x7684;&#x53D8;&#x91CF;&#x4E2D;&#xFF0C;&#x8FD9;&#x4E9B;&#x53D8;&#x91CF;&#x7684;&#x547D;&#x540D;&#x65B9;&#x5F0F;&#x4E3A;: \1, \2, \3, ...</p><h2 id="%E6%9C%80%E8%BF%91%E5%BE%88%E5%A4%9A%E5%B0%8F%E4%BC%99%E4%BC%B4%E6%89%BE%E6%88%91%E8%A6%81%E5%90%84%E7%A7%8D%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99%EF%BC%8C%E4%BD%86%E4%B8%80%E4%B8%AA%E4%B8%AA%E7%A7%81%E4%BF%A1%E5%A4%AA%E8%80%BD%E8%AF%AF%E5%A4%A7%E5%AE%B6%E6%97%B6%E9%97%B4%E4%BA%86%EF%BC%8C%E4%BA%8E%E6%98%AF%E6%88%91%E6%95%B4%E7%90%86%E4%BA%86%E4%B8%80%E4%BA%9B%E4%BC%98%E8%B4%A8%E7%BB%8F%E5%85%B8%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%BA%90%EF%BC%8C%E6%B6%B5%E7%9B%96linux%E3%80%81%E8%99%9A%E6%8B%9F%E5%8C%96%E3%80%81%E5%AE%B9%E5%99%A8%E3%80%81%E4%BA%91%E8%AE%A1%E7%AE%97%E3%80%81%E7%BD%91%E7%BB%9C%E3%80%81python%E7%AD%89%E4%B9%A6%E7%B1%8D%E5%92%8C%E8%A7%86%E9%A2%91%EF%BC%8C%E7%82%B9%E5%87%BB%E9%93%BE%E6%8E%A5%E5%8D%B3%E5%8F%AF%E9%A2%86%E5%8F%96%EF%BC%8C%E7%A5%9D%E5%AD%A6%E4%B8%9A%E6%9C%89%E6%88%90%EF%BC%81%EF%BC%88%E6%97%A0%E4%BB%BB%E4%BD%95%E5%A5%97%E8%B7%AF%EF%BC%81%EF%BC%89">&#x6700;&#x8FD1;&#x5F88;&#x591A;&#x5C0F;&#x4F19;&#x4F34;&#x627E;&#x6211;&#x8981;&#x5404;&#x79CD;&#x5B66;&#x4E60;&#x8D44;&#x6599;&#xFF0C;&#x4F46;&#x4E00;&#x4E2A;&#x4E2A;&#x79C1;&#x4FE1;&#x592A;&#x803D;&#x8BEF;&#x5927;&#x5BB6;&#x65F6;&#x95F4;&#x4E86;&#xFF0C;&#x4E8E;&#x662F;&#x6211;&#x6574;&#x7406;&#x4E86;&#x4E00;&#x4E9B;&#x4F18;&#x8D28;&#x7ECF;&#x5178;&#x5B66;&#x4E60;&#x8D44;&#x6E90;&#xFF0C;&#x6DB5;&#x76D6;Linux&#x3001;&#x865A;&#x62DF;&#x5316;&#x3001;&#x5BB9;&#x5668;&#x3001;&#x4E91;&#x8BA1;&#x7B97;&#x3001;&#x7F51;&#x7EDC;&#x3001;Python&#x7B49;&#x4E66;&#x7C4D;&#x548C;&#x89C6;&#x9891;&#xFF0C;<a href="https://link.zhihu.com/?target=https%3A//www.linuxyz.cn/2378.html" rel="nofollow noreferrer">&#x70B9;&#x51FB;&#x94FE;&#x63A5;&#x5373;&#x53EF;&#x9886;&#x53D6;&#xFF0C;&#x795D;&#x5B66;&#x4E1A;&#x6709;&#x6210;&#xFF01;&#xFF08;&#x65E0;&#x4EFB;&#x4F55;&#x5957;&#x8DEF;&#xFF01;&#xFF09;</a></h2><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-fdd53f281dd1cd22c44c86f6748e3cbb_720w.webp" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//www.linuxyz.cn/2378.html">10T&#x5B66;&#x4E60;&#x8D44;&#x6E90;&#x5927;&#x653E;&#x9001;&#xFF0C;&#x6DB5;&#x76D6;Linux&#x3001;&#x865A;&#x62DF;&#x5316;&#x3001;&#x5BB9;&#x5668;&#x3001;&#x4E91;&#x8BA1;&#x7B97;&#x3001;&#x7F51;&#x7EDC;&#x3001;Python&#x3001;Go&#x7B49;&#x4E66;&#x7C4D;&#x548C;&#x89C6;&#x9891;&#x200B;www.linuxyz.cn/2378.html</a></p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/v2-483087fffd0310a5f3356ad759c9cd59_180x120.jpg" class="kg-image" alt loading="lazy"></figure><p>&#x2461; &#x540E;&#x5411;&#x5F15;&#x7528;</p><p>&#x5F15;&#x7528;&#x524D;&#x9762;&#x7684;&#x5206;&#x7EC4;&#x62EC;&#x53F7;&#x4E2D;&#x7684;&#x6A21;&#x5F0F;&#x6240;&#x5339;&#x914D;&#x5B57;&#x7B26;&#xFF0C;&#x800C;&#x975E;&#x6A21;&#x5F0F;&#x672C;&#x8EAB;</p><p>\1 &#x8868;&#x793A;&#x4ECE;&#x5DE6;&#x4FA7;&#x8D77;&#x7B2C;&#x4E00;&#x4E2A;&#x5DE6;&#x62EC;&#x53F7;&#x4EE5;&#x53CA;&#x4E0E;&#x4E4B;&#x5339;&#x914D;&#x53F3;&#x62EC;&#x53F7;&#x4E4B;&#x95F4;&#x7684;&#x6A21;&#x5F0F;&#x6240;&#x5339;&#x914D;&#x5230;&#x7684;&#x5B57;&#x7B26;</p><p>\2 &#x8868;&#x793A;&#x4ECE;&#x5DE6;&#x4FA7;&#x8D77;&#x7B2C;2&#x4E2A;&#x5DE6;&#x62EC;&#x53F7;&#x4EE5;&#x53CA;&#x4E0E;&#x4E4B;&#x5339;&#x914D;&#x53F3;&#x62EC;&#x53F7;&#x4E4B;&#x95F4;&#x7684;&#x6A21;&#x5F0F;&#x6240;&#x5339;&#x914D;&#x5230;&#x7684;&#x5B57;&#x7B26;&#xFF0C;&#x4EE5;&#x6B64;&#x7C7B;&#x63A8;</p><p>\&amp; &#x8868;&#x793A;&#x524D;&#x9762;&#x7684;&#x5206;&#x7EC4;&#x4E2D;&#x6240;&#x6709;&#x5B57;&#x7B26;</p><p>&#x2462; &#x6D41;&#x7A0B;&#x5206;&#x6790;&#x5982;&#x4E0B;&#xFF1A;</p><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-9643f2f975c1acc1f51ebb4b7bc3ad79_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#xFF08;2&#xFF09;&#x6F14;&#x793A;</p><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-47bce3866f56bf6d3404268a582f21c7_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h3 id="23-%E6%89%A9%E5%B1%95%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F"><strong>2.3 &#x6269;&#x5C55;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;</strong></h3><p>&#xFF08;1&#xFF09;&#x5B57;&#x7B26;&#x5339;&#x914D;&#xFF1A;</p><ul><li>. &#x4EFB;&#x610F;&#x5355;&#x4E2A;&#x5B57;&#x7B26;</li><li>[] &#x6307;&#x5B9A;&#x8303;&#x56F4;&#x7684;&#x5B57;&#x7B26;</li><li>[^] &#x4E0D;&#x5728;&#x6307;&#x5B9A;&#x8303;&#x56F4;&#x7684;&#x5B57;&#x7B26;</li><li>&#x6B21;&#x6570;&#x5339;&#x914D;&#xFF1A;</li><li>* &#xFF1A;&#x5339;&#x914D;&#x524D;&#x9762;&#x5B57;&#x7B26;&#x4EFB;&#x610F;&#x6B21;</li><li>? : 0 &#x6216;1&#x6B21;</li><li>+ &#xFF1A;1 &#x6B21;&#x6216;&#x591A;&#x6B21;</li><li>{m} &#xFF1A;&#x5339;&#x914D;m&#x6B21; &#x6B21;</li><li>{m,n} &#xFF1A;&#x81F3;&#x5C11;m &#xFF0C;&#x81F3;&#x591A;n&#x6B21;</li></ul><p>&#xFF08;2&#xFF09;&#x4F4D;&#x7F6E;&#x951A;&#x5B9A;&#xFF1A;</p><ul><li>^ : &#x884C;&#x9996;</li><li>$ : &#x884C;&#x5C3E;</li><li>\&lt;, \b : &#x8BED;&#x9996;</li><li>\&gt;, \b : &#x8BED;&#x5C3E;</li><li>&#x5206;&#x7EC4;&#xFF1A;()</li><li>&#x540E;&#x5411;&#x5F15;&#x7528;&#xFF1A;\1, \2, ...</li></ul><p>&#xFF08;3&#xFF09;&#x603B;&#x7ED3;</p><p>&#x9664;&#x4E86;\&lt;, \b : &#x8BED;&#x9996;&#x3001;\&gt;, \b : &#x8BED;&#x5C3E;&#xFF1B;&#x4F7F;&#x7528;&#x5176;&#x4ED6;&#x6B63;&#x5219;&#x90FD;&#x53EF;&#x4EE5;&#x53BB;&#x6389;\&#xFF1B;&#x4E0A;&#x9762;&#x6709;&#x6F14;&#x793A;&#x6848;&#x4F8B;&#xFF0C;&#x4E0D;&#x5728;&#x8FDB;&#x884C;&#x6F14;&#x793A;</p><h2 id="3%E3%80%81sed">3&#x3001;sed</h2><h3 id="31-%E8%AE%A4%E8%AF%86sed"><strong>3.1 &#x8BA4;&#x8BC6;sed</strong></h3><p>sed &#x662F;&#x4E00;&#x79CD;&#x6D41;&#x7F16;&#x8F91;&#x5668;&#xFF0C;&#x5B83;&#x4E00;&#x6B21;&#x5904;&#x7406;&#x4E00;<strong>&#x884C;</strong>&#x5185;&#x5BB9;&#x3002;&#x5904;&#x7406;&#x65F6;&#xFF0C;&#x628A;&#x5F53;&#x524D;&#x5904;&#x7406;&#x7684;&#x884C;&#x5B58;&#x50A8;&#x5728;&#x4E34;&#x65F6;&#x7F13;&#x51B2;&#x533A;&#x4E2D;&#xFF0C;&#x79F0;&#x4E3A;&#x201C;<strong>&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;</strong>&#x201D;&#xFF08;patternspace &#xFF09;&#xFF0C;&#x63A5;&#x7740;&#x7528;sed &#x547D;&#x4EE4;&#x5904;&#x7406;&#x7F13;&#x51B2;&#x533A;&#x4E2D;&#x7684;&#x5185;&#x5BB9;&#xFF0C;&#x5904;&#x7406;&#x5B8C;&#x6210;&#x540E;&#xFF0C;&#x628A;&#x7F13;&#x51B2;&#x533A;&#x7684;&#x5185;&#x5BB9;&#x9001;&#x5F80;&#x5C4F;&#x5E55;&#x3002;&#x7136;&#x540E;&#x8BFB;&#x5165;&#x4E0B;&#x884C;&#xFF0C;&#x6267;&#x884C;&#x4E0B;&#x4E00;&#x4E2A;&#x5FAA;&#x73AF;&#x3002;&#x5982;&#x679C;&#x6CA1;&#x6709;&#x4F7F;&#x8BF8;&#x5982;&#x2018;D&#x2019; &#x7684;&#x7279;&#x6B8A;&#x547D;&#x4EE4;&#xFF0C;&#x90A3;&#x4F1A;&#x5728;&#x4E24;&#x4E2A;&#x5FAA;&#x73AF;&#x4E4B;&#x95F4;&#x6E05;&#x7A7A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#xFF0C;&#x4F46;&#x4E0D;&#x4F1A;&#x6E05;&#x7A7A;<strong>&#x4FDD;&#x7559;&#x7A7A;&#x95F4;</strong>&#x3002;&#x8FD9;&#x6837;&#x4E0D;&#x65AD;&#x91CD;&#x590D;&#xFF0C;&#x76F4;&#x5230;&#x6587;&#x4EF6;&#x672B;&#x5C3E;&#x3002;<strong>&#x6587;&#x4EF6;&#x5185;&#x5BB9;&#x5E76;&#x6CA1;&#x6709;&#x6539;&#x53D8;</strong>&#xFF0C;&#x9664;&#x975E;&#x4F60;&#x4F7F;&#x7528;<strong>&#x91CD;&#x5B9A;&#x5411;&#x5B58;&#x50A8;&#x8F93;&#x51FA;&#x6216;-i</strong>&#x3002;</p><p>&#x529F;&#x80FD;&#xFF1A;&#x4E3B;&#x8981;&#x7528;&#x6765;&#x81EA;&#x52A8;&#x7F16;&#x8F91;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;&#x6587;&#x4EF6;, &#x7B80;&#x5316;&#x5BF9;&#x6587;&#x4EF6;&#x7684;&#x53CD;&#x590D;&#x64CD;&#x4F5C;</p><h3 id="32-%E4%BD%BF%E7%94%A8sed"><strong>3.2 &#x4F7F;&#x7528;sed</strong></h3><h3 id="321-%E5%91%BD%E4%BB%A4%E6%A0%BC%E5%BC%8F"><strong>3.2.1 &#x547D;&#x4EE4;&#x683C;&#x5F0F;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">1</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">sed [options] &apos;[&#x5730;&#x5740;&#x5B9A;&#x754C;] command&apos; file(s)</td></tr></tbody></table><!--kg-card-end: html--><h3 id="322-%E5%B8%B8%E7%94%A8%E9%80%89%E9%A1%B9options"><strong>3.2.2 &#x5E38;&#x7528;&#x9009;&#x9879;options</strong></h3><ul><li><strong>-n</strong>&#xFF1A;&#x4E0D;&#x8F93;&#x51FA;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x5185;&#x5BB9;&#x5230;&#x5C4F;&#x5E55;&#xFF0C;&#x5373;&#x4E0D;&#x81EA;&#x52A8;&#x6253;&#x5370;&#xFF0C;&#x53EA;&#x6253;&#x5370;&#x5339;&#x914D;&#x5230;&#x7684;&#x884C;</li><li><strong>-e&#xFF1A;</strong>&#x591A;&#x70B9;&#x7F16;&#x8F91;&#xFF0C;&#x5BF9;&#x6BCF;&#x884C;&#x5904;&#x7406;&#x65F6;&#xFF0C;&#x53EF;&#x4EE5;&#x6709;&#x591A;&#x4E2A;Script</li><li><strong>-f</strong>&#xFF1A;&#x628A;Script&#x5199;&#x5230;&#x6587;&#x4EF6;&#x5F53;&#x4E2D;&#xFF0C;&#x5728;&#x6267;&#x884C;sed&#x65F6;-f &#x6307;&#x5B9A;&#x6587;&#x4EF6;&#x8DEF;&#x5F84;&#xFF0C;&#x5982;&#x679C;&#x662F;&#x591A;&#x4E2A;Script&#xFF0C;&#x6362;&#x884C;&#x5199;</li><li><strong>-r</strong>&#xFF1A;&#x652F;&#x6301;<strong>&#x6269;&#x5C55;&#x7684;&#x6B63;&#x5219;</strong>&#x8868;&#x8FBE;&#x5F0F;</li><li><strong>-i</strong>&#xFF1A;&#x76F4;&#x63A5;&#x5C06;&#x5904;&#x7406;&#x7684;&#x7ED3;&#x679C;&#x5199;&#x5165;&#x6587;&#x4EF6;</li><li><strong>-i.bak</strong>&#xFF1A;&#x5728;&#x5C06;&#x5904;&#x7406;&#x7684;&#x7ED3;&#x679C;&#x5199;&#x5165;&#x6587;&#x4EF6;&#x4E4B;&#x524D;&#x5907;&#x4EFD;&#x4E00;&#x4EFD;</li></ul><h3 id="323-%E5%9C%B0%E5%9D%80%E5%AE%9A%E7%95%8C"><strong>3.2.3 &#x5730;&#x5740;&#x5B9A;&#x754C;</strong></h3><ul><li>&#x4E0D;&#x7ED9;&#x5730;&#x5740;&#xFF1A;&#x5BF9;&#x5168;&#x6587;&#x8FDB;&#x884C;&#x5904;&#x7406;</li><li>&#x5355;&#x5730;&#x5740;&#xFF1A;</li><li>#: &#x6307;&#x5B9A;&#x7684;&#x884C;</li><li>/pattern/&#xFF1A;&#x88AB;&#x6B64;&#x5904;&#x6A21;&#x5F0F;&#x6240;&#x80FD;&#x591F;&#x5339;&#x914D;&#x5230;&#x7684;&#x6BCF;&#x4E00;&#x884C;</li><li>&#x5730;&#x5740;&#x8303;&#x56F4;&#xFF1A;</li><li>#,#</li><li>#,+#</li><li>/pat1/,/pat2/</li><li>#,/pat1/</li><li><strong>~&#xFF1A;&#x6B65;&#x8FDB;</strong></li><li>sed -n<strong> &apos;1~2p&apos; </strong>&#x53EA;&#x6253;&#x5370;&#x5947;&#x6570;&#x884C; &#xFF08;1~2 &#x4ECE;&#x7B2C;1&#x884C;&#xFF0C;&#x4E00;&#x6B21;&#x52A0;2&#x884C;&#xFF09;</li><li>sed -n <strong>&apos;2~2p&apos;</strong> &#x53EA;&#x6253;&#x5370;&#x5076;&#x6570;&#x884C;</li></ul><h3 id="324-%E7%BC%96%E8%BE%91%E5%91%BD%E4%BB%A4command"><strong>3.2.4 &#x7F16;&#x8F91;&#x547D;&#x4EE4;command</strong></h3><ul><li><strong>d&#xFF1A;&#x5220;&#x9664;</strong>&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x5339;&#x914D;&#x7684;&#x884C;&#xFF0C;&#x5E76;&#x7ACB;&#x5373;&#x542F;&#x7528;&#x4E0B;&#x4E00;&#x8F6E;&#x5FAA;&#x73AF;</li><li><strong>p&#xFF1A;&#x6253;&#x5370;</strong>&#x5F53;&#x524D;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x5185;&#x5BB9;&#xFF0C;&#x8FFD;&#x52A0;&#x5230;&#x9ED8;&#x8BA4;&#x8F93;&#x51FA;&#x4E4B;&#x540E;</li><li><strong>a</strong>&#xFF1A;&#x5728;&#x6307;&#x5B9A;&#x884C;<strong>&#x540E;&#x9762;&#x8FFD;&#x52A0;</strong>&#x6587;&#x672C;&#xFF0C;&#x652F;&#x6301;&#x4F7F;&#x7528;\n&#x5B9E;&#x73B0;&#x591A;&#x884C;&#x8FFD;&#x52A0;</li><li><strong>i</strong>&#xFF1A;&#x5728;&#x884C;<strong>&#x524D;&#x9762;&#x63D2;&#x5165;</strong>&#x6587;&#x672C;&#xFF0C;&#x652F;&#x6301;&#x4F7F;&#x7528;\n&#x5B9E;&#x73B0;&#x591A;&#x884C;&#x8FFD;&#x52A0;</li><li><strong>c</strong>&#xFF1A;<strong>&#x66FF;&#x6362;</strong>&#x884C;&#x4E3A;&#x5355;&#x884C;&#x6216;&#x591A;&#x884C;&#x6587;&#x672C;&#xFF0C;&#x652F;&#x6301;&#x4F7F;&#x7528;\n&#x5B9E;&#x73B0;&#x591A;&#x884C;&#x8FFD;&#x52A0;</li><li>w&#xFF1A;&#x4FDD;&#x5B58;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x7684;&#x884C;&#x81F3;&#x6307;&#x5B9A;&#x6587;&#x4EF6;</li><li>r&#xFF1A;&#x8BFB;&#x53D6;&#x6307;&#x5B9A;&#x6587;&#x4EF6;&#x7684;&#x6587;&#x672C;&#x81F3;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x5339;&#x914D;&#x5230;&#x7684;&#x884C;&#x540E;</li><li>=&#xFF1A;&#x4E3A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x7684;&#x884C;&#x6253;&#x5370;&#x884C;&#x53F7;</li><li><strong>!</strong>&#xFF1A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x5339;&#x914D;&#x884C;<strong>&#x53D6;&#x53CD;</strong>&#x5904;&#x7406;</li><li><strong>s///</strong>&#xFF1A;<strong>&#x67E5;&#x627E;&#x66FF;&#x6362;</strong>&#xFF0C;&#x652F;&#x6301;&#x4F7F;&#x7528;&#x5176;&#x5B83;&#x5206;&#x9694;&#x7B26;&#xFF0C;&#x5982;&#xFF1A;s@@@&#xFF0C;s###&#xFF1B;</li><li><strong>&#x52A0;g&#x8868;&#x793A;&#x884C;&#x5185;&#x5168;&#x5C40;&#x66FF;&#x6362;&#xFF1B;</strong></li><li>&#x5728;&#x66FF;&#x6362;&#x65F6;&#xFF0C;&#x53EF;&#x4EE5;&#x52A0;&#x4E00;&#x4E0B;&#x547D;&#x4EE4;&#xFF0C;&#x5B9E;&#x73B0;&#x5927;&#x5C0F;&#x5199;&#x8F6C;&#x6362;</li><li>\l&#xFF1A;&#x628A;&#x4E0B;&#x4E2A;&#x5B57;&#x7B26;&#x8F6C;&#x6362;&#x6210;&#x5C0F;&#x5199;&#x3002;</li><li>\L&#xFF1A;&#x628A;replacement&#x5B57;&#x6BCD;&#x8F6C;&#x6362;&#x6210;&#x5C0F;&#x5199;&#xFF0C;&#x76F4;&#x5230;\U&#x6216;\E&#x51FA;&#x73B0;&#x3002;</li><li>\u&#xFF1A;&#x628A;&#x4E0B;&#x4E2A;&#x5B57;&#x7B26;&#x8F6C;&#x6362;&#x6210;&#x5927;&#x5199;&#x3002;</li><li>\U&#xFF1A;&#x628A;replacement&#x5B57;&#x6BCD;&#x8F6C;&#x6362;&#x6210;&#x5927;&#x5199;&#xFF0C;&#x76F4;&#x5230;\L&#x6216;\E&#x51FA;&#x73B0;&#x3002;</li><li>\E&#xFF1A;&#x505C;&#x6B62;&#x4EE5;\L&#x6216;\U&#x5F00;&#x59CB;&#x7684;&#x5927;&#x5C0F;&#x5199;&#x8F6C;&#x6362;</li></ul><h3 id="33-sed%E7%94%A8%E6%B3%95%E6%BC%94%E7%A4%BA"><strong>3.3 sed&#x7528;&#x6CD5;&#x6F14;&#x793A;</strong></h3><h3 id="331-%E5%B8%B8%E7%94%A8%E9%80%89%E9%A1%B9options%E6%BC%94%E7%A4%BA"><strong>3.3.1 &#x5E38;&#x7528;&#x9009;&#x9879;options&#x6F14;&#x793A;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat demo<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;/aaa/p&quot; demo #&#x5339;&#x914D;&#x5230;&#x7684;&#x884C;&#x4F1A;&#x6253;&#x5370;&#x4E00;&#x904D;&#xFF0C;&#x4E0D;&#x5339;&#x914D;&#x7684;&#x884C;&#x4E5F;&#x4F1A;&#x6253;&#x5370;<br><br>aaa<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed -n &quot;/aaa/p&quot; demo #-n&#x4E0D;&#x663E;&#x793A;&#x6CA1;&#x5339;&#x914D;&#x7684;&#x884C;<br><br>aaa<br><br>[root@along ~]# sed -e &quot;s/a/A/&quot; -e &quot;s/b/B/&quot; demo #-e&#x591A;&#x70B9;&#x7F16;&#x8F91;<br><br>Aaa<br><br>Bbbb<br><br>AABBCCDD<br><br>[root@along ~]# cat sedscript.txt<br><br>s/A/a/g<br><br>[root@along ~]# sed -f sedscript.txt demo #-f&#x4F7F;&#x7528;&#x6587;&#x4EF6;&#x5904;&#x7406;<br><br>aaa<br><br>bbbb<br><br>aaBBCCDD<br><br>[root@along ~]# sed -i.bak &quot;s/a/A/g&quot; demo #-i&#x76F4;&#x63A5;&#x5BF9;&#x6587;&#x4EF6;&#x8FDB;&#x884C;&#x5904;&#x7406;<br><br>[root@along ~]# cat demo<br><br>AAA<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# cat demo.bak<br><br>aaa<br><br>bbbb<br><br>AABBCCDD</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="332-%E5%9C%B0%E5%9D%80%E7%95%8C%E5%AE%9A%E6%BC%94%E7%A4%BA"><strong>3.3.2 &#x5730;&#x5740;&#x754C;&#x5B9A;&#x6F14;&#x793A;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat demo<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed -n &quot;p&quot; demo #&#x4E0D;&#x6307;&#x5B9A;&#x884C;&#xFF0C;&#x6253;&#x5370;&#x5168;&#x6587;<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;2s/b/B/g&quot; demo #&#x66FF;&#x6362;&#x7B2C;2&#x884C;&#x7684;b-&gt;B<br><br>aaa<br><br>BBBB<br><br>AABBCCDD<br><br>[root@along ~]# sed -n &quot;/aaa/p&quot; demo<br><br>aaa<br><br>[root@along ~]# sed -n &quot;1,2p&quot; demo #&#x6253;&#x5370;1-2&#x884C;<br><br>aaa<br><br>bbbb<br><br>[root@along ~]# sed -n &quot;/aaa/,/DD/p&quot; demo<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed -n &quot;2,/DD/p&quot; demo<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;1~2s/[aA]/E/g&quot; demo #&#x5C06;&#x5947;&#x6570;&#x884C;&#x7684;a&#x6216;A&#x66FF;&#x6362;&#x4E3A;E<br><br>EEE<br><br>bbbb<br><br>EEBBCCDD</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="333-%E7%BC%96%E8%BE%91%E5%91%BD%E4%BB%A4command%E6%BC%94%E7%A4%BA"><strong>3.3.3 &#x7F16;&#x8F91;&#x547D;&#x4EE4;command&#x6F14;&#x793A;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat demo<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;2d&quot; demo #&#x5220;&#x9664;&#x7B2C;2&#x884C;<br><br>aaa<br><br>AABBCCDD<br><br>[root@along ~]# sed -n &quot;2p&quot; demo #&#x6253;&#x5370;&#x7B2C;2&#x884C;<br><br>bbbb<br><br>[root@along ~]# sed &quot;2a123&quot; demo #&#x5728;&#x7B2C;2&#x884C;&#x540E;&#x52A0;123<br><br>aaa<br><br>bbbb<br><br>123<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;1i123&quot; demo #&#x5728;&#x7B2C;1&#x884C;&#x524D;&#x52A0;123<br><br>123<br><br>aaa<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;3c123\n456&quot; demo #&#x66FF;&#x6362;&#x7B2C;3&#x884C;&#x5185;&#x5BB9;<br><br>aaa<br><br>bbbb<br><br>123<br><br>456<br><br>[root@along ~]# sed -n &quot;3w/root/demo3&quot; demo #&#x4FDD;&#x5B58;&#x7B2C;3&#x884C;&#x7684;&#x5185;&#x5BB9;&#x5230;demo3&#x6587;&#x4EF6;&#x4E2D;<br><br>[root@along ~]# cat demo3<br><br>AABBCCDD<br><br>[root@along ~]# sed &quot;1r/root/demo3&quot; demo #&#x8BFB;&#x53D6;demo3&#x7684;&#x5185;&#x5BB9;&#x5230;&#x7B2C;1&#x884C;&#x540E;<br><br>aaa<br><br>AABBCCDD<br><br>bbbb<br><br>AABBCCDD<br><br>[root@along ~]# sed -n &quot;=&quot; demo #=&#x6253;&#x5370;&#x884C;&#x53F7;<br><br>1<br><br>2<br><br>3<br><br>[root@along ~]# sed -n &apos;2!p&apos; demo #&#x6253;&#x5370;&#x9664;&#x4E86;&#x7B2C;2&#x884C;&#x7684;&#x5185;&#x5BB9;<br><br>aaa<br><br>AABBCCDD<br><br>[root@along ~]# sed &apos;s@[a-z]@\u&amp;@g&apos; demo #&#x5C06;&#x5168;&#x6587;&#x7684;&#x5C0F;&#x5199;&#x5B57;&#x6BCD;&#x66FF;&#x6362;&#x4E3A;&#x5927;&#x5199;&#x5B57;&#x6BCD;<br><br>AAA<br><br>BBBB<br><br>AABBCCDD</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="34-sed%E9%AB%98%E7%BA%A7%E7%BC%96%E8%BE%91%E5%91%BD%E4%BB%A4"><strong>3.4 sed&#x9AD8;&#x7EA7;&#x7F16;&#x8F91;&#x547D;&#x4EE4;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;</p><ul><li>h&#xFF1A;&#x628A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x7684;&#x5185;&#x5BB9;&#x8986;&#x76D6;&#x81F3;&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x4E2D;</li><li>H&#xFF1A;&#x628A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x7684;&#x5185;&#x5BB9;&#x8FFD;&#x52A0;&#x81F3;&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x4E2D;</li><li>g&#xFF1A;&#x4ECE;&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x53D6;&#x51FA;&#x6570;&#x636E;&#x8986;&#x76D6;&#x81F3;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;</li><li>G&#xFF1A;&#x4ECE;&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x53D6;&#x51FA;&#x5185;&#x5BB9;&#x8FFD;&#x52A0;&#x81F3;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;</li><li>x&#xFF1A;&#x628A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x7684;&#x5185;&#x5BB9;&#x4E0E;&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x4E2D;&#x7684;&#x5185;&#x5BB9;&#x8FDB;&#x884C;&#x4E92;&#x6362;</li><li>n&#xFF1A;&#x8BFB;&#x53D6;&#x5339;&#x914D;&#x5230;&#x7684;&#x884C;&#x7684;&#x4E0B;&#x4E00;&#x884C;&#x8986;&#x76D6; &#x81F3;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;</li><li>N&#xFF1A;&#x8BFB;&#x53D6;&#x5339;&#x914D;&#x5230;&#x7684;&#x884C;&#x7684;&#x4E0B;&#x4E00;&#x884C;&#x8FFD;&#x52A0; &#x81F3;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;</li><li>d&#xFF1A;&#x5220;&#x9664;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E2D;&#x7684;&#x884C;</li><li>D&#xFF1A;&#x5220;&#x9664; &#x5F53;&#x524D;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x5F00;&#x7AEF;&#x81F3;\n &#x7684;&#x5185;&#x5BB9;&#xFF08;&#x4E0D;&#x518D;&#x4F20; &#x81F3;&#x6807;&#x51C6;&#x8F93;&#x51FA;&#xFF09;&#xFF0C;&#x653E;&#x5F03;&#x4E4B;&#x540E;&#x7684;&#x547D;&#x4EE4;&#xFF0C;&#x4F46;&#x662F;&#x5BF9;&#x5269;&#x4F59;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x91CD;&#x65B0;&#x6267;&#x884C;sed</li></ul><p>&#xFF08;2&#xFF09;&#x4E00;&#x4E2A;&#x6848;&#x4F8B;+&#x793A;&#x610F;&#x56FE;&#x6F14;&#x793A;</p><p>&#x2460; &#x6848;&#x4F8B;&#xFF1A;&#x5012;&#x5E8F;&#x8F93;&#x51FA;&#x6587;&#x672C;&#x5185;&#x5BB9;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat num.txt<br><br>One<br><br>Two<br><br>Three<br><br>[root@along ~]# sed &apos;1!G;h;$!d&apos; num.txt<br><br>Three<br><br>Two<br><br>One</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2461; &#x793A;&#x610F;&#x56FE;&#x5982;&#x4E0B;&#xFF1A;</p><p><br></p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-fc9e4a8f2aa743fcb4d7b1e618084362_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x2462; &#x603B;&#x7ED3;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E0E;&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x5173;&#x7CFB;&#xFF1A;</p><p>&#x4FDD;&#x6301;&#x7A7A;&#x95F4;&#x662F;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x4E00;&#x4E2A;&#x4E34;&#x65F6;&#x5B58;&#x653E;&#x6570;&#x636E;&#x7684;&#x7F13;&#x51B2;&#x533A;&#xFF0C;&#x534F;&#x52A9;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x8FDB;&#x884C;&#x6570;&#x636E;&#x5904;&#x7406;</p><p>&#xFF08;3&#xFF09;&#x6F14;&#x793A;</p><p>&#x2460; &#x663E;&#x793A;&#x5076;&#x6570;&#x884C;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9 |sed -n &apos;n;p&apos;<br><br>2<br><br>4<br><br>6<br><br>8</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2461; &#x5012;&#x5E8F;&#x663E;&#x793A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9 |sed &apos;1!G;h;$!d&apos;<br><br>9<br><br>8<br><br>7<br><br>6<br><br>5<br><br>4<br><br>3<br><br>2<br><br>1</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2462; &#x663E;&#x793A;&#x5947;&#x6570;&#x884C;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9 |sed &apos;H;n;d&apos;<br><br>1<br><br>3<br><br>5<br><br>7<br><br>9</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2463; &#x663E;&#x793A;&#x6700;&#x540E;&#x4E00;&#x884C;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9| sed &apos;N;D&apos;<br><br>9</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2464; &#x6BCF;&#x884C;&#x4E4B;&#x95F4;&#x52A0;&#x7A7A;&#x884C;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9 |sed &apos;G&apos;<br><br>1<br><br><br>2<br><br><br>3<br><br><br>4<br><br><br>5<br><br><br>6<br><br><br>7<br><br><br>8<br><br><br>9<br><br><br>---</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2465; &#x628A;&#x6BCF;&#x884C;&#x5185;&#x5BB9;&#x66FF;&#x6362;&#x6210;&#x7A7A;&#x884C;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9 |sed &quot;g&quot;<br><br><br><br><br><br><br><br><br><br><br>---</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2466; &#x786E;&#x4FDD;&#x6BCF;&#x4E00;&#x884C;&#x4E0B;&#x9762;&#x90FD;&#x6709;&#x4E00;&#x4E2A;&#x7A7A;&#x884C;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 9 |sed &apos;/^$/d;G&apos;<br><br>1<br><br><br>2<br><br><br>3<br><br><br>4<br><br><br>5<br><br><br>6<br><br><br>7<br><br><br>8<br><br><br>9</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h2 id="4%E3%80%81awk">4&#x3001;awk</h2><h3 id="41-%E8%AE%A4%E8%AF%86awk"><strong>4.1 &#x8BA4;&#x8BC6;awk</strong></h3><p>awk&#x662F;&#x4E00;&#x79CD;&#x7F16;&#x7A0B;&#x8BED;&#x8A00;&#xFF0C;&#x7528;&#x4E8E;&#x5728;linux/unix&#x4E0B;&#x5BF9;&#x6587;&#x672C;&#x548C;&#x6570;&#x636E;&#x8FDB;&#x884C;&#x5904;&#x7406;&#x3002;&#x6570;&#x636E;&#x53EF;&#x4EE5;&#x6765;&#x81EA;&#x6807;&#x51C6;&#x8F93;&#x5165;(stdin)&#x3001;&#x4E00;&#x4E2A;&#x6216;&#x591A;&#x4E2A;&#x6587;&#x4EF6;&#xFF0C;&#x6216;&#x5176;&#x5B83;&#x547D;&#x4EE4;&#x7684;&#x8F93;&#x51FA;&#x3002;&#x5B83;<strong>&#x652F;&#x6301;&#x7528;&#x6237;&#x81EA;&#x5B9A;&#x4E49;&#x51FD;&#x6570;</strong>&#x548C;&#x52A8;&#x6001;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x7B49;&#x5148;&#x8FDB;&#x529F;&#x80FD;&#xFF0C;&#x662F;linux/unix&#x4E0B;&#x7684;&#x4E00;&#x4E2A;&#x5F3A;&#x5927;&#x7F16;&#x7A0B;&#x5DE5;&#x5177;&#x3002;&#x5B83;&#x5728;&#x547D;&#x4EE4;&#x884C;&#x4E2D;&#x4F7F;&#x7528;&#xFF0C;&#x4F46;&#x66F4;&#x591A;&#x662F;&#x4F5C;&#x4E3A;&#x811A;&#x672C;&#x6765;&#x4F7F;&#x7528;&#x3002;<strong>awk&#x6709;&#x5F88;&#x591A;&#x5185;&#x5EFA;&#x7684;&#x529F;&#x80FD;</strong>&#xFF0C;&#x6BD4;&#x5982;&#x6570;&#x7EC4;&#x3001;&#x51FD;&#x6570;&#x7B49;&#xFF0C;&#x8FD9;&#x662F;&#x5B83;&#x548C;C&#x8BED;&#x8A00;&#x7684;&#x76F8;&#x540C;&#x4E4B;&#x5904;&#xFF0C;&#x7075;&#x6D3B;&#x6027;&#x662F;awk&#x6700;&#x5927;&#x7684;&#x4F18;&#x52BF;&#x3002;</p><p>awk&#x5176;&#x5B9E;&#x4E0D;&#x4EC5;&#x4EC5;&#x662F;&#x5DE5;&#x5177;&#x8F6F;&#x4EF6;&#xFF0C;&#x8FD8;&#x662F;&#x4E00;&#x79CD;&#x7F16;&#x7A0B;&#x8BED;&#x8A00;&#x3002;&#x4E0D;&#x8FC7;&#xFF0C;&#x672C;&#x6587;&#x53EA;&#x4ECB;&#x7ECD;&#x5B83;&#x7684;&#x547D;&#x4EE4;&#x884C;&#x7528;&#x6CD5;&#xFF0C;&#x5BF9;&#x4E8E;&#x5927;&#x591A;&#x6570;&#x573A;&#x5408;&#xFF0C;&#x5E94;&#x8BE5;&#x8DB3;&#x591F;&#x7528;&#x4E86;&#x3002;</p><h3 id="42-%E4%BD%BF%E7%94%A8awk"><strong>4.2 &#x4F7F;&#x7528;awk</strong></h3><h3 id="421-%E8%AF%AD%E6%B3%95"><strong>4.2.1 &#x8BED;&#x6CD5;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">awk [options] &apos;program&apos; var=value file&#x2026;<br><br>awk [options] -f programfile var=value file&#x2026;<br><br>awk [options] &apos;BEGIN{ action;&#x2026; } pattern{ action;&#x2026; } END{ action;&#x2026; }&apos; file ...</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="422-%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4%E9%80%89%E9%A1%B9"><strong>4.2.2 &#x5E38;&#x7528;&#x547D;&#x4EE4;&#x9009;&#x9879;</strong></h3><ul><li>-F fs&#xFF1A;fs&#x6307;&#x5B9A;&#x8F93;&#x5165;&#x5206;&#x9694;&#x7B26;&#xFF0C;fs&#x53EF;&#x4EE5;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#x6216;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#xFF0C;&#x5982;-F:</li><li>-v var=value&#xFF1A;&#x8D4B;&#x503C;&#x4E00;&#x4E2A;&#x7528;&#x6237;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;&#xFF0C;&#x5C06;&#x5916;&#x90E8;&#x53D8;&#x91CF;&#x4F20;&#x9012;&#x7ED9;awk</li><li>-f scripfile&#xFF1A;&#x4ECE;&#x811A;&#x672C;&#x6587;&#x4EF6;&#x4E2D;&#x8BFB;&#x53D6;awk&#x547D;&#x4EE4;</li></ul><h3 id="43-awk%E5%8F%98%E9%87%8F"><strong>4.3 awk&#x53D8;&#x91CF;</strong></h3><p>&#x53D8;&#x91CF;&#xFF1A;&#x5185;&#x7F6E;&#x548C;&#x81EA;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;&#xFF0C;&#x6BCF;&#x4E2A;&#x53D8;&#x91CF;&#x524D;&#x52A0; -v &#x547D;&#x4EE4;&#x9009;&#x9879;</p><h3 id="431-%E5%86%85%E7%BD%AE%E5%8F%98%E9%87%8F"><strong>4.3.1 &#x5185;&#x7F6E;&#x53D8;&#x91CF;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;</p><ul><li><strong>FS</strong>&#xFF1A;<strong>&#x8F93;&#x5165;&#x5B57;&#x6BB5;&#x5206;&#x9694;&#x7B26;</strong>&#xFF0C;<strong>&#x9ED8;&#x8BA4;&#x4E3A;&#x7A7A;&#x767D;&#x5B57;&#x7B26;</strong></li><li><strong>OFS</strong>&#xFF1A;<strong>&#x8F93;&#x51FA;&#x5B57;&#x6BB5;&#x5206;&#x9694;&#x7B26;</strong>&#xFF0C;&#x9ED8;&#x8BA4;&#x4E3A;&#x7A7A;&#x767D;&#x5B57;&#x7B26;</li><li>RS &#xFF1A;<strong>&#x8F93;&#x5165;&#x8BB0;&#x5F55;&#x5206;&#x9694;&#x7B26;</strong>&#xFF0C;&#x6307;&#x5B9A;&#x8F93;&#x5165;&#x65F6;&#x7684;&#x6362;&#x884C;&#x7B26;&#xFF0C;&#x539F;&#x6362;&#x884C;&#x7B26;&#x4ECD;&#x6709;&#x6548;</li><li>ORS &#xFF1A;<strong>&#x8F93;&#x51FA;&#x8BB0;&#x5F55;&#x5206;&#x9694;&#x7B26;</strong>&#xFF0C;&#x8F93;&#x51FA;&#x65F6;&#x7528;&#x6307;&#x5B9A;&#x7B26;&#x53F7;&#x4EE3;&#x66FF;&#x6362;&#x884C;&#x7B26;</li><li><strong>NF</strong> &#xFF1A;&#x5B57;&#x6BB5;&#x6570;&#x91CF;&#xFF0C;<strong>&#x5171;&#x6709;</strong>&#x591A;&#x5C11;&#x5B57;&#x6BB5;&#xFF0C;<strong> $NF&#x5F15;&#x7528;&#x6700;&#x540E;&#x4E00;&#x5217;&#xFF0C;$(NF-1)&#x5F15;&#x7528;&#x5012;&#x6570;&#x7B2C;2&#x5217;</strong></li><li><strong>NR</strong> &#xFF1A;<strong>&#x884C;&#x53F7;</strong>&#xFF0C;&#x540E;&#x53EF;&#x8DDF;&#x591A;&#x4E2A;&#x6587;&#x4EF6;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x6587;&#x4EF6;&#x884C;&#x53F7;&#x7EE7;&#x7EED;&#x4ECE;&#x7B2C;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;&#x6700;&#x540E;&#x884C;&#x53F7;&#x5F00;&#x59CB;</li><li>FNR &#xFF1A;&#x5404;&#x6587;&#x4EF6;&#x5206;&#x522B;&#x8BA1;&#x6570;, &#x884C;&#x53F7;&#xFF0C;&#x540E;&#x8DDF;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;&#x548C;NR&#x4E00;&#x6837;&#xFF0C;&#x8DDF;&#x591A;&#x4E2A;&#x6587;&#x4EF6;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x6587;&#x4EF6;<strong>&#x884C;&#x53F7;&#x4ECE;1&#x5F00;&#x59CB;</strong></li><li>FILENAME &#xFF1A;<strong>&#x5F53;&#x524D;&#x6587;&#x4EF6;&#x540D;</strong></li><li>ARGC &#xFF1A;<strong>&#x547D;&#x4EE4;&#x884C;&#x53C2;&#x6570;</strong>&#x7684;&#x4E2A;&#x6570;</li><li>ARGV &#xFF1A;&#x6570;&#x7EC4;&#xFF0C;&#x4FDD;&#x5B58;&#x7684;&#x662F;&#x547D;&#x4EE4;&#x884C;&#x6240;&#x7ED9;&#x5B9A;&#x7684;&#x5404;&#x53C2;&#x6570;&#xFF0C;<strong>&#x67E5;&#x770B;&#x53C2;&#x6570;</strong></li></ul><p>&#xFF08;2&#xFF09;&#x6F14;&#x793A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat awkdemo<br><br>hello:world<br><br>linux:redhat:lalala:hahaha<br><br>along:love:youou<br><br>[root@along ~]# awk -v FS=&apos;:&apos; &apos;{print $1,$2}&apos; awkdemo #FS&#x6307;&#x5B9A;&#x8F93;&#x5165;&#x5206;&#x9694;&#x7B26;<br><br>hello world<br><br>linux redhat<br><br>along love<br><br>[root@along ~]# awk -v FS=&apos;:&apos; -v OFS=&apos;---&apos; &apos;{print $1,$2}&apos; awkdemo #OFS&#x6307;&#x5B9A;&#x8F93;&#x51FA;&#x5206;&#x9694;&#x7B26;<br><br>hello---world<br><br>linux---redhat<br><br>along---love<br><br>[root@along ~]# awk -v RS=&apos;:&apos; &apos;{print $1,$2}&apos; awkdemo<br><br>hello<br><br>world linux<br><br>redhat<br><br>lalala<br><br>hahaha along<br><br>love<br><br>you<br><br>[root@along ~]# awk -v FS=&apos;:&apos; -v ORS=&apos;---&apos; &apos;{print $1,$2}&apos; awkdemo<br><br>hello world---linux redhat---along love---<br><br>[root@along ~]# awk -F: &apos;{print NF}&apos; awkdemo<br><br>2<br><br>4<br><br>3<br><br>[root@along ~]# awk -F: &apos;{print $(NF-1)}&apos; awkdemo #&#x663E;&#x793A;&#x5012;&#x6570;&#x7B2C;2&#x5217;<br><br>hello<br><br>lalala<br><br>love<br><br>[root@along ~]# awk &apos;{print NR}&apos; awkdemo awkdemo1<br><br>1<br><br>2<br><br>3<br><br>4<br><br>5<br><br>[root@along ~]# awk END&apos;{print NR}&apos; awkdemo awkdemo1<br><br>5<br><br>[root@along ~]# awk &apos;{print FNR}&apos; awkdemo awkdemo1<br><br>1<br><br>2<br><br>3<br><br>1<br><br>2<br><br>[root@along ~]# awk &apos;{print FILENAME}&apos; awkdemo<br><br>awkdemo<br><br>awkdemo<br><br>awkdemo<br><br>[root@along ~]# awk &apos;BEGIN {print ARGC}&apos; awkdemo awkdemo1<br><br>3<br><br>[root@along ~]# awk &apos;BEGIN {print ARGV[0]}&apos; awkdemo awkdemo1<br><br>awk<br><br>[root@along ~]# awk &apos;BEGIN {print ARGV[1]}&apos; awkdemo awkdemo1<br><br>awkdemo<br><br>[root@along ~]# awk &apos;BEGIN {print ARGV[2]}&apos; awkdemo awkdemo1<br><br>awkdemo1</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="432-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%98%E9%87%8F"><strong>4.3.2 &#x81EA;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;</strong></h3><p>&#x81EA;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;( &#x533A;&#x5206;&#x5B57;&#x7B26;&#x5927;&#x5C0F;&#x5199;)</p><p>&#xFF08;1&#xFF09;-v var=value</p><p>&#x2460; &#x5148;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;&#xFF0C;&#x540E;&#x6267;&#x884C;&#x52A8;&#x4F5C;print</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk -v name=&quot;along&quot; -F: &apos;{print name&quot;:&quot;$0}&apos; awkdemo<br><br>along:hello:world<br><br>along:linux:redhat:lalala:hahaha<br><br>along:along:love:you</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x2461; &#x5728;&#x6267;&#x884C;&#x52A8;&#x4F5C;print&#x540E;&#x5B9A;&#x4E49;&#x53D8;&#x91CF;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk -F: &apos;{print name&quot;:&quot;$0;name=&quot;along&quot;}&apos; awkdemo<br><br>:hello:world<br><br>along:linux:redhat:lalala:hahaha<br><br>along:along:love:you</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;2&#xFF09;&#x5728;program &#x4E2D;&#x76F4;&#x63A5;&#x5B9A;&#x4E49;</p><p>&#x53EF;&#x4EE5;&#x628A;&#x6267;&#x884C;&#x7684;&#x52A8;&#x4F5C;&#x653E;&#x5728;&#x811A;&#x672C;&#x4E2D;&#xFF0C;&#x76F4;&#x63A5;&#x8C03;&#x7528;&#x811A;&#x672C; -f</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat awk.txt<br><br>{name=&quot;along&quot;;print name,$1}<br><br>[root@along ~]# awk -F: -f awk.txt awkdemo<br><br>along hello<br><br>along linux<br><br>along along</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="44-printf%E5%91%BD%E4%BB%A4"><strong>4.4 printf&#x547D;&#x4EE4;</strong></h3><p>&#x6BD4;print&#x66F4;&#x5F3A;&#x5927;</p><h3 id="441-%E6%A0%BC%E5%BC%8F"><strong>4.4.1 &#x683C;&#x5F0F;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;&#x5316;&#x8F93;&#x51FA;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">1</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">printf &quot;FORMAT&quot;, item1,item2, ...</td></tr></tbody></table><!--kg-card-end: html--><p>&#x2460; &#x5FC5;&#x987B;&#x6307;&#x5B9A;FORMAT</p><p>&#x2461; <strong>&#x4E0D;&#x4F1A;&#x81EA;&#x52A8;&#x6362;&#x884C;&#xFF0C;&#x9700;&#x8981;&#x663E;&#x5F0F;&#x7ED9;&#x51FA;&#x6362;&#x884C;&#x63A7;&#x5236;&#x7B26;&#xFF0C;\n</strong></p><p>&#x2462; FORMAT &#x4E2D;&#x9700;&#x8981;&#x5206;&#x522B;&#x4E3A;&#x540E;&#x9762;&#x6BCF;&#x4E2A;item &#x6307;&#x5B9A;&#x683C;&#x5F0F;&#x7B26;</p><p>&#xFF08;2&#xFF09;&#x683C;&#x5F0F;&#x7B26;&#xFF1A;&#x4E0E;item &#x4E00;&#x4E00;&#x5BF9;&#x5E94;</p><ul><li>%c: &#x663E;&#x793A;&#x5B57;&#x7B26;&#x7684;ASCII&#x7801;</li><li>%d, %i: &#x663E;&#x793A;&#x5341;&#x8FDB;&#x5236;&#x6574;&#x6570;</li><li>%e, %E: &#x663E;&#x793A;&#x79D1;&#x5B66;&#x8BA1;&#x6570;&#x6CD5;&#x6570;&#x503C;</li><li><strong>%f &#xFF1A;&#x663E;&#x793A;&#x4E3A;&#x6D6E;&#x70B9;&#x6570;&#xFF0C;&#x5C0F;&#x6570; </strong>%5.1f&#xFF0C;&#x5E26;&#x6574;&#x6570;&#x3001;&#x5C0F;&#x6570;&#x70B9;&#x3001;&#x6574;&#x6570;&#x5171;5&#x4F4D;&#xFF0C;&#x5C0F;&#x6570;1&#x4F4D;&#xFF0C;&#x4E0D;&#x591F;&#x7528;&#x7A7A;&#x683C;&#x8865;&#x4E0A;</li><li>%g, %G &#xFF1A;&#x4EE5;&#x79D1;&#x5B66;&#x8BA1;&#x6570;&#x6CD5;&#x6216;&#x6D6E;&#x70B9;&#x5F62;&#x5F0F;&#x663E;&#x793A;&#x6570;&#x503C;</li><li><strong>%s &#xFF1A;&#x663E;&#x793A;&#x5B57;&#x7B26;&#x4E32;</strong>&#xFF1B;&#x4F8B;&#xFF1A;%5s&#x6700;&#x5C11;5&#x4E2A;&#x5B57;&#x7B26;&#xFF0C;&#x4E0D;&#x591F;&#x7528;&#x7A7A;&#x683C;&#x8865;&#x4E0A;&#xFF0C;&#x8D85;&#x8FC7;5&#x4E2A;&#x8FD8;&#x7EE7;&#x7EED;&#x663E;&#x793A;</li><li><strong>%u &#xFF1A;&#x65E0;&#x7B26;&#x53F7;&#x6574;&#x6570;</strong></li><li>%%: &#x663E;&#x793A;% &#x81EA;&#x8EAB;</li></ul><p>&#xFF08;3&#xFF09;&#x4FEE;&#x9970;&#x7B26;&#xFF1A;&#x653E;&#x5728;%c[/d/e/f...]&#x4E4B;&#x95F4;</p><ul><li>#[.#]&#xFF1A;&#x7B2C;&#x4E00;&#x4E2A;&#x6570;&#x5B57;&#x63A7;&#x5236;&#x663E;&#x793A;&#x7684;&#x5BBD;&#x5EA6;&#xFF1B;&#x7B2C;&#x4E8C;&#x4E2A;# &#x8868;&#x793A;&#x5C0F;&#x6570;&#x70B9;&#x540E;&#x7CBE;&#x5EA6;&#xFF0C;%5.1f</li><li>-&#xFF1A;&#x5DE6;&#x5BF9;&#x9F50;&#xFF08;<strong>&#x9ED8;&#x8BA4;&#x53F3;&#x5BF9;&#x9F50;</strong>&#xFF09; %-15s</li><li>+&#xFF1A;&#x663E;&#x793A;&#x6570;&#x503C;&#x7684;&#x6B63;&#x8D1F;&#x7B26;&#x53F7; %+d</li></ul><h3 id="442-%E6%BC%94%E7%A4%BA"><strong>4.4.2 &#x6F14;&#x793A;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk -F: &apos;{print $1,$3}&apos; /etc/passwd<br><br>root 0<br><br>bin 1<br><br>---&#x7B2C;&#x4E00;&#x5217;&#x663E;&#x793A;&#x5C0F;&#x4E8E;20&#x7684;&#x5B57;&#x7B26;&#x4E32;&#xFF1B;&#x7B2C;2&#x5217;&#x663E;&#x793A;&#x6574;&#x6570;&#x5E76;&#x6362;&#x884C;<br><br>[root@along ~]# awk -F: &apos;{printf &quot;%20s---%u\n&quot;,$1,$3}&apos; /etc/passwd<br><br>root---0<br><br>bin---1<br><br>---&#x4F7F;&#x7528;-&#x8FDB;&#x884C;&#x5DE6;&#x5BF9;&#x9F50;&#xFF1B;&#x7B2C;2&#x5217;&#x663E;&#x793A;&#x6D6E;&#x70B9;&#x6570;<br><br>[root@along ~]# awk -F: &apos;{printf &quot;%-20s---%-10.3f\n&quot;,$1,$3}&apos; /etc/passwd<br><br>root ---0.000<br><br>bin ---1.000<br><br>---&#x4F7F;&#x7528;printf&#x505A;&#x8868;&#x683C;<br><br>[root@along ~]# awk -F: &apos;BEGIN{printf &quot;username userid\n-----------------------------\n&quot;}{printf &quot;%-20s|%-10.3f\n&quot;,$1,$3}&apos; /etc/passwd<br><br>username userid<br><br>-----------------------------<br><br>root |0.000<br><br>bin |1.000</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="45-%E6%93%8D%E4%BD%9C%E7%AC%A6"><strong>4.5 &#x64CD;&#x4F5C;&#x7B26;</strong></h3><h3 id="451-%E6%A0%BC%E5%BC%8F"><strong>4.5.1 &#x683C;&#x5F0F;</strong></h3><ul><li>&#x7B97;&#x672F;&#x64CD;&#x4F5C;&#x7B26;&#xFF1A;</li><li>x+y, x-y, x*y, x/y, x^y, x%y</li><li>-x: &#x8F6C;&#x6362;&#x4E3A;&#x8D1F;&#x6570;</li><li>+x: &#x8F6C;&#x6362;&#x4E3A;&#x6570;&#x503C;</li><li>&#x5B57;&#x7B26;&#x4E32;&#x64CD;&#x4F5C;&#x7B26;&#xFF1A;&#x6CA1;&#x6709;&#x7B26;&#x53F7;&#x7684;&#x64CD;&#x4F5C;&#x7B26;&#xFF0C;&#x5B57;&#x7B26;&#x4E32;&#x8FDE;&#x63A5;</li><li>&#x8D4B;&#x503C;&#x64CD;&#x4F5C;&#x7B26;&#xFF1A;</li><li>=, +=, -=, *=, /=, %=, ^=</li><li>++, --</li><li>&#x6BD4;&#x8F83;&#x64CD;&#x4F5C;&#x7B26;&#xFF1A;</li><li>==, !=, &gt;, &gt;=, &lt;, &lt;=</li><li>&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x7B26;&#xFF1A;~ &#xFF1A;&#x5DE6;&#x8FB9;&#x662F;&#x5426;&#x548C;&#x53F3;&#x8FB9;&#x5339;&#x914D;&#x5305;&#x542B; !~ &#xFF1A;&#x662F;&#x5426;&#x4E0D;&#x5339;&#x914D;</li><li>&#x903B;&#x8F91;&#x64CD;&#x4F5C;&#x7B26;&#xFF1A;&#x4E0E;&amp;&amp; &#xFF0C;&#x6216;|| &#xFF0C;&#x975E;!</li><li>&#x51FD;&#x6570;&#x8C03;&#x7528;&#xFF1A; function_name(argu1, argu2, ...)</li><li>&#x6761;&#x4EF6;&#x8868;&#x8FBE;&#x5F0F;&#xFF08;&#x4E09;&#x76EE;&#x8868;&#x8FBE;&#x5F0F;&#xFF09;&#xFF1A;selector<strong>?</strong>if-true-expression<strong>:</strong>if-false-expression</li><li>&#x6CE8;&#x91CA;&#xFF1A;&#x5148;&#x5224;&#x65AD;selector&#xFF0C;&#x5982;&#x679C;&#x7B26;&#x5408;&#x6267;&#x884C; ? &#x540E;&#x7684;&#x64CD;&#x4F5C;&#xFF1B;&#x5426;&#x5219;&#x6267;&#x884C; : &#x540E;&#x7684;&#x64CD;&#x4F5C;</li></ul><h3 id="452-%E6%BC%94%E7%A4%BA"><strong>4.5.2 &#x6F14;&#x793A;</strong></h3><p>&#xFF08;1&#xFF09;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x7B26;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">---&#x67E5;&#x8BE2;&#x4EE5;/dev&#x5F00;&#x5934;&#x7684;&#x78C1;&#x76D8;&#x4FE1;&#x606F;<br><br>[root@along ~]# df -h |awk -F: &apos;$0 ~ /^\/dev/&apos;<br><br>/dev/mapper/cl-root 17G 7.3G 9.7G 43% /<br><br>/dev/sda1 1014M 121M 894M 12% /boot<br><br>---&#x53EA;&#x663E;&#x793A;&#x78C1;&#x76D8;&#x4F7F;&#x7528;&#x72B6;&#x51B5;&#x548C;&#x78C1;&#x76D8;&#x540D;<br><br>[root@along ~]# df -h |awk &apos;$0 ~ /^\/dev/{print $(NF-1)&quot;---&quot;$1}&apos;<br><br>43%---/dev/mapper/cl-root<br><br>12%---/dev/sda1<br><br>---&#x67E5;&#x627E;&#x78C1;&#x76D8;&#x5927;&#x4E8E;40%&#x7684;<br><br>[root@along ~]# df -h |awk &apos;$0 ~ /^\/dev/{print $(NF-1)&quot;---&quot;$1}&apos; |awk -F% &apos;$1 &gt; 40&apos;<br><br>43%---/dev/mapper/cl-root</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;2&#xFF09;&#x903B;&#x8F91;&#x64CD;&#x4F5C;&#x7B26;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk -F: &apos;$3&gt;=0 &amp;&amp; $3&lt;=1000 {print $1,$3}&apos; /etc/passwd<br><br>root 0<br><br>bin 1<br><br>[root@along ~]# awk -F: &apos;$3==0 || $3&gt;=1000 {print $1}&apos; /etc/passwd<br><br>root<br><br>[root@along ~]# awk -F: &apos;!($3==0) {print $1}&apos; /etc/passwd<br><br>bin<br><br>[root@along ~]# awk -F: &apos;!($0 ~ /bash$/) {print $1,$3}&apos; /etc/passwd<br><br>bin 1<br><br>daemon 2</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;3&#xFF09;&#x6761;&#x4EF6;&#x8868;&#x8FBE;&#x5F0F;&#xFF08;&#x4E09;&#x76EE;&#x8868;&#x8FBE;&#x5F0F;&#xFF09;</p><p><br></p><pre><code class="language-text">[root@along ~]# awk -F: &apos;{$3 &gt;= 1000?usertype=&quot;common user&quot;:usertype=&quot;sysadmin user&quot;;print usertype,$1,$3}&apos; /etc/passwd

sysadmin user root 0

common user along 1000</code></pre><h3 id="46-awk-pattern-%E5%8C%B9%E9%85%8D%E9%83%A8%E5%88%86"><strong>4.6 awk PATTERN &#x5339;&#x914D;&#x90E8;&#x5206;</strong></h3><h3 id="461-%E6%A0%BC%E5%BC%8F"><strong>4.6.1 &#x683C;&#x5F0F;</strong></h3><p>PATTERN&#xFF1A;&#x6839;&#x636E;pattern &#x6761;&#x4EF6;&#xFF0C;&#x8FC7;&#x6EE4;&#x5339;&#x914D;&#x7684;&#x884C;&#xFF0C;&#x518D;&#x505A;&#x5904;&#x7406;</p><p>&#xFF08;1&#xFF09;&#x5982;&#x679C;&#x672A;&#x6307;&#x5B9A;&#xFF1A;&#x7A7A;&#x6A21;&#x5F0F;&#xFF0C;&#x5339;&#x914D;&#x6BCF;&#x4E00;&#x884C;</p><p>&#xFF08;2&#xFF09;/regular expression/ &#xFF1A;&#x4EC5;&#x5904;&#x7406;&#x80FD;&#x591F;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x5230;&#x7684;&#x884C;&#xFF0C;<strong>&#x6B63;&#x5219;</strong>&#xFF0C;&#x9700;&#x8981;&#x7528;/ / &#x62EC;&#x8D77;&#x6765;</p><p>&#xFF08;3&#xFF09;relational expression&#xFF1A;<strong>&#x5173;&#x7CFB;&#x8868;&#x8FBE;&#x5F0F;&#xFF0C;&#x7ED3;&#x679C;&#x4E3A;&#x201C;&#x771F;&#x201D;&#x624D;&#x4F1A;&#x88AB;&#x5904;&#x7406;</strong></p><p>&#x771F;&#xFF1A;&#x7ED3;&#x679C;&#x4E3A;&#x975E;0&#x503C;&#xFF0C;&#x975E;&#x7A7A;&#x5B57;&#x7B26;&#x4E32;</p><p>&#x5047;&#xFF1A;&#x7ED3;&#x679C;&#x4E3A;&#x7A7A;&#x5B57;&#x7B26;&#x4E32;&#x6216;0&#x503C;</p><p>&#xFF08;4&#xFF09;line ranges&#xFF1A;&#x884C;&#x8303;&#x56F4;</p><p>startline(&#x8D77;&#x59CB;&#x884C;),endline(&#x7ED3;&#x675F;&#x884C;)&#xFF1A;/pat1/,/pat2/ &#x4E0D;&#x652F;&#x6301;&#x76F4;&#x63A5;&#x7ED9;&#x51FA;&#x6570;&#x5B57;&#xFF0C;&#x53EF;&#x4EE5;&#x6709;&#x591A;&#x6BB5;&#xFF0C;&#x4E2D;&#x95F4;&#x53EF;&#x4EE5;&#x6709;&#x95F4;&#x9694;</p><p>&#xFF08;5&#xFF09;BEGIN/END &#x6A21;&#x5F0F;</p><p>BEGIN{}: &#x4EC5;&#x5728;&#x5F00;&#x59CB;&#x5904;&#x7406;&#x6587;&#x4EF6;&#x4E2D;&#x7684;&#x6587;&#x672C;&#x4E4B;&#x524D;&#x6267;&#x884C;&#x4E00;&#x6B21;</p><p>END{} &#xFF1A;&#x4EC5;&#x5728;&#x6587;&#x672C;&#x5904;&#x7406;&#x5B8C;&#x6210;&#x4E4B;&#x540E;&#x6267;&#x884C;</p><h3 id="462-%E6%BC%94%E7%A4%BA"><strong>4.6.2 &#x6F14;&#x793A;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk -F: &apos;{print $1}&apos; awkdemo<br><br>hello<br><br>linux<br><br>along<br><br>[root@along ~]# awk -F: &apos;/along/{print $1}&apos; awkdemo<br><br>along<br><br>[root@along ~]# awk -F: &apos;1{print $1}&apos; awkdemo<br><br>hello<br><br>linux<br><br>along<br><br>[root@along ~]# awk -F: &apos;0{print $1}&apos; awkdemo<br><br>[root@along ~]# awk -F: &apos;/^h/,/^a/{print $1}&apos; awkdemo<br><br>hello<br><br>linux<br><br>along<br><br>[root@along ~]# awk -F: &apos;BEGIN{print &quot;&#x7B2C;&#x4E00;&#x5217;&quot;}{print $1} END{print &quot;&#x7ED3;&#x675F;&quot;}&apos; awkdemo<br><br>&#x7B2C;&#x4E00;&#x5217;<br><br>hello<br><br>linux<br><br>along<br><br>&#x7ED3;&#x675F;</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="47-awk%E6%9C%89%E6%84%8F%E6%80%9D%E7%9A%84%E6%A1%88%E4%BE%8B"><strong>4.7 awk&#x6709;&#x610F;&#x601D;&#x7684;&#x6848;&#x4F8B;</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# seq 10<br><br>1<br><br>2<br><br>3<br><br>4<br><br>5<br><br>6<br><br>7<br><br>8<br><br>9<br><br>10<br><br>---&#x56E0;&#x4E3A;i=0&#xFF0C;&#x4E3A;&#x5047;&#xFF0C;&#x6240;&#x4EE5;&#x4E0D;&#x6253;&#x5370;<br><br>[root@along ~]# seq 10 |awk &apos;i=0&apos;<br><br>---i=1&#xFF0C;&#x4E3A;&#x771F;&#xFF0C;&#x6240;&#x4EE5;&#x5168;&#x90E8;&#x6253;&#x5370;<br><br>[root@along ~]# seq 10 |awk &apos;i=1&apos;<br><br>1<br><br>2<br><br>3<br><br>4<br><br>5<br><br>6<br><br>7<br><br>8<br><br>9<br><br>10<br><br>---&#x53EA;&#x6253;&#x5370;&#x5947;&#x6570;&#x884C;&#xFF1B;&#x5947;&#x6570;&#x884C;i&#x8FDB;&#x5165;&#x65F6;&#x672C;&#x8EAB;&#x4E3A;&#x7A7A;&#xFF0C;&#x88AB;&#x8D4B;&#x4E3A;!i&#xFF0C;&#x5373;&#x4E0D;&#x4E3A;&#x7A7A;&#xFF0C;&#x6240;&#x4EE5;&#x6253;&#x5370;&#xFF1B;&#x5076;&#x6570;&#x884C;i&#x8FDB;&#x5165;&#x65F6;&#x672C;&#x8EAB;&#x4E0D;&#x4E3A;&#x7A7A;&#xFF0C;&#x88AB;&#x8D4B;&#x4E3A;!i&#xFF0C;&#x5373;&#x4E3A;&#x7A7A;&#xFF0C;&#x6240;&#x4EE5;&#x4E0D;&#x6253;&#x5370;<br><br>[root@along ~]# seq 10 |awk &apos;i=!i&apos;<br><br>1<br><br>3<br><br>5<br><br>7<br><br>9<br><br>---&#x89E3;&#x91CA;&#x4E0A;&#x4E00;&#x4E2A;&#x64CD;&#x4F5C;&#xFF0C;i&#x5728;&#x5947;&#x5076;&#x884C;&#x7684;&#x503C;<br><br>[root@along ~]# seq 10 |awk &apos;{i=!i;print i}&apos;<br><br>1<br><br>0<br><br>1<br><br>0<br><br>1<br><br>0<br><br>1<br><br>0<br><br>1<br><br>0<br><br>---&#x53EA;&#x6253;&#x5370;&#x5076;&#x6570;&#x884C;&#xFF0C;&#x662F;&#x4E0A;&#x8FB9;&#x6253;&#x5370;&#x5947;&#x6570;&#x884C;&#x7684;&#x53D6;&#x53CD;<br><br>[root@along ~]# seq 10 |awk &apos;!(i=!i)&apos;<br><br>2<br><br>4<br><br>6<br><br>8<br><br>10<br><br>---&#x53EA;&#x6253;&#x5370;&#x5076;&#x6570;&#x884C;&#xFF1B;&#x5148;&#x5BF9;i&#x8FDB;&#x884C;&#x8D4B;&#x503C;&#xFF0C;&#x5373;&#x4E0D;&#x4E3A;&#x7A7A;&#xFF0C;&#x521A;&#x597D;&#x548C;&#x6253;&#x5370;&#x5947;&#x6570;&#x884C;&#x76F8;&#x53CD;<br><br>[root@along ~]# seq 10 |awk -v i=1 &apos;i=!i&apos;<br><br>2<br><br>4<br><br>6<br><br>8<br><br>10</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h2 id="5%E3%80%81awk%E9%AB%98%E9%98%B6%E7%94%A8%E6%B3%95">5&#x3001;awk&#x9AD8;&#x9636;&#x7528;&#x6CD5;</h2><h3 id="51-awk%E6%8E%A7%E5%88%B6%E8%AF%AD%E5%8F%A5%E2%80%94if-else%E5%88%A4%E6%96%AD"><strong>5.1 awk&#x63A7;&#x5236;&#x8BED;&#x53E5;&#x2014;if-else&#x5224;&#x65AD;</strong></h3><p>&#xFF08;1&#xFF09;&#x8BED;&#x6CD5;</p><p><br></p><pre><code class="language-text">if(condition){statement;&#x2026;}[else statement]  &#x53CC;&#x5206;&#x652F;

if(condition1){statement1}else if(condition2){statement2}else{statement3}  &#x591A;&#x5206;&#x652F;</code></pre><p><br></p><p>&#xFF08;2&#xFF09;&#x4F7F;&#x7528;&#x573A;&#x666F;&#xFF1A;&#x5BF9;awk &#x53D6;&#x5F97;&#x7684;&#x6574;&#x884C;&#x6216;&#x67D0;&#x4E2A;&#x5B57;&#x6BB5;&#x505A;&#x6761;&#x4EF6;&#x5224;&#x65AD;</p><p>&#xFF08;3&#xFF09;&#x6F14;&#x793A;</p><p><br></p><pre><code class="language-text">[root@along ~]# awk -F: &apos;{if($3&gt;10 &amp;&amp; $3&lt;1000)print $1,$3}&apos; /etc/passwd

operator 11

games 1

[root@along ~]# awk -F: &apos;{if($NF==&quot;/bin/bash&quot;) print $1,$NF}&apos; /etc/passwd

root /bin/bash

along /bin/bash

---&#x8F93;&#x51FA;&#x603B;&#x5217;&#x6570;&#x5927;&#x4E8E;3&#x7684;&#x884C;

[root@along ~]# awk -F: &apos;{if(NF&gt;2) print $0}&apos; awkdemo

linux:redhat:lalala:hahaha

along:love:you

---&#x7B2C;3&#x5217;&gt;=1000&#x4E3A;Common user&#xFF0C;&#x53CD;&#x4E4B;&#x662F;root or Sysuser

[root@along ~]# awk -F: &apos;{if($3&gt;=1000) {printf &quot;Common user: %s\n&quot;,$1} else{printf &quot;root or Sysuser: %s\n&quot;,$1}}&apos; /etc/passwd

root or Sysuser: root

root or Sysuser: bin

Common user: along

---&#x78C1;&#x76D8;&#x5229;&#x7528;&#x7387;&#x8D85;&#x8FC7;40&#x7684;&#x8BBE;&#x5907;&#x540D;&#x548C;&#x5229;&#x7528;&#x7387;

[root@along ~]# df -h|awk -F% &apos;/^\/dev/{print $1}&apos;|awk &apos;$NF &gt; 40{print $1,$NF}&apos;

/dev/mapper/cl-root 43

---test=100&#x548C;&gt;90&#x4E3A;very good; 90&gt;test&gt;60&#x4E3A;good; test&lt;60&#x4E3A;no pass

[root@along ~]# awk &apos;BEGIN{ test=100;if(test&gt;90){print &quot;very good&quot;}else if(test&gt;60){ print &quot;good&quot;}else{print &quot;no pass&quot;}}&apos;

very good

[root@along ~]# awk &apos;BEGIN{ test=80;if(test&gt;90){print &quot;very good&quot;}else if(test&gt;60){ print &quot;good&quot;}else{print &quot;no pass&quot;}}&apos;

good

[root@along ~]# awk &apos;BEGIN{ test=50;if(test&gt;90){print &quot;very good&quot;}else if(test&gt;60){ print &quot;good&quot;}else{print &quot;no pass&quot;}}&apos;

no pass</code></pre><h3 id="52-awk%E6%8E%A7%E5%88%B6%E8%AF%AD%E5%8F%A5%E2%80%94while%E5%BE%AA%E7%8E%AF"><strong>5.2 awk&#x63A7;&#x5236;&#x8BED;&#x53E5;&#x2014;while&#x5FAA;&#x73AF;</strong></h3><p>&#xFF08;1&#xFF09;&#x8BED;&#x6CD5;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">while(condition){statement;&#x2026;}</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x6CE8;&#xFF1A;&#x6761;&#x4EF6;&#x201C;&#x771F;&#x201D;&#xFF0C;&#x8FDB;&#x5165;&#x5FAA;&#x73AF;&#xFF1B;&#x6761;&#x4EF6;&#x201C;&#x5047;&#x201D;&#xFF0C; &#x9000;&#x51FA;&#x5FAA;&#x73AF;</p><p>&#xFF08;2&#xFF09;&#x4F7F;&#x7528;&#x573A;&#x666F;</p><p>&#x5BF9;&#x4E00;&#x884C;&#x5185;&#x7684;&#x591A;&#x4E2A;&#x5B57;&#x6BB5;&#x9010;&#x4E00;&#x7C7B;&#x4F3C;&#x5904;&#x7406;&#x65F6;&#x4F7F;&#x7528;</p><p>&#x5BF9;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x5404;&#x5143;&#x7D20;&#x9010;&#x4E00;&#x5904;&#x7406;&#x65F6;&#x4F7F;&#x7528;</p><p>&#xFF08;3&#xFF09;&#x6F14;&#x793A;</p><p><br></p><pre><code class="language-text">---&#x4EE5;along&#x5F00;&#x5934;&#x7684;&#x884C;&#xFF0C;&#x4EE5;&#xFF1A;&#x4E3A;&#x5206;&#x9694;&#xFF0C;&#x663E;&#x793A;&#x6BCF;&#x4E00;&#x884C;&#x7684;&#x6BCF;&#x4E2A;&#x5355;&#x8BCD;&#x548C;&#x5176;&#x957F;&#x5EA6;

[root@along ~]# awk -F: &apos;/^along/{i=1;while(i&lt;=NF){print $i,length($i); i++}}&apos; awkdemo

along 5

love 4

you 3

---&#x4EE5;&#xFF1A;&#x4E3A;&#x5206;&#x9694;&#xFF0C;&#x663E;&#x793A;&#x6BCF;&#x4E00;&#x884C;&#x7684;&#x957F;&#x5EA6;&#x5927;&#x4E8E;6&#x7684;&#x5355;&#x8BCD;&#x548C;&#x5176;&#x957F;&#x5EA6;

[root@along ~]# awk -F: &apos;{i=1;while(i&lt;=NF) {if(length($i)&gt;=6){print $i,length($i)}; i++}}&apos; awkdemo

redhat 6

lalala 6

hahaha 6

---&#x8BA1;&#x7B97;1+2+3+...+100=5050

[root@along ~]# awk &apos;BEGIN{i=1;sum=0;while(i&lt;=100){sum+=i;i++};print sum}&apos;

5050</code></pre><h3 id="53-awk%E6%8E%A7%E5%88%B6%E8%AF%AD%E5%8F%A5%E2%80%94do-while%E5%BE%AA%E7%8E%AF"><strong>5.3 awk&#x63A7;&#x5236;&#x8BED;&#x53E5;&#x2014;do-while&#x5FAA;&#x73AF;</strong></h3><p>&#xFF08;1&#xFF09;&#x8BED;&#x6CD5;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">do {statement;&#x2026;}while(condition)</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x610F;&#x4E49;&#xFF1A;&#x65E0;&#x8BBA;&#x771F;&#x5047;&#xFF0C;&#x81F3;&#x5C11;&#x6267;&#x884C;&#x4E00;&#x6B21;&#x5FAA;&#x73AF;&#x4F53;</p><p>&#xFF08;2&#xFF09;&#x8BA1;&#x7B97;1+2+3+...+100=5050</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk &apos;BEGIN{sum=0;i=1;do{sum+=i;i++}while(i&lt;=100);print sum}&apos;<br><br>5050</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="54-awk%E6%8E%A7%E5%88%B6%E8%AF%AD%E5%8F%A5%E2%80%94for%E5%BE%AA%E7%8E%AF"><strong>5.4 awk&#x63A7;&#x5236;&#x8BED;&#x53E5;&#x2014;for&#x5FAA;&#x73AF;</strong></h3><p>&#xFF08;1&#xFF09;&#x8BED;&#x6CD5;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">for(expr1;expr2;expr3) {statement;&#x2026;}</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;2&#xFF09;&#x7279;&#x6B8A;&#x7528;&#x6CD5;&#xFF1A;&#x904D;&#x5386;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x5143;&#x7D20;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">for(var in array) {for-body}</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;3&#xFF09;&#x6F14;&#x793A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">---&#x663E;&#x793A;&#x6BCF;&#x4E00;&#x884C;&#x7684;&#x6BCF;&#x4E2A;&#x5355;&#x8BCD;&#x548C;&#x5176;&#x957F;&#x5EA6;<br><br>[root@along ~]# awk -F: &apos;{for(i=1;i&lt;=NF;i++) {print$i,length($i)}}&apos; awkdemo<br><br>hello 5<br><br>world 5<br><br>linux 5<br><br>redhat 6<br><br>lalala 6<br><br>hahaha 6<br><br>along 5<br><br>love 4<br><br>you 3<br><br>---&#x6C42;&#x7537;m&#x3001;&#x5973;f&#x5404;&#x81EA;&#x7684;&#x5E73;&#x5747;<br><br>[root@along ~]# cat sort.txt<br><br>xiaoming m 90<br><br>xiaohong f 93<br><br>xiaohei m 80<br><br>xiaofang f 99<br><br>[root@along ~]# awk &apos;{m[$2]++;score[$2]+=$3}END{for(i in m){printf &quot;%s:%6.2f\n&quot;,i,score[i]/m[i]}}&apos; sort.txt<br><br>m: 85.00<br><br>f: 96.00</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="55-%E5%92%8Cshell%E8%84%9A%E6%9C%AC%E4%B8%AD%E8%BE%83%E7%9B%B8%E4%BC%BC%E7%9A%84%E6%8E%A7%E5%88%B6%E8%AF%AD%E5%8F%A5"><strong>5.5 &#x548C;shell&#x811A;&#x672C;&#x4E2D;&#x8F83;&#x76F8;&#x4F3C;&#x7684;&#x63A7;&#x5236;&#x8BED;&#x53E5;</strong></h3><h3 id="551-switch%E8%AF%AD%E5%8F%A5"><strong>5.5.1 switch&#x8BED;&#x53E5;</strong></h3><p>&#x548C;shell&#x4E2D;&#x7684;case&#x5F88;&#x50CF;&#xFF0C;&#x5C31;&#x4E0D;&#x5728;&#x6F14;&#x793A;&#x4E86;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">switch(expression) {case VALUE1 or /REGEXP/:statement1; case VALUE2 or /REGEXP2/: statement2;...; default: statementn}</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="552-break%E5%92%8Ccontinue"><strong>5.5.2 break&#x548C;continue</strong></h3><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">---&#x5947;&#x6570;&#x76F8;&#x52A0;<br><br>[root@along ~]# awk &apos;BEGIN{sum=0;for(i=1;i&lt;=100;i++){if(i%2==0)continue;sum+=i}print sum}&apos;<br><br>2500<br><br>---1+2+...+66<br><br>[root@along ~]# awk &apos;BEGIN{sum=0;for(i=1;i&lt;=100;i++){if(i==66)break;sum+=i}print sum}&apos;<br><br>2145</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="553-next"><strong>5.5.3 next</strong></h3><p>next&#xFF1A;&#x63D0;&#x524D;&#x7ED3;&#x675F;&#x5BF9;&#x672C;&#x884C;&#x5904;&#x7406;&#x800C;&#x76F4;&#x63A5;&#x8FDB;&#x5165;&#x4E0B;&#x4E00;&#x884C;&#x5904;&#x7406;&#xFF08;awk &#x81EA;&#x8EAB;&#x5FAA;&#x73AF;&#xFF09;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">---&#x53EA;&#x6253;&#x5370;&#x5076;&#x6570;&#x884C;<br><br>[root@along ~]# awk -F: &apos;{if(NR%2!=0) next; print $1,$3}&apos; /etc/passwd<br><br>bin 1<br><br>adm 3</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="56-awk%E6%95%B0%E7%BB%84"><strong>5.6 awk&#x6570;&#x7EC4;</strong></h3><h3 id="561-%E5%85%B3%E8%81%94%E6%95%B0%E7%BB%84%EF%BC%9Aarrayindex-expression"><strong>5.6.1 &#x5173;&#x8054;&#x6570;&#x7EC4;&#xFF1A;array[index-expression]</strong></h3><p>&#xFF08;1&#xFF09;&#x53EF;&#x4F7F;&#x7528;&#x4EFB;&#x610F;&#x5B57;&#x7B26;&#x4E32;&#xFF1B;&#x5B57;&#x7B26;&#x4E32;&#x8981;&#x4F7F;&#x7528;&#x53CC;&#x5F15;&#x53F7;&#x62EC;&#x8D77;&#x6765;</p><p>&#xFF08;2&#xFF09;&#x5982;&#x679C;&#x67D0;&#x6570;&#x7EC4;&#x5143;&#x7D20;&#x4E8B;&#x5148;&#x4E0D;&#x5B58;&#x5728;&#xFF0C;&#x5728;&#x5F15;&#x7528;&#x65F6;&#xFF0C;awk &#x4F1A;&#x81EA;&#x52A8;&#x521B;&#x5EFA;&#x6B64;&#x5143;&#x7D20;&#xFF0C;&#x5E76;&#x5C06;&#x5176;&#x503C;&#x521D;&#x59CB;&#x5316;&#x4E3A;&#x201C;&#x7A7A;&#x4E32;&#x201D;</p><p>&#xFF08;3&#xFF09;&#x82E5;&#x8981;&#x5224;&#x65AD;&#x6570;&#x7EC4;&#x4E2D;&#x662F;&#x5426;&#x5B58;&#x5728;&#x67D0;&#x5143;&#x7D20;&#xFF0C;&#x8981;&#x4F7F;&#x7528;&#x201C;index in array&#x201D;&#x683C;&#x5F0F;&#x8FDB;&#x884C;<strong>&#x904D;&#x5386;</strong></p><p>&#xFF08;4&#xFF09;&#x82E5;&#x8981;<strong>&#x904D;&#x5386;&#x6570;&#x7EC4;&#x4E2D;&#x7684;&#x6BCF;&#x4E2A;&#x5143;&#x7D20;</strong>&#xFF0C;&#x8981;&#x4F7F;&#x7528;for &#x5FAA;&#x73AF;<strong>&#xFF1A;for(var in array)</strong> {for-body}</p><h3 id="562-%E6%BC%94%E7%A4%BA"><strong>5.6.2 &#x6F14;&#x793A;</strong></h3><p>&#xFF08;1&#xFF09;awk&#x4F7F;&#x7528;&#x6570;&#x7EC4;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat awkdemo2<br><br>aaa<br><br>bbbb<br><br>aaa<br><br>123<br><br>123<br><br>123<br><br>---&#x53BB;&#x9664;&#x91CD;&#x590D;&#x7684;&#x884C;<br><br>[root@along ~]# awk &apos;!arr[$0]++&apos; awkdemo2<br><br>aaa<br><br>bbbb<br><br>123<br><br>---&#x6253;&#x5370;&#x6587;&#x4EF6;&#x5185;&#x5BB9;&#xFF0C;&#x548C;&#x8BE5;&#x884C;&#x91CD;&#x590D;&#x7B2C;&#x51E0;&#x6B21;&#x51FA;&#x73B0;<br><br>[root@along ~]# awk &apos;{!arr[$0]++;print $0,arr[$0]}&apos; awkdemo2<br><br>aaa 1<br><br>bbbb 1<br><br>aaa 2<br><br>123 1<br><br>123 2<br><br>123 3</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x5206;&#x6790;&#xFF1A;&#x628A;&#x6BCF;&#x884C;&#x4F5C;&#x4E3A;&#x4E0B;&#x6807;&#xFF0C;&#x7B2C;&#x4E00;&#x6B21;&#x8FDB;&#x6765;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;print ias...&#x4E00;&#x6837;&#x7ED3;&#x679C;&#x4E3A;&#x7A7A;&#xFF0C;&#x6253;&#x5370;&#x7A7A;&#xFF0C;!&#x53D6;&#x53CD;&#x7ED3;&#x679C;&#x4E3A;1&#xFF0C;&#x6253;&#x5370;&#x672C;&#x884C;&#xFF0C;&#x5E76;&#x4E14;++&#x53D8;&#x4E3A;&#x4E0D;&#x7A7A;&#xFF0C;&#x4E0B;&#x6B21;&#x8FDB;&#x6765;&#x76F8;&#x540C;&#x7684;&#x884C;&#x5C31;&#x662F;&#x76F8;&#x540C;&#x7684;&#x4E0B;&#x6807;&#xFF0C;&#x672C;&#x6765;&#x4E0A;&#x6B21;&#x7684;&#x503C;&#xFF0C;&#xFF01;&#x53D6;&#x53CD;&#x4E3A;&#x7A7A;&#xFF0C;&#x4E0D;&#x6253;&#x5370;&#xFF0C;++&#x53D8;&#x4E3A;&#x4E0D;&#x7A7A;&#xFF0C;&#x6240;&#x4EE5;&#x6BCF;&#x6B21;&#x91CD;&#x590D;&#x8FDB;&#x6765;&#x7684;&#x884C;&#x90FD;&#x4E0D;&#x6253;&#x5370;</p><p>&#xFF08;2&#xFF09;&#x6570;&#x7EC4;&#x904D;&#x5386;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk &apos;BEGIN{abc[&quot;ceo&quot;]=&quot;along&quot;;abc[&quot;coo&quot;]=&quot;mayun&quot;;abc[&quot;cto&quot;]=&quot;mahuateng&quot;;for(i in abc){print i,abc[i]}}&apos;<br><br>coo mayun<br><br>ceo along<br><br>cto mahuateng<br><br>[root@along ~]# awk &apos;{for(i=1;i&lt;=NF;i++)abc[$i]++}END{for(j in abc)print j,abc[j]}&apos; awkdemo2<br><br>aaa 2<br><br>bbbb 1<br><br>123 3</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="563-%E6%95%B0%E5%80%BC%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%A4%84%E7%90%86"><strong>5.6.3 &#x6570;&#x503C;\&#x5B57;&#x7B26;&#x4E32;&#x5904;&#x7406;</strong></h3><p>&#xFF08;1&#xFF09;&#x6570;&#x503C;&#x5904;&#x7406;</p><ul><li>rand()&#xFF1A;&#x8FD4;&#x56DE;0&#x548C;1&#x4E4B;&#x95F4;&#x4E00;&#x4E2A;&#x968F;&#x673A;&#x6570;&#xFF0C;&#x9700;&#x6709;&#x4E2A;&#x79CD;&#x5B50; srand()&#xFF0C;&#x6CA1;&#x6709;&#x79CD;&#x5B50;&#xFF0C;&#x4E00;&#x76F4;&#x8F93;&#x51FA;0.237788</li></ul><p>&#x6F14;&#x793A;&#xFF1A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk &apos;BEGIN{print rand()}&apos;<br><br>0.237788<br><br>[root@along ~]# awk &apos;BEGIN{srand(); print rand()}&apos;<br><br>0.51692<br><br>[root@along ~]# awk &apos;BEGIN{srand(); print rand()}&apos;<br><br>0.189917<br><br>---&#x53D6;0-50&#x968F;&#x673A;&#x6570;<br><br>[root@along ~]# awk &apos;BEGIN{srand(); print int(rand()*100%50)+1}&apos;<br><br>12<br><br>[root@along ~]# awk &apos;BEGIN{srand(); print int(rand()*100%50)+1}&apos;<br><br>24</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;2&#xFF09;&#x5B57;&#x7B26;&#x4E32;&#x5904;&#x7406;&#xFF1A;</p><ul><li>length([s]) &#xFF1A;&#x8FD4;&#x56DE;&#x6307;&#x5B9A;&#x5B57;&#x7B26;&#x4E32;&#x7684;&#x957F;&#x5EA6;</li><li>sub(r,s,[t]) &#xFF1A;&#x5BF9;t &#x5B57;&#x7B26;&#x4E32;&#x8FDB;&#x884C;&#x641C;&#x7D22;r &#x8868;&#x793A;&#x7684;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x7684;&#x5185;&#x5BB9;&#xFF0C;&#x5E76;<strong>&#x5C06;&#x7B2C;&#x4E00;&#x4E2A;</strong>&#x5339;&#x914D;&#x7684;&#x5185;&#x5BB9;&#x66FF;&#x6362;&#x4E3A;s</li><li>gsub(r,s,[t]) &#xFF1A;&#x5BF9;t &#x5B57;&#x7B26;&#x4E32;&#x8FDB;&#x884C;&#x641C;&#x7D22;r &#x8868;&#x793A;&#x7684;&#x6A21;&#x5F0F;&#x5339;&#x914D;&#x7684;&#x5185;&#x5BB9;&#xFF0C;<strong>&#x5E76;&#x5168;&#x90E8;&#x66FF;&#x6362;</strong>&#x4E3A;s &#x6240;&#x8868;&#x793A;&#x7684;&#x5185;&#x5BB9;</li><li>plit(s,array,[r]) &#xFF1A;&#x4EE5;r &#x4E3A;&#x5206;&#x9694;&#x7B26;&#xFF0C;&#x5207;&#x5272;&#x5B57;&#x7B26;&#x4E32;s &#xFF0C;&#x5E76;&#x5C06;&#x5207;&#x5272;&#x540E;&#x7684;&#x7ED3;&#x679C;&#x4FDD;&#x5B58;&#x81F3;array &#x6240;&#x8868;&#x793A;&#x7684;&#x6570;&#x7EC4;&#x4E2D;&#xFF0C;&#x7B2C;&#x4E00;&#x4E2A;&#x7D22;&#x5F15;&#x503C;&#x4E3A;1, &#x7B2C;&#x4E8C;&#x4E2A;&#x7D22;&#x5F15;&#x503C;&#x4E3A;2,&#x2026;</li></ul><p>&#x6F14;&#x793A;&#xFF1A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# echo &quot;2008:08:08 08:08:08&quot; | awk &apos;sub(/:/,&quot;-&quot;,$1)&apos;<br><br>2008-08:08 08:08:08<br><br>[root@along ~]# echo &quot;2008:08:08 08:08:08&quot; | awk &apos;gsub(/:/,&quot;-&quot;,$0)&apos;<br><br>2008-08-08 08-08-08<br><br>[root@along ~]# echo &quot;2008:08:08 08:08:08&quot; | awk &apos;{split($0,i,&quot;:&quot;)}END{for(n in i){print n,i[n]}}&apos;<br><br>4 08<br><br>5 08<br><br>1 2008<br><br>2 08<br><br>3 08 08</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="57-awk%E8%87%AA%E5%AE%9A%E4%B9%89%E5%87%BD%E6%95%B0"><strong>5.7 awk&#x81EA;&#x5B9A;&#x4E49;&#x51FD;&#x6570;</strong></h3><p>&#xFF08;1&#xFF09;&#x683C;&#x5F0F;&#xFF1A;&#x548C;bash&#x533A;&#x522B;&#xFF1A;&#x5B9A;&#x4E49;&#x51FD;&#x6570;&#xFF08;&#xFF09;&#x4E2D;&#x9700;&#x52A0;&#x53C2;&#x6570;&#xFF0C;return&#x8FD4;&#x56DE;&#x503C;&#x4E0D;&#x662F;$?&#xFF0C;&#x662F;&#x76F8;&#x5F53;&#x4E8E;echo&#x8F93;&#x51FA;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">function name ( parameter, parameter, ... ) {<br><br>statements<br><br>return expression<br><br>}</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;2&#xFF09;&#x6F14;&#x793A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat fun.awk<br><br>function max(v1,v2) {<br><br>v1&gt;v2?var=v1:var=v2<br><br>return var<br><br>}<br><br>BEGIN{a=3;b=2;print max(a,b)}<br><br>[root@along ~]# awk -f fun.awk<br><br>3</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h3 id="58-awk%E4%B8%AD%E8%B0%83%E7%94%A8shell-%E5%91%BD%E4%BB%A4"><strong>5.8 awk&#x4E2D;&#x8C03;&#x7528;shell &#x547D;&#x4EE4;</strong></h3><p>&#xFF08;1&#xFF09;system &#x547D;&#x4EE4;</p><p>&#x7A7A;&#x683C;&#x662F;awk &#x4E2D;&#x7684;&#x5B57;&#x7B26;&#x4E32;&#x8FDE;&#x63A5;&#x7B26;&#xFF0C;&#x5982;&#x679C;system&#x4E2D;&#x9700;&#x8981;&#x4F7F;&#x7528;awk&#x4E2D;&#x7684;&#x53D8;&#x91CF;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x7A7A;&#x683C;&#x5206;&#x9694;&#xFF0C;&#x6216;&#x8005;&#x8BF4;&#x9664;&#x4E86;awk &#x7684;&#x53D8;&#x91CF;&#x5916;&#x5176;&#x4ED6;&#x4E00;&#x5F8B;&#x7528;&quot;&quot; &#x5F15;&#x7528; &#x8D77;&#x6765;&#x3002;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# awk BEGIN&apos;{system(&quot;hostname&quot;) }&apos;<br><br>along<br><br>[root@along ~]# awk &apos;BEGIN{name=&quot;along&quot;;system(&quot;echo &quot;name)}&apos; &#x6CE8;&#xFF1A;&quot;echo &quot; echo&#x540E;&#x6709;&#x7A7A;&#x683C;<br><br>along<br><br>[root@along ~]# awk &apos;BEGIN{score=100; system(&quot;echo your score is &quot; score) }&apos;<br><br>your score is 100</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;2&#xFF09;awk &#x811A;&#x672C;</p><p>&#x5C06;awk &#x7A0B;&#x5E8F;&#x5199;&#x6210;&#x811A;&#x672C;&#xFF0C;&#x76F4;&#x63A5;&#x8C03;&#x7528;&#x6216;&#x6267;&#x884C;</p><p>&#x793A;&#x4F8B;&#xFF1A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat f1.awk<br><br>{if($3&gt;=1000)print $1,$3}<br><br>[root@along ~]# cat f2.awk<br><br>#!/bin/awk -f<br><br>{if($3 &gt;= 1000)print $1,$3}<br><br>[root@along ~]# chmod +x f2.awk<br><br>[root@along ~]# ./f2.awk -F: /etc/passwd<br><br>along 1000</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#xFF08;3&#xFF09;&#x5411;awk&#x811A;&#x672C;&#x4F20;&#x9012;&#x53C2;&#x6570;</p><p>&#x2460; &#x683C;&#x5F0F;&#xFF1A;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">awkfile var=value var2=value2... Inputfile</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><p>&#x6CE8;&#x610F; &#xFF1A;&#x5728;BEGIN &#x8FC7;&#x7A0B; &#x4E2D;&#x4E0D;&#x53EF;&#x7528;&#x3002;&#x76F4;&#x5230; &#x9996;&#x884C;&#x8F93;&#x5165;&#x5B8C;&#x6210;&#x4EE5;&#x540E;&#xFF0C;&#x53D8;&#x91CF;&#x624D;&#x53EF;&#x7528; &#x3002;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;<strong>-v &#x53C2;&#x6570;</strong>&#xFF0C;&#x8BA9;awk &#x5728;&#x6267;&#x884C;BEGIN &#x4E4B;&#x524D;&#x5F97;&#x5230;&#x53D8;&#x91CF;&#x7684;&#x503C;&#x3002;&#x547D;&#x4EE4;&#x884C;&#x4E2D;&#x6BCF;&#x4E00;&#x4E2A;&#x6307;&#x5B9A;&#x7684;&#x53D8;&#x91CF;&#x90FD;&#x9700;&#x8981;&#x4E00;&#x4E2A;-v</p><p>&#x2461; &#x793A;&#x4F8B;</p><!--kg-card-begin: html--><table data-draft-node="block" data-draft-type="table" data-size="normal" data-row-style="normal" style="border-collapse: collapse; font-size: 15px; margin: 1.4em auto; max-width: 100%; table-layout: fixed; text-align: left; width: 690px; color: rgb(25, 27, 31); font-family: -apple-system, BlinkMacSystemFont, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Source Han Sans SC&quot;, &quot;Noto Sans CJK SC&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><tbody><tr><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;">[root@along ~]# cat test.awk<br><br>#!/bin/awk -f<br><br>{if($3 &gt;=min &amp;&amp; $3&lt;=max)print $1,$3}<br><br>[root@along ~]# chmod +x test.awk<br><br>[root@along ~]# ./test.awk -F: min=100 max=200 /etc/passwd<br><br>systemd-network 192</td><td style="border: 1px solid rgb(196, 199, 206); height: 24px; line-height: 24px; padding: 3px 12px;"></td></tr></tbody></table><!--kg-card-end: html--><h2 id="6%E3%80%81grep-awk-sed%E5%AF%B9%E6%AF%94">6&#x3001;grep awk sed&#x5BF9;&#x6BD4;</h2><p>grep &#x4E3B;&#x8981;&#x7528;&#x4E8E;&#x641C;&#x7D22;&#x67D0;&#x4E9B;&#x5B57;&#x7B26;&#x4E32;&#xFF1B;</p><p>sed&#xFF0C;awk &#x7528;&#x4E8E;&#x5904;&#x7406;&#x6587;&#x672C; &#xFF1B;</p><p><strong>grep&#x57FA;&#x672C;&#x662F;&#x4EE5;&#x884C;&#x4E3A;&#x5355;&#x4F4D;&#x5904;&#x7406;&#x6587;&#x672C;&#x7684;&#xFF1B;</strong> <strong>&#x800C;awk&#x53EF;&#x4EE5;&#x505A;&#x66F4;&#x7EC6;&#x5206;&#x7684;&#x5904;&#x7406;&#xFF0C;&#x901A;&#x8FC7;&#x6307;&#x5B9A;&#x5206;&#x9694;&#x7B26;&#x5C06;&#x4E00;&#x884C;&#xFF08;&#x4E00;&#x6761;&#x8BB0;&#x5F55;&#xFF09;&#x5212;&#x5206;&#x4E3A;&#x591A;&#x4E2A;&#x5B57;&#x6BB5;&#xFF0C;&#x4EE5;&#x5B57;&#x6BB5;&#x4E3A;&#x5355;&#x4F4D;&#x5904;&#x7406;&#x6587;&#x672C;&#x3002;</strong>awk&#x4E2D;&#x652F;&#x6301;C&#x8BED;&#x6CD5;&#xFF0C;&#x53EF;&#x4EE5;&#x6709;&#x5206;&#x652F;&#x6761;&#x4EF6;&#x5224;&#x65AD;&#x3001;&#x5FAA;&#x73AF;&#x8BED;&#x53E5;&#x7B49;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;&#x4E00;&#x4E2A;&#x5C0F;&#x578B;&#x7F16;&#x7A0B;&#x8BED;&#x8A00;&#x3002;</p><p>awk&#x529F;&#x80FD;&#x6BD4;&#x8F83;&#x591A;&#x662F;&#x4E00;&#x4E2A;&#x7F16;&#x7A0B;&#x8BED;&#x8A00;&#x4E86;&#x3002; grep&#x529F;&#x80FD;&#x7B80;&#x5355;&#xFF0C;&#x5C31;&#x662F;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x6B63;&#x5219;&#x8868;&#x8FBE;&#x5F0F;&#x7684;&#x5339;&#x914D;&#x3002; awk&#x7684;&#x529F;&#x80FD;&#x4F9D;&#x8D56;&#x4E8E;grep&#x3002;</p><p><strong>grep&#x53EF;&#x4EE5;&#x7406;&#x89E3;&#x4E3A;&#x4E3B;&#x8981;&#x4F5C;&#x7528;&#x662F;&#x5728;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;&#x4E2D;&#x67E5;&#x627E;&#x8FC7;&#x6EE4;&#x9700;&#x8981;&#x7684;&#x5185;&#x5BB9;</strong>&#x3002;awk&#x4E0D;&#x662F;&#x8FC7;&#x6EE4;&#x67E5;&#x627E;&#xFF0C;&#x800C;&#x662F;&#x6587;&#x672C;&#x5904;&#x7406;&#x5DE5;&#x5177;&#xFF0C;&#x662F;&#x628A;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;&#x5904;&#x7406;&#x6210;&#x4F60;&#x60F3;&#x8981;&#x7684;&#x683C;&#x5F0F;&#x3002;</p><p>AWK&#x7684;&#x529F;&#x80FD;&#x662F;&#x4EC0;&#x4E48;&#xFF1F;&#x4E0E;sed&#x548C;grep&#x5F88;&#x76F8;&#x4F3C;&#xFF0C;<strong>awk&#x662F;&#x4E00;&#x79CD;&#x6837;&#x5F0F;&#x626B;&#x63CF;&#x4E0E;&#x5904;&#x7406;&#x5DE5;&#x5177;</strong>&#x3002;&#x4F46;&#x5176;&#x529F;&#x80FD;&#x5374;&#x5927;&#x5927;&#x5F3A;&#x4E8E;sed&#x548C;grep&#x3002;awk&#x63D0;&#x4F9B;&#x4E86;&#x6781;&#x5176;&#x5F3A;&#x5927;&#x7684;&#x529F;&#x80FD;&#xFF1A;&#x5B83;&#x51E0;&#x4E4E;&#x53EF;&#x4EE5;&#x5B8C;&#x6210;grep&#x548C;sed&#x6240;&#x80FD;&#x5B8C;&#x6210;&#x7684;&#x5168;&#x90E8;&#x5DE5;&#x4F5C;&#xFF0C;&#x540C;&#x65F6;&#xFF0C;&#x5B83;&#x8FD8;&#x53EF;&#x4EE5;&#x53EF;&#x4EE5;&#x8FDB;&#x884C;<strong>&#x6837;&#x5F0F;&#x88C5;&#x5165;&#x3001;&#x6D41;&#x63A7;&#x5236;&#x3001;&#x6570;&#x5B66;&#x8FD0;&#x7B97;&#x7B26;&#x3001;&#x8FDB;&#x7A0B;&#x63A7;&#x5236;&#x8BED;&#x53E5;&#x751A;&#x81F3;&#x4E8E;&#x5185;&#x7F6E;&#x7684;&#x53D8;&#x91CF;&#x548C;&#x51FD;&#x6570;</strong>&#x3002;&#x5B83;&#x5177;&#x5907;&#x4E86;&#x4E00;&#x4E2A;&#x5B8C;&#x6574;&#x7684;&#x8BED;&#x8A00;&#x6240;&#x5E94;&#x5177;&#x6709;&#x7684;&#x51E0;&#x4E4E;&#x6240;&#x6709;&#x7CBE;&#x7F8E;&#x7279;&#x6027;&#x3002;&#x5B9E;&#x9645;&#x4E0A;&#xFF0C;awk&#x7684;&#x786E;&#x62E5;&#x6709;&#x81EA;&#x5DF1;&#x7684;&#x8BED;&#x8A00;&#xFF1A;awk&#x7A0B;&#x5E8F;&#x8BBE;&#x8BA1;&#x8BED;&#x8A00;&#xFF0C;awk&#x7684;&#x4E09;&#x4F4D;&#x521B;&#x5EFA;&#x8005;&#x5DF2;&#x5C06;&#x5B83;&#x6B63;&#x5F0F;&#x5B9A;&#x4E49;&#x4E3A;&#xFF1A;&#x6837;&#x5F0F;&#x626B;&#x63CF;&#x548C;&#x5904;&#x7406;&#x8BED;&#x8A00;&#x3002;&#x4F7F;&#x7528;awk&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x7406;&#x7531;&#x662F;&#x57FA;&#x4E8E;&#x6587;&#x672C;&#x7684;&#x6837;&#x5F0F;&#x626B;&#x63CF;&#x548C;&#x5904;&#x7406;&#x662F;&#x6211;&#x4EEC;&#x7ECF;&#x5E38;&#x505A;&#x7684;&#x5DE5;&#x4F5C;&#xFF0C;awk&#x6240;&#x505A;&#x7684;&#x5DE5;&#x4F5C;&#x6709;&#x4E9B;&#x8C61;&#x6570;&#x636E;&#x5E93;&#xFF0C;&#x4F46;&#x4E0E;&#x6570;&#x636E;&#x5E93;&#x4E0D;&#x540C;&#x7684;&#x662F;&#xFF0C;&#x5B83;&#x5904;&#x7406;&#x7684;&#x662F;&#x6587;&#x672C;&#x6587;&#x4EF6;&#xFF0C;&#x8FD9;&#x4E9B;&#x6587;&#x4EF6;&#x6CA1;&#x6709;&#x4E13;&#x95E8;&#x7684;&#x5B58;&#x50A8;&#x683C;&#x5F0F;&#xFF0C;&#x666E;&#x901A;&#x7684;&#x4EBA;&#x4EEC;&#x5C31;&#x80FD;&#x7F16;&#x8F91;&#x3001;&#x9605;&#x8BFB;&#x3001;&#x7406;&#x89E3;&#x548C;&#x5904;&#x7406;&#x5B83;&#x4EEC;&#x3002;&#x800C;&#x6570;&#x636E;&#x5E93;&#x6587;&#x4EF6;&#x5F80;&#x5F80;&#x5177;&#x6709;&#x7279;&#x6B8A;&#x7684;&#x5B58;&#x50A8;&#x683C;&#x5F0F;&#xFF0C;&#x8FD9;&#x4F7F;&#x5F97;&#x5B83;&#x4EEC;&#x5FC5;&#x987B;&#x7528;&#x6570;&#x636E;&#x5E93;&#x5904;&#x7406;&#x7A0B;&#x5E8F;&#x6765;&#x5904;&#x7406;&#x5B83;&#x4EEC;&#x3002;&#x65E2;&#x7136;&#x8FD9;&#x79CD;&#x7C7B;&#x4F3C;&#x4E8E;&#x6570;&#x636E;&#x5E93;&#x7684;&#x5904;&#x7406;&#x5DE5;&#x4F5C;&#x6211;&#x4EEC;&#x7ECF;&#x5E38;&#x4F1A;&#x9047;&#x5230;&#xFF0C;&#x6211;&#x4EEC;&#x5C31;&#x5E94;&#x5F53;&#x627E;&#x5230;&#x5904;&#x7406;&#x5B83;&#x4EEC;&#x7684;&#x7B80;&#x4FBF;&#x6613;&#x884C;&#x7684;&#x65B9;&#x6CD5;&#xFF0C;UNIX&#x6709;&#x5F88;&#x591A;&#x8FD9;&#x65B9;&#x9762;&#x7684;&#x5DE5;&#x5177;&#xFF0C;&#x4F8B;&#x5982;sed &#x3001;grep&#x3001;sort&#x4EE5;&#x53CA;find&#x7B49;&#x7B49;&#xFF0C;awk&#x662F;&#x5176;&#x4E2D;&#x5341;&#x5206;&#x4F18;&#x79C0;&#x7684;&#x4E00;&#x79CD;&#x3002;</p><p><strong>&#x4F7F;&#x7528;awk&#x7684;&#x7B2C;&#x4E8C;&#x4E2A;&#x7406;&#x7531;&#x662F;awk&#x662F;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x5DE5;&#x5177;</strong>&#xFF0C;&#x5F53;&#x7136;&#x8FD9;&#x662F;&#x76F8;&#x5BF9;&#x4E8E;&#x5176;&#x5F3A;&#x5927;&#x7684;&#x529F;&#x80FD;&#x6765;&#x8BF4;&#x7684;&#x3002;&#x7684;&#x786E;&#xFF0C;UNIX&#x6709;&#x8BB8;&#x591A;&#x4F18;&#x79C0;&#x7684;&#x5DE5;&#x5177;&#xFF0C;&#x4F8B;&#x5982;UNIX&#x5929;&#x7136;&#x7684;&#x5F00;&#x53D1;&#x5DE5;&#x5177;C&#x8BED;&#x8A00;&#x53CA;&#x5176;&#x5EF6;&#x7EED;C++&#x5C31;&#x975E;&#x5E38;&#x7684;&#x4F18;&#x79C0;&#x3002;&#x4F46;&#x76F8;&#x5BF9;&#x4E8E;&#x5B83;&#x4EEC;&#x6765;&#x8BF4;&#xFF0C;awk&#x5B8C;&#x6210;&#x540C;&#x6837;&#x7684;&#x529F;&#x80FD;&#x8981;&#x65B9;&#x4FBF;&#x548C;&#x7B80;&#x6377;&#x5F97;&#x591A;&#x3002;&#x8FD9;&#x9996;&#x5148;&#x662F;&#x56E0;&#x4E3A;awk&#x63D0;&#x4F9B;&#x4E86;&#x9002;&#x5E94;&#x591A;&#x79CD;&#x9700;&#x8981;&#x7684;&#x89E3;&#x51B3;&#x65B9;&#x6848;&#xFF1A;&#x4ECE;&#x89E3;&#x51B3;&#x7B80;&#x5355;&#x95EE;&#x9898;&#x7684;awk&#x547D;&#x4EE4;&#x884C;&#x5230;&#x590D;&#x6742;&#x800C;&#x7CBE;&#x5DE7;&#x7684;awk&#x7A0B;&#x5E8F;&#x8BBE;&#x8BA1;&#x8BED;&#x8A00;&#xFF0C;&#x8FD9;&#x6837;&#x505A;&#x7684;&#x597D;&#x5904;&#x662F;&#xFF0C;&#x4F60;&#x53EF;&#x4EE5;&#x4E0D;&#x5FC5;&#x7528;&#x590D;&#x6742;&#x7684;&#x65B9;&#x6CD5;&#x53BB;&#x89E3;&#x51B3;&#x672C;&#x6765;&#x5F88;&#x7B80;&#x5355;&#x7684;&#x95EE;&#x9898;&#x3002;&#x4F8B;&#x5982;&#xFF0C;&#x4F60;&#x53EF;&#x4EE5;&#x7528;&#x4E00;&#x4E2A;&#x547D;&#x4EE4;&#x884C;&#x89E3;&#x51B3;&#x7B80;&#x5355;&#x7684;&#x95EE;&#x9898;&#xFF0C;&#x800C;C&#x4E0D;&#x884C;&#xFF0C;&#x5373;&#x4F7F;&#x4E00;&#x4E2A;&#x518D;&#x7B80;&#x5355;&#x7684;&#x7A0B;&#x5E8F;&#xFF0C;C&#x8BED;&#x8A00;&#x4E5F;&#x5FC5;&#x987B;&#x7ECF;&#x8FC7;&#x7F16;&#x5199;&#x3001;&#x7F16;&#x8BD1;&#x7684;&#x5168;&#x8FC7;&#x7A0B;&#x3002;&#x5176;&#x6B21;&#xFF0C;awk&#x672C;&#x8EAB;&#x662F;&#x89E3;&#x91CA;&#x6267;&#x884C;&#x7684;&#xFF0C;&#x8FD9;&#x5C31;&#x4F7F;&#x5F97;awk&#x7A0B;&#x5E8F;&#x4E0D;&#x5FC5;&#x7ECF;&#x8FC7;&#x7F16;&#x8BD1;&#x7684;&#x8FC7;&#x7A0B;&#xFF0C;&#x540C;&#x65F6;&#xFF0C;&#x8FD9;&#x4E5F;&#x4F7F;&#x5F97;&#x5B83;&#x4E0E;shell script&#x7A0B;&#x5E8F;&#x80FD;&#x591F;&#x5F88;&#x597D;&#x7684;&#x5951;&#x5408;&#x3002;&#x6700;&#x540E;&#xFF0C;awk&#x672C;&#x8EAB;&#x8F83;C&#x8BED;&#x8A00;&#x7B80;&#x5355;&#xFF0C;&#x867D;&#x7136;awk&#x5438;&#x6536;&#x4E86;C&#x8BED;&#x8A00;&#x5F88;&#x591A;&#x4F18;&#x79C0;&#x7684;&#x6210;&#x5206;&#xFF0C;&#x719F;&#x6089;C&#x8BED;&#x8A00;&#x4F1A;&#x5BF9;&#x5B66;&#x4E60;awk&#x6709;&#x5F88;&#x5927;&#x7684;&#x5E2E;&#x52A9;&#xFF0C;&#x4F46;awk&#x672C;&#x8EAB;&#x4E0D;&#x987B;&#x8981;&#x4F1A;&#x4F7F;&#x7528;C&#x8BED;&#x8A00;&#x2014;&#x2014;&#x4E00;&#x79CD;&#x529F;&#x80FD;&#x5F3A;&#x5927;&#x4F46;&#x9700;&#x8981;&#x5927;&#x91CF;&#x65F6;&#x95F4;&#x5B66;&#x4E60;&#x624D;&#x80FD;&#x638C;&#x63E1;&#x5176;&#x6280;&#x5DE7;&#x7684;&#x5F00;&#x53D1;&#x5DE5;&#x5177;&#x3002;</p><p><strong>&#x4F7F;&#x7528;awk&#x7684;&#x7B2C;&#x4E09;&#x4E2A;&#x7406;&#x7531;&#x662F;awk&#x662F;&#x4E00;&#x4E2A;&#x5BB9;&#x6613;&#x83B7;&#x5F97;&#x7684;&#x5DE5;&#x5177;</strong>&#x3002;&#x4E0E;C&#x548C;C++&#x8BED;&#x8A00;&#x4E0D;&#x540C;&#xFF0C;awk&#x53EA;&#x6709;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;(/bin/awk)&#xFF0C;&#x800C;&#x4E14;&#x51E0;&#x4E4E;&#x6BCF;&#x4E2A;&#x7248;&#x672C;&#x7684;UNIX&#x90FD;&#x63D0;&#x4F9B;&#x5404;&#x81EA;&#x7248;&#x672C;&#x7684;awk&#xFF0C;&#x4F60;&#x5B8C;&#x5168;&#x4E0D;&#x5FC5;&#x8D39;&#x5FC3;&#x53BB;&#x60F3;&#x5982;&#x4F55;&#x83B7;&#x5F97;awk&#x3002;&#x4F46;C&#x8BED;&#x8A00;&#x5374;&#x4E0D;&#x662F;&#x8FD9;&#x6837;&#xFF0C;&#x867D;&#x7136;C&#x8BED;&#x8A00;&#x662F;UNIX&#x5929;&#x7136;&#x7684;&#x5F00;&#x53D1;&#x5DE5;&#x5177;&#xFF0C;&#x4F46;&#x8FD9;&#x4E2A;&#x5F00;&#x53D1;&#x5DE5;&#x5177;&#x5374;&#x662F;&#x5355;&#x72EC;&#x53D1;&#x884C;&#x7684;&#xFF0C;&#x6362;&#x8A00;&#x4E4B;&#xFF0C;&#x4F60;&#x5FC5;&#x987B;&#x4E3A;&#x4F60;&#x7684;UNIX&#x7248;&#x672C;&#x7684;C&#x8BED;&#x8A00;&#x5F00;&#x53D1;&#x5DE5;&#x5177;&#x5355;&#x72EC;&#x4ED8;&#x8D39;&#xFF08;&#x5F53;&#x7136;&#x4F7F;&#x7528;D&#x7248;&#x8005;&#x9664;&#x5916;&#xFF09;&#xFF0C;&#x83B7;&#x5F97;&#x5E76;&#x5B89;&#x88C5;&#x5B83;&#xFF0C;&#x7136;&#x540E;&#x4F60;&#x624D;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x5B83;&#x3002;</p><p>&#x57FA;&#x4E8E;&#x4EE5;&#x4E0A;&#x7406;&#x7531;&#xFF0C;&#x518D;&#x52A0;&#x4E0A;awk&#x5F3A;&#x5927;&#x7684;&#x529F;&#x80FD;&#xFF0C;&#x6211;&#x4EEC;&#x6709;&#x7406;&#x7531;&#x8BF4;&#xFF0C;&#x5982;&#x679C;&#x4F60;&#x8981;&#x5904;&#x7406;&#x4E0E;&#x6587;&#x672C;&#x6837;&#x5F0F;&#x626B;&#x63CF;&#x76F8;&#x5173;&#x7684;&#x5DE5;&#x4F5C;&#xFF0C;awk&#x5E94;&#x8BE5;&#x662F;&#x4F60;&#x7684;&#x7B2C;&#x4E00;&#x9009;&#x62E9;&#x3002;&#x5728;&#x8FD9;&#x91CC;&#x6709;&#x4E00;&#x4E2A;&#x53EF;&#x9075;&#x5FAA;&#x7684;&#x4E00;&#x822C;&#x539F;&#x5219;&#xFF1A;&#x5982;&#x679C;&#x4F60;&#x7528;&#x666E;&#x901A;&#x7684;shell&#x5DE5;&#x5177;&#x6216;shell script&#x6709;&#x56F0;&#x96BE;&#x7684;&#x8BDD;&#xFF0C;&#x8BD5;&#x8BD5;awk,&#x5982;&#x679C;awk&#x4ECD;&#x4E0D;&#x80FD;&#x89E3;&#x51B3;&#x95EE;&#x9898;&#xFF0C;&#x5219;&#x4FBF;&#x7528;C&#x8BED;&#x8A00;&#xFF0C;&#x5982;&#x679C;C&#x8BED;&#x8A00;&#x4ECD;&#x7136;&#x5931;&#x8D25;&#xFF0C;&#x5219;&#x79FB;&#x81F3;C++&#x3002;</p><p><strong>sed&#x662F;&#x4E00;&#x4E2A;&#x975E;&#x4EA4;&#x4E92;&#x6027;&#x6587;&#x672C;&#x6D41;&#x7F16;&#x8F91;&#x5668;&#x3002;</strong>&#x5B83;&#x7F16;&#x8F91;&#x6587;&#x4EF6;&#x6216;&#x6807;&#x51C6;&#x8F93;&#x5165;&#x5BFC;&#x51FA;&#x7684;&#x6587;&#x672C;&#x62F7;&#x8D1D;&#x3002;sed&#x7F16;&#x8F91;&#x5668;&#x6309;&#x7167;&#x4E00;&#x6B21;&#x5904;&#x7406; &#x4E00;&#x884C;&#x7684;&#x65B9;&#x5F0F;&#x6765;&#x5904;&#x7406;&#x6587;&#x4EF6;&#xFF08;&#x6216;&#x8005;&#x8F93;&#x5165;&#xFF09;&#x5E76;&#x628A;&#x8F93;&#x51FA;&#x9001;&#x5230;&#x5C4F;&#x5E55;&#x4E0A;&#x3002;&#x4F60;&#x53EF;&#x4EE5;&#x5728;vi&#x548C;ex/ed&#x7F16;&#x8F91;&#x5668;&#x91CC;&#x8BC6;&#x522B;&#x4ED6;&#x7684;&#x547D;&#x4EE4;&#x3002;sed&#x628A;&#x5F53;&#x524D;&#x6B63;&#x5728;&#x5904;&#x7406;&#x7684;&#x884C;&#x4FDD;&#x5B58;&#x5728;&#x4E00;&#x4E2A;&#x4E34;&#x65F6;&#x7F13;&#x5B58;&#x91CC;&#xFF0C;&#x8FD9;&#x4E2A;&#x7F13;&#x5B58;&#x53EB;&#x505A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x3002;&#x4E00;&#x4F46;sed&#x5B8C;&#x6210;&#x4E86;&#x5BF9;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x91CC;&#x7684;&#x884C;&#x7684;&#x5904;&#x7406;&#xFF08;&#x5373;&#x5BF9;&#x8BE5;&#x884C;&#x6267;&#x884C;sed&#x547D;&#x4EE4;&#xFF09;&#xFF0C;&#x5C31;&#x628A;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x7684;&#x884C;&#x9001;&#x5230;&#x5C4F;&#x5E55;&#x4E0A;&#xFF08;&#x9664;&#x975E;&#x8BE5;&#x547D;&#x4EE4;&#x8981;&#x5220;&#x9664;&#x8BE5;&#x884C;&#x6D3B;&#x7981;&#x6B62;&#x6253;&#x5370;&#xFF09;&#x3002;&#x5904;&#x7406;&#x5B8C;&#x8BE5;&#x884C;&#x4E4B;&#x540E;&#xFF0C;&#x4ECE;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#x91CC;&#x5220;&#x9664;&#x5B83;&#xFF0C;&#x7136;&#x540E;&#x628A;&#x4E0B;&#x4E00;&#x884C;&#x8BFB;&#x5165;&#x6A21;&#x5F0F;&#x7A7A;&#x95F4;&#xFF0C;&#x8FDB;&#x884C;&#x5904;&#x7406;&#xFF0C;&#x5E76;&#x663E;&#x793A;&#x3002;&#x5F53;&#x8F93;&#x5165;&#x6587;&#x4EF6;&#x7684;&#x6700;&#x540E;&#x4E00;&#x884C;&#x5904;&#x7406;&#x5B8C;&#x540E;&#xFF0C;sed&#x7EC8;&#x6B62;&#x3002;&#x901A;&#x8FC7;&#x628A;&#x6BCF;&#x4E00;&#x884C;&#x5B58;&#x5728;&#x4E00;&#x4E2A;&#x4E34;&#x65F6;&#x7F13;&#x5B58;&#x91CC;&#x5E76;&#x7F16;&#x8F91;&#x8BE5;&#x884C;&#xFF0C;&#x521D;&#x59CB;&#x6587;&#x4EF6;&#x4E0D;&#x4F1A;&#x88AB;&#x4FEE;&#x6539;&#x6216;&#x88AB;&#x7834;&#x574F;&#x3002;</p>]]></content:encoded></item><item><title><![CDATA[万字解析 go 语言分布式消息队列 NSQ]]></title><description><![CDATA[<h2 id="0-%E5%89%8D%E8%A8%80">0 &#x524D;&#x8A00;</h2><p>&#x672C;&#x671F;&#x548C;&#x5927;&#x5BB6;&#x4E00;&#x8D77;&#x63A2;&#x8BA8;&#x4E00;&#x6B3E;&#x5B8C;&#x5168;&#x57FA;&#x4E8E; go &#x8BED;&#x8A00;&#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x6D88;&#x606F;&#x961F;&#x5217;&#x2014;&#x2014;nsq.</p><p>&#x6709;&#x5173;&#x4E8E;&#x6D88;&#x606F;&#x961F;&#x5217; Message Queue &#x7684;&#x6982;&#x5FF5;&#x53CA;&#x4F5C;&#x7528;&#xFF0C;</p>]]></description><link>http://www.net-e.cn/mo-zi-jie-xi-go-yu-yan-fen-bu-shi-xiao-xi-dui-lie-nsq/</link><guid isPermaLink="false">65824ba01cca100001bb3f6f</guid><dc:creator><![CDATA[Liang Wang]]></dc:creator><pubDate>Wed, 20 Dec 2023 02:05:37 GMT</pubDate><content:encoded><![CDATA[<h2 id="0-%E5%89%8D%E8%A8%80">0 &#x524D;&#x8A00;</h2><p>&#x672C;&#x671F;&#x548C;&#x5927;&#x5BB6;&#x4E00;&#x8D77;&#x63A2;&#x8BA8;&#x4E00;&#x6B3E;&#x5B8C;&#x5168;&#x57FA;&#x4E8E; go &#x8BED;&#x8A00;&#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x6D88;&#x606F;&#x961F;&#x5217;&#x2014;&#x2014;nsq.</p><p>&#x6709;&#x5173;&#x4E8E;&#x6D88;&#x606F;&#x961F;&#x5217; Message Queue &#x7684;&#x6982;&#x5FF5;&#x53CA;&#x4F5C;&#x7528;&#xFF0C;&#x5927;&#x5BB6;&#x53EF;&#x4EE5;&#x53C2;&#x8003;&#x6211;&#x4E4B;&#x524D;&#x53D1;&#x8868;&#x7684;&#x6587;&#x7AE0;&#x2014;&#x2014;&#x4E07;&#x5B57;&#x957F;&#x6587;&#x89E3;&#x6790;&#x5982;&#x4F55;&#x57FA;&#x4E8E;Redis&#x5B9E;&#x73B0;&#x6D88;&#x606F;&#x961F;&#x5217;&#xFF0C;&#x8FD9;&#x4E9B;&#x57FA;&#x7840;&#x77E5;&#x8BC6;&#x672C;&#x6587;&#x4E0D;&#x518D;&#x8D58;&#x8FF0;.</p><p>nsq &#x662F;&#x4E00;&#x6B3E;&#x57FA;&#x4E8E; go &#x8BED;&#x8A00;&#x5F00;&#x53D1;&#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x6D88;&#x606F;&#x961F;&#x5217;&#x7EC4;&#x4EF6;&#xFF0C;&#x5728; golang &#x4E16;&#x754C;&#x4E2D;&#x62E5;&#x6709;&#x7740;&#x5F88;&#x9AD8;&#x7684;&#x8BA4;&#x53EF;&#x5EA6;&#x548C;&#x6D41;&#x884C;&#x6027;&#xFF0C;&#x622A;&#x6B62;&#x4ECA;&#x65E5;&#x5728; github &#x4E0A;&#x7684; stars &#x6570;&#x5DF2;&#x9AD8;&#x8FBE; 23 k. &#x672C;&#x671F;&#x4F1A;&#x6D89;&#x53CA;&#x5927;&#x91CF;&#x5BF9; nsq &#x7684;&#x6E90;&#x7801;&#x8D70;&#x8BFB;&#x73AF;&#x8282;&#xFF0C;&#x4E3B;&#x8981;&#x5305;&#x542B;&#xFF1A;</p><ul><li>nsq &#x5BA2;&#x6237;&#x7AEF;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//github.com/nsqio/go-nsq" rel="nofollow noreferrer">https://github.com/nsqio/go-nsq</a> . &#x672C;&#x6587;&#x8D70;&#x8BFB;&#x6E90;&#x7801;&#x7248;&#x672C;&#x4E3A;&#xFF1A;v1.1.0.</li><li>nsq &#x670D;&#x52A1;&#x7AEF;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//github.com/nsqio/nsq" rel="nofollow noreferrer">https://github.com/nsqio/nsq</a> . &#x672C;&#x6587;&#x8D70;&#x8BFB;&#x6E90;&#x7801;&#x7248;&#x672C;&#x4E3A;&#xFF1A;v1.2.1.</li></ul><p>&#x6B64;&#x5916;&#x6709;&#x4E00;&#x4E2A;&#x62D3;&#x5C55;&#x6027;&#x5185;&#x5BB9;&#xFF0C;&#x6D89;&#x53CA;&#x5230; nsq &#x670D;&#x52A1;&#x7AEF;&#x4E0E;&#x78C1;&#x76D8;&#x7684;&#x5B58;&#x50A8;&#x4EA4;&#x4E92;&#x64CD;&#x4F5C;&#xFF0C;&#x5BF9;&#x5E94;&#x9879;&#x76EE;&#x4E3A; <a href="https://link.zhihu.com/?target=https%3A//github.com/nsqio/go-diskqueue" rel="nofollow noreferrer">https://github.com/nsqio/go-diskqueue</a> . &#x5927;&#x5BB6;&#x611F;&#x5174;&#x8DA3;&#x53EF;&#x81EA;&#x884C;&#x62D3;&#x5C55;&#x5B66;&#x4E60;&#xFF0C;&#x8FD9;&#x90E8;&#x5206;&#x5185;&#x5BB9;&#x672C;&#x6587;&#x4E0D;&#x4F5C;&#x5C55;&#x5F00;.</p><p>&#x672C;&#x671F;&#x5206;&#x4EAB;&#x5185;&#x5BB9;&#x7684;&#x5927;&#x7EB2;&#x7F57;&#x5217;&#x5982;&#x4E0B;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-c40ff09df8cabbf3206ba2ce8767cb12_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="1-%E6%9E%B6%E6%9E%84%E4%BB%8B%E7%BB%8D">1 &#x67B6;&#x6784;&#x4ECB;&#x7ECD;</h2><p>&#x672C;&#x7AE0;&#x6211;&#x4EEC;&#x9996;&#x5148;&#x6765;&#x7406;&#x6E05;&#x695A; nsq &#x7684;&#x6574;&#x4F53;&#x67B6;&#x6784;&#x548C;&#x6838;&#x5FC3;&#x6982;&#x5FF5;&#xFF0C;&#x5728;&#x5927;&#x7684;&#x65B9;&#x5411;&#x4E0A;&#x5EFA;&#x7ACB;&#x4E00;&#x5B9A;&#x7684;&#x7406;&#x89E3;&#x57FA;&#x7840;&#xFF0C;&#x518D;&#x5728;&#x540E;&#x7EED;&#x7AE0;&#x8282;&#x4E2D;&#x57FA;&#x4E8E;&#x5404;&#x4E2A;&#x4E3B;&#x8981;&#x6D41;&#x7A0B;&#x5C55;&#x5F00;&#x6280;&#x672F;&#x7EC6;&#x8282;&#x7684;&#x63A2;&#x8BA8;.</p><h2 id="11-%E6%95%B4%E4%BD%93%E6%9E%B6%E6%9E%84">1.1 &#x6574;&#x4F53;&#x67B6;&#x6784;</h2><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-8d66648eb43322e733ef4d029f2c08bf_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>nsq &#x53EF;&#x4EE5;&#x62C6;&#x5206;&#x4E3A;&#x4E09;&#x4E2A;&#x7EC4;&#x4EF6;&#xFF1A;</p><ul><li><strong>nsqd&#xFF1A;&#x6700;&#x6838;&#x5FC3;&#x7684;&#x6D88;&#x606F;&#x961F;&#x5217;&#x540E;&#x7AEF;&#x6A21;&#x5757;</strong>&#xFF0C;&#x8D1F;&#x8D23;&#x63A5;&#x6536;&#x3001;&#x5B58;&#x50A8;&#x548C;&#x53D1;&#x9001;&#x6D88;&#x606F;</li><li><strong>nsqlookupd&#xFF1A;nsq &#x4E2D;&#x7684;&#x670D;&#x52A1;&#x53D1;&#x73B0;&#x4E0E;&#x6CE8;&#x518C;&#x4E2D;&#x5FC3;</strong>&#xFF0C;&#x8D1F;&#x8D23;&#x7BA1;&#x7406; nsqd &#x8282;&#x70B9;&#x3001;topic&#x3001;channel &#x4E4B;&#x95F4;&#x62D3;&#x6251;&#x6620;&#x5C04;&#x5173;&#x7CFB;</li><li>nsqadmin&#xFF1A;&#x63D0;&#x4F9B;&#x4E86;&#x7528;&#x4E8E;&#x5B9E;&#x65F6;&#x76D1;&#x63A7; nsq &#x96C6;&#x7FA4;&#x7684; web &#x53EF;&#x89C6;&#x5316;&#x754C;&#x9762;</li></ul><h2 id="12-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5">1.2 &#x6838;&#x5FC3;&#x6982;&#x5FF5;</h2><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-979038f3833ebbfe63aad30d1f880c2f_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>nsq &#x6574;&#x4F53;&#x67B6;&#x6784;&#x5982;&#x4E0A;&#x56FE;&#x6240;&#x793A;&#xFF0C;&#x5176;&#x4E2D;&#x6D89;&#x53CA;&#x5230;&#x7684; topic&#x3001;channel&#x3001;producer&#x3001;consumer &#x7B49;&#x6982;&#x5FF5;&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x9010;&#x4E00;&#x62C6;&#x89E3;&#xFF1A;</p><ul><li><strong>topic&#xFF1A;&#x4EBA;&#x4E3A;&#x5B9A;&#x4E49;&#x7684;&#x6D88;&#x606F;&#x4E3B;&#x9898;</strong>&#xFF0C;&#x6240;&#x6709;&#x88AB;&#x751F;&#x4EA7;&#x51FA;&#x6765;&#x7684;&#x6D88;&#x606F;&#x9996;&#x5148;&#x6307;&#x5B9A;&#x5176;&#x88AB;&#x53D1;&#x5F80;&#x54EA;&#x4E2A;&#x4E3B;&#x9898;.</li><li><strong>channel&#xFF1A;&#x6D88;&#x8D39;&#x65B9;&#x5B9A;&#x4E49;&#x7684;&#x6D88;&#x606F;&#x9891;&#x9053;</strong>. channel &#x4E0E; topic &#x662F;&#x591A;&#x5BF9;&#x4E00;&#x5173;&#x7CFB;&#xFF0C;&#x6BCF;&#x4E2A; channel &#x90FD;&#x4F1A;&#x62E5;&#x6709;&#x4E00;&#x4EFD; topic &#x4E0B;&#x7684;&#x5168;&#x91CF;&#x5B8C;&#x6574;&#x6570;&#x636E;</li><li><strong>producer&#xFF1A;&#x6D88;&#x606F;&#x751F;&#x4EA7;&#x65B9;</strong>&#xFF0C;&#x751F;&#x4EA7;&#x6D88;&#x606F;&#x65F6;&#x9700;&#x8981;&#x663E;&#x5F0F;&#x6307;&#x5B9A;&#x5176;&#x4ECE;&#x5C5E;&#x7684; topic</li><li><strong>consumer&#xFF1A;&#x6D88;&#x606F;&#x6D88;&#x8D39;&#x65B9;</strong>. &#x6D88;&#x8D39;&#x6D88;&#x606F;&#x65F6;&#x9700;&#x8981;&#x663E;&#x5F0F;&#x6307;&#x5B9A;&#x4E3B;&#x9898; topic &#x4EE5;&#x53CA;&#x9891;&#x9053; channel</li></ul><p>&#x8FD9;&#x91CC;&#x6211;&#x4EEC;&#x7740;&#x91CD;&#x89E3;&#x91CA;&#x4E00;&#x4E0B; channel &#x7684;&#x6982;&#x5FF5;.<strong> channel &#x53EF;&#x4EE5;&#x4E0E;&#x5176;&#x4ED6;&#x6D88;&#x8D39;&#x961F;&#x5217;&#x7EC4;&#x4EF6;&#x4E2D;&#x7684; consumer group &#x6D88;&#x8D39;&#x8005;&#x7EC4;&#x7684;&#x6982;&#x5FF5;&#x7C7B;&#x6BD4;</strong>&#x6765;&#x770B;&#xFF1A;</p><ul><li>&#x9996;&#x5148;&#xFF0C;<strong>channel &#x4E0E; topic &#x662F;&#x4E00;&#x5BF9;&#x591A;&#x5173;&#x7CFB;</strong>&#xFF0C;&#x6BCF;&#x5F53; topic &#x6709;&#x65B0;&#x6D88;&#x606F;&#x5230;&#x8FBE;&#x65F6;&#xFF0C;&#x90FD;&#x4F1A;&#x62F7;&#x8D1D;&#x6210;&#x591A;&#x4EFD;&#xFF0C;&#x9010;&#x4E00;&#x53D1;&#x9001;&#x5230;&#x6BCF;&#x4E2A; channel &#x5F53;&#x4E2D;&#xFF0C;&#x4FDD;&#x8BC1;<strong>&#x6BCF;&#x4E2A; channel &#x62E5;&#x6709;&#x72EC;&#x7ACB;&#x5B8C;&#x6574;&#x7684;&#x4E00;&#x4EFD;&#x6570;&#x636E;</strong></li><li>&#x5176;&#x6B21;&#xFF0C;&#x6240;&#x6709; <strong>consumer &#x5728;&#x53D1;&#x8D77;&#x8BA2;&#x9605;</strong>&#x65F6;&#xFF0C;&#x90FD;&#x9700;&#x8981;<strong>&#x663E;&#x5F0F;&#x6307;&#x5B9A; topic + channel</strong> &#x7684;&#x4E8C;&#x7EF4;&#x4FE1;&#x606F;</li><li>&#x6700;&#x540E;&#xFF0C;channel &#x4E0B;&#x7684;&#x6BCF;&#x4E00;&#x6761;&#x6D88;&#x606F;&#x4F1A;&#x88AB;<strong>&#x968F;&#x673A;&#x63A8;&#x9001;&#x7ED9;&#x8BA2;&#x9605;&#x4E86;&#x8BE5; channel &#x7684; 1 &#x540D; consumer</strong></li></ul><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-76e2668a4cc138d9a4ddc68bdddaac0a_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x7531;&#x6B64;&#x53EF;&#x89C1;&#xFF0C;&#x6240;&#x6709; subcribe &#x4E86;<strong>&#x76F8;&#x540C; channel &#x7684; consumer &#x4E4B;&#x95F4;&#x81EA;&#x52A8;&#x5F62;&#x6210;&#x4E86;&#x4E00;&#x79CD;&#x7C7B;&#x4F3C;&#x6D88;&#x8D39;&#x8005;&#x7EC4;&#x7684;&#x673A;&#x5236;</strong>&#xFF0C;&#x5927;&#x5BB6;&#x5404;&#x81EA;&#x6D88;&#x8D39; topic &#x4E0B;&#x6570;&#x636E;&#x7684;&#x4E00;&#x90E8;&#x5206;&#xFF0C;&#x5F62;&#x6210;&#x6570;&#x636E;&#x5206;&#x6CBB;&#x4E0E;&#x8D1F;&#x8F7D;&#x5747;&#x8861;.</p><p>&#x5018;&#x82E5;&#x67D0;&#x4E2A; consumer &#x9700;&#x8981;&#x83B7;&#x53D6;&#x5230; topic &#x4E2D;&#x7684;<strong>&#x5168;&#x91CF;&#x6570;&#x636E;</strong>&#xFF0C;&#x90A3;&#x4E5F;&#x5BB9;&#x6613;&#xFF0C;&#x53EA;&#x9700;&#x8981; <strong>subscribe &#x4E00;&#x4E2A;&#x4E0D;&#x4E0E;&#x4ED6;&#x4EBA;&#x5171;&#x4EAB;&#x7684; channel</strong> &#x5373;&#x53EF;.</p><p>nsq &#x4E0E;&#x5176;&#x4ED6;&#x6D88;&#x606F;&#x961F;&#x5217;&#x7EC4;&#x4EF6;&#x7684;&#x53E6;&#x4E00;&#x5927;&#x5DEE;&#x5F02;&#x662F;&#xFF0C;&#x5176;&#x4E2D;&#x7684; topic &#x548C; channel &#x91C7;&#x7528;&#x7684;&#x90FD;&#x662F;&#x61D2;&#x521B;&#x5EFA;&#x7684;&#x673A;&#x5236;&#xFF0C;&#x4F7F;&#x7528;&#x65B9;&#x65E0;&#x9700;&#x663E;&#x5F0F;&#x6267;&#x884C; topic &#x6216;&#x8005; channel &#x7684;&#x521B;&#x5EFA;&#x64CD;&#x4F5C;&#xFF0C;<strong>channel &#x7531;&#x9996;&#x6B21;&#x9488;&#x5BF9;&#x8BE5;&#x9891;&#x9053;&#x53D1;&#x8D77; subscribe &#x8BA2;&#x9605;&#x64CD;&#x4F5C;&#x7684; consumer &#x521B;&#x5EFA;</strong>&#xFF1B;&#x800C; <strong>topic &#x5219;&#x7531;&#x9996;&#x6B21;&#x9488;&#x5BF9;&#x8BE5;&#x4E3B;&#x9898;&#x53D1;&#x8D77; publish &#x64CD;&#x4F5C;&#x7684; producer &#x6216;&#x8005; subscribe &#x64CD;&#x4F5C;&#x7684; consumer &#x521B;&#x5EFA;</strong>.</p><p>&#x5230;&#x8FD9;&#x91CC;&#xFF0C;&#x6709;&#x5173; nsq &#x7684;&#x6838;&#x5FC3;&#x6982;&#x5FF5;&#x5C31;&#x4ECB;&#x7ECD;&#x5F97;&#x5DEE;&#x4E0D;&#x591A;&#x4E86;&#xFF0C;&#x5EFA;&#x8BAE;&#x5927;&#x5BB6;&#x7565;&#x4F5C;&#x6D88;&#x5316;&#x540E;&#xFF0C;&#x53EF;&#x4EE5;&#x56DE;&#x5934;&#x770B;&#x4E00;&#x773C;&#x672C;&#x7AE0;&#x6700;&#x5F00;&#x59CB;&#x5C55;&#x793A;&#x7684;&#x6574;&#x4F53;&#x67B6;&#x6784;&#x56FE;&#xFF0C;&#x5DE9;&#x56FA;&#x4E00;&#x4E0B;&#x5BF9;&#x6982;&#x5FF5;&#x7684;&#x7406;&#x89E3;.</p><h2 id="2-%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B">2 &#x4F7F;&#x7528;&#x6559;&#x7A0B;</h2><p>&#x672C;&#x7AE0;&#x5F00;&#x59CB;&#xFF0C;&#x6211;&#x4EEC;&#x4ECB;&#x7ECD;&#x4E00;&#x4E0B; nsq &#x7684;&#x57FA;&#x672C;&#x7528;&#x6CD5;.</p><h2 id="21-%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF">2.1 &#x542F;&#x52A8;&#x670D;&#x52A1;&#x7AEF;</h2><p>&#x9996;&#x5148;&#x6211;&#x4EEC;&#x4ECB;&#x7ECD;&#xFF0C;&#x5982;&#x4F55;&#x5728;&#x4E00;&#x53F0; linux &#x670D;&#x52A1;&#x5668;&#x4E2D;&#x542F;&#x52A8; nsq &#x670D;&#x52A1;&#x7AEF;.</p><p>nsq &#x7684;&#x5B98;&#x7F51;&#x4E0B;&#x8F7D;&#x5B89;&#x88C5;&#x5305;&#x5730;&#x5740;&#x4E3A; <a href="https://link.zhihu.com/?target=https%3A//nsq.io/deployment/installing.html" rel="nofollow noreferrer">https://nsq.io/deployment/installing.html</a>&#xFF0C;&#x53EF;&#x4EE5;&#x4ECE;&#x4E2D;&#x4E0B;&#x8F7D;&#x5230;&#x5BF9;&#x5E94;&#x4E8E; linux &#x7CFB;&#x7EDF;&#x7684;&#x5B89;&#x88C5;&#x5305;&#x538B;&#x7F29;&#x6587;&#x4EF6;.</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-272511f62ab8d144af52e65e07bd67b3_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5728; linux &#x670D;&#x52A1;&#x5668;&#x4E0A;&#x89E3;&#x538B;&#x6587;&#x4EF6;&#xFF0C;&#x7136;&#x540E;&#x8FDB;&#x5165; bin &#x76EE;&#x5F55;&#x5373;&#x53EF;&#x4E00;&#x952E;&#x542F;&#x52A8; nsq &#x670D;&#x52A1;. &#x4E3A;&#x4E86;&#x907F;&#x514D;&#x56E0;&#x4E3A;&#x542F;&#x52A8;&#x670D;&#x52A1;&#x800C;&#x4F7F;&#x5F97;&#x7EC8;&#x7AEF;&#x9677;&#x5165;&#x963B;&#x585E;&#xFF0C;&#x6211;&#x4EEC;&#x901A;&#x8FC7; nohup &#x6307;&#x4EE4;&#x4EE5;&#x5B88;&#x62A4;&#x8FDB;&#x7A0B;&#x7684;&#x65B9;&#x5F0F;&#x5206;&#x522B;&#x542F;&#x52A8; nsqlookupd&#x3001;nsqd &#x548C; nsqadmin &#x8FDB;&#x7A0B;&#xFF1A;</p><ul><li>&#x542F;&#x52A8; nsqlookupd</li></ul><p>&#x811A;&#x672C;&#xFF1A;start_lookup.sh</p><pre><code class="language-text">nohup ./nsqlookupd ./nsqlookupd &amp;
exit</code></pre><ul><li>&#x542F;&#x52A8; nsqd &#xFF1A;</li></ul><p>&#x811A;&#x672C;&#xFF1A;start_nsqd.sh</p><pre><code class="language-text">nohup ./nsqd --lookupd-tcp-address=127.0.0.1:4160 &amp;
exit</code></pre><ul><li>&#x542F;&#x52A8; nsqadmin&#xFF1A;</li></ul><p>&#x811A;&#x672C;&#xFF1A;start_admin.sh</p><pre><code class="language-text">nohup ./nsqadmin --lookupd-http-address=127.0.0.1:4161 &amp;
exit</code></pre><p>&#x5728; nsqadmin &#x542F;&#x52A8;&#x540E;&#xFF0C;&#x5373;&#x53EF;&#x8FDB;&#x5165; <a href="https://link.zhihu.com/?target=http%3A//localhost%3A4171/" rel="nofollow noreferrer">http://localhost:4171</a> &#x9875;&#x9762;&#x6D4F;&#x89C8; topic&#x3001;channel &#x76F8;&#x5173;&#x4FE1;&#x606F;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-d54c51c413da4198e8fb1fe3c1a200bd_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x4E0A;&#x8FF0;&#x5404;&#x4E2A;&#x8FDB;&#x7A0B;&#x5BF9;&#x5E94;&#x7684;&#x7AEF;&#x53E3;&#x53F7;&#x5982;&#x4E0B;&#xFF1A;</p><ul><li><strong>nsqlookupd&#xFF1A;</strong>tcp &#x7AEF;&#x53E3;&#xFF1A;4160&#xFF0C;&#x7528;&#x4E8E; nsqd &#x96C6;&#x7FA4;&#x5E7F;&#x64AD;&#xFF1B;http &#x7AEF;&#x53E3;&#xFF1A;4161&#xFF0C;&#x7528;&#x4E8E;&#x5BA2;&#x6237;&#x7AEF;&#x8BBF;&#x95EE;</li><li><strong>nsqd&#xFF1A;</strong>tcp &#x7AEF;&#x53E3;: 4150&#xFF0C;&#x7528;&#x4E8E;&#x751F;&#x4EA7;&#x8005;&#x3001;&#x6D88;&#x8D39;&#x8005;&#x8BBF;&#x95EE;&#xFF1B;http &#x7AEF;&#x53E3;: 4151&#xFF0C;&#x7528;&#x4E8E;&#x751F;&#x4EA7;&#x8005;&#x8BBF;&#x95EE;</li><li><strong>nsqadmin&#xFF1A;</strong>&#x7AEF;&#x53E3;&#xFF1A;4171</li></ul><h2 id="22-%E8%BF%90%E8%A1%8C%E5%AE%A2%E6%88%B7%E7%AB%AF">2.2 &#x8FD0;&#x884C;&#x5BA2;&#x6237;&#x7AEF;</h2><p>&#x4E0B;&#x9762;&#x5C55;&#x793A;&#x4E00;&#x4E0B;&#xFF0C;nsq &#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x793A;&#x4F8B;&#x4EE3;&#x7801;&#xFF0C;&#x5176;&#x4E2D;&#x5305;&#x62EC;&#x5BF9; consumer &#x548C; producer &#x7684;&#x8FD0;&#x884C;&#x542F;&#x52A8;&#x5B9E;&#x4F8B;. &#x5177;&#x4F53;&#x4EE3;&#x7801;&#x4EE5;&#x53CA;&#x6CE8;&#x91CA;&#x5C55;&#x793A;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">package main


import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;testing&quot;
    &quot;time&quot;


    &quot;github.com/nsqio/go-nsq&quot;
)


const (
    // &#x7528;&#x4E8E;&#x6D4B;&#x8BD5;&#x7684;&#x6D88;&#x606F;&#x4E3B;&#x9898;
    testTopic = &quot;my_test_topic&quot;
    // nsqd &#x670D;&#x52A1;&#x7AEF;&#x5730;&#x5740;
    nsqdAddr  = &quot;localhost:4150&quot;
    // &#x8BA2;&#x9605; channelGroupA &#x7684;&#x6D88;&#x8D39;&#x8005; A1
    consumerA1 = &quot;consumer_a1&quot;
    // &#x8BA2;&#x9605; channelGroupA &#x7684;&#x6D88;&#x8D39;&#x8005; A2
    consumerA2 = &quot;consumer_a2&quot;
    // &#x5355;&#x72EC;&#x8BA2;&#x9605; channelGroupB &#x7684;&#x6D88;&#x8D39;&#x8005; B
    consumerB  = &quot;consumer_b&quot;
    // testTopic &#x4E0B;&#x7684; channelA
    channelGroupA = &quot;channel_a&quot;
    // testTopic &#x4E0B;&#x7684; channelB
    channelGroupB = &quot;channel_b&quot;
)


// &#x5EFA;&#x7ACB; consumer &#x4E0E; channel &#x4E4B;&#x95F4;&#x7684;&#x6620;&#x5C04;&#x5173;&#x7CFB;
// consumerA1&#x3001;consumerA2 -&gt; channelA
// consumerB -&gt; channelB
var consumerToChannelGroup = map[string]string{
    consumerA1: channelGroupA,
    consumerA2: channelGroupA,
    consumerB:  channelGroupB,
}


func Test_nsq(t *testing.T) {
    // &#x6D88;&#x8D39;&#x8005;&#x6D88;&#x8D39;&#x5230;&#x6D88;&#x606F;&#x540E;&#x7684;&#x6267;&#x884C;&#x903B;&#x8F91;
    msgCallback := func(consumerName string, msg []byte) error {
        t.Logf(&quot;i am %s, receive msg: %s&quot;, consumerName, msg)
        return nil
    }


    // &#x8FD0;&#x884C; producer
    if err := runProducer(); err != nil {
        t.Error(err)
        return
    }


    // &#x5E76;&#x53D1;&#x8FD0;&#x884C;&#x4E09;&#x4E2A; consumer
    var wg sync.WaitGroup
    for consumer := range consumerToChannelGroup {
        // shadow
        wg.Add(1)
        go func(consumer string) {
            defer wg.Done()
            if err := runConsumer(consumer, msgCallback); err != nil {
                t.Error(err)
            }
        }(consumer)




    }
    wg.Wait()
}


// &#x8FD0;&#x884C;&#x751F;&#x4EA7;&#x8005;
func runProducer() error {
    // &#x901A;&#x8FC7; addr &#x76F4;&#x8FDE; nsqd &#x670D;&#x52A1;&#x7AEF;
    producer, err := nsq.NewProducer(nsqdAddr, nsq.NewConfig())
    if err != nil {
        return err
    }
    defer producer.Stop()


    // &#x901A;&#x8FC7; producer.Publish &#x65B9;&#x6CD5;&#xFF0C;&#x5F80; testTopic &#x4E2D;&#x53D1;&#x9001;&#x4E09;&#x6761;&#x6D88;&#x606F;
    for i := 0; i &lt; 3; i++ {
        msg := fmt.Sprintf(&quot;hello xiaoxu %d&quot;, i)
        if err := producer.Publish(testTopic, []byte(msg)); err != nil {
            return err
        }
    }
    return nil 
}


// &#x7528;&#x4E8E;&#x5904;&#x7406;&#x6D88;&#x606F;&#x7684; processor&#xFF0C;&#x9700;&#x8981;&#x5B9E;&#x73B0; go-nsq &#x4E2D;&#x5B9A;&#x4E49;&#x7684; msgProcessor interface&#xFF0C;&#x6838;&#x5FC3;&#x662F;&#x5B9E;&#x73B0;&#x6D88;&#x606F;&#x56DE;&#x8C03;&#x5904;&#x7406;&#x65B9;&#x6CD5;&#xFF1A; func HandleMessage(msg *nsq.Message) error
type msgProcessor struct {
    // &#x6D88;&#x8D39;&#x8005;&#x540D;&#x79F0;
    consumerName string
    // &#x6D88;&#x606F;&#x56DE;&#x8C03;&#x5904;&#x7406;&#x51FD;&#x6570;
    callback     func(consumerName string, msg []byte) error
}


func newMsgProcessor(consumerName string, callback func(consumerName string, msg []byte) error) *msgProcessor {
    return &amp;msgProcessor{
        consumerName: consumerName,
        callback:     callback,
    }
}


// &#x6D88;&#x606F;&#x56DE;&#x8C03;&#x5904;&#x7406;
func (m *msgProcessor) HandleMessage(msg *nsq.Message) error {
    // &#x6267;&#x884C;&#x7528;&#x6237;&#x5B9A;&#x4E49;&#x7684;&#x4E1A;&#x52A1;&#x5904;&#x7406;&#x903B;&#x8F91;
    if err := m.callback(m.consumerName, msg.Body); err != nil {
        return err
    }
    // &#x5018;&#x82E5;&#x4E1A;&#x52A1;&#x5904;&#x7406;&#x6210;&#x529F;&#xFF0C;&#x5219;&#x8C03;&#x7528; Finish &#x65B9;&#x6CD5;&#xFF0C;&#x53D1;&#x9001;&#x6D88;&#x606F;&#x7684; ack
    msg.Finish()
    return nil
}


// &#x8FD0;&#x884C;&#x6D88;&#x8D39;&#x8005;
func runConsumer(consumerName string, callback func(consumerName string, msg []byte) error) error {
    // &#x6839;&#x636E;&#x6D88;&#x8D39;&#x8005;&#x540D;&#x83B7;&#x53D6;&#x5230;&#x5BF9;&#x5E94;&#x7684; channel
    channel, ok := consumerToChannelGroup[consumerName]
    if !ok {
        return fmt.Errorf(&quot;bad name: %s&quot;, consumerName)
    }


    // &#x6307;&#x5B9A; topic &#x548C; channel&#xFF0C;&#x521B;&#x5EFA; consumer &#x5B9E;&#x4F8B;
    consumer, err := nsq.NewConsumer(testTopic, channel, nsq.NewConfig())
    if err != nil {
        return err
    }
    defer consumer.Stop()


    // &#x6DFB;&#x52A0;&#x6D88;&#x606F;&#x56DE;&#x8C03;&#x5904;&#x7406;&#x51FD;&#x6570;
    consumer.AddHandler(newMsgProcessor(consumerName, callback))
    
    // consumer &#x8FDE;&#x63A5;&#x5230; nsqd &#x670D;&#x52A1;&#x7AEF;&#xFF0C;&#x5F00;&#x542F;&#x6D88;&#x8D39;&#x6D41;&#x7A0B;
    if err = consumer.ConnectToNSQD(nsqdAddr); err != nil {
        return err
    }


    &lt;-time.After(5 * time.Second)
}</code></pre><p>&#x6309;&#x7167;&#x4E0A;&#x8FF0;&#x6D41;&#x7A0B;&#x8FD0;&#x884C;&#x5355;&#x6D4B;&#x4EE3;&#x7801;&#x540E;&#xFF0C;&#x5BF9;&#x5E94;&#x7684;&#x8F93;&#x51FA;&#x7ED3;&#x679C;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">nsq_test.go:32: i am consumer_a1, receive msg: hello xiaoxu 0
    nsq_test.go:32: i am consumer_b, receive msg: hello xiaoxu 0
    nsq_test.go:32: i am consumer_a2, receive msg: hello xiaoxu 1
    nsq_test.go:32: i am consumer_b, receive msg: hello xiaoxu 1
    nsq_test.go:32: i am consumer_a1, receive msg: hello xiaoxu 2
    nsq_test.go:32: i am consumer_b, receive msg: hello xiaoxu 2</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;&#x5171;&#x4EAB;&#x4E86; channelA &#x7684;&#x4E24;&#x4E2A; consumerA1&#x3001;consumerA2 &#x5206;&#x644A;&#x4E86; topic &#x4E0B;&#x7684;&#x6D88;&#x606F;&#x6570;&#x636E;&#xFF1B;&#x800C;&#x72EC;&#x4EAB; channelB &#x7684; consumer &#x5219;&#x6D88;&#x8D39;&#x5230;&#x4E86; topic &#x4E0B;&#x7684;&#x5168;&#x91CF;&#x6D88;&#x606F;.</p><h2 id="3-%E5%AE%A2%E6%88%B7%E7%AB%AF">3 &#x5BA2;&#x6237;&#x7AEF;</h2><p>&#x672C;&#x7AE0;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x5E26;&#x7740;&#x5927;&#x5BB6;&#x6DF1;&#x5165;&#x5230; nsq &#x5BA2;&#x6237;&#x7AEF;&#x9879;&#x76EE;&#x4E2D;&#xFF0C;&#x68B3;&#x7406;&#x751F;&#x4EA7;&#x8005;&#x4E0E;&#x6D88;&#x8D39;&#x8005;&#x7684;&#x8FD0;&#x884C;&#x6D41;&#x7A0B;.</p><p>nsq &#x5BA2;&#x6237;&#x7AEF; lib &#x5E93;&#x5F00;&#x6E90;&#x5730;&#x5740;&#x4E3A;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//github.com/nsqio/go-nsq" rel="nofollow noreferrer">https://github.com/nsqio/go-nsq</a>&#xFF0C;&#x672C;&#x6587;<strong>&#x8D70;&#x8BFB;&#x6E90;&#x7801;&#x7248;&#x672C;&#x4E3A; v1.1.0</strong></p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-f3974d3fa987f4d341d697eeb606adfd_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="31-%E8%BF%9E%E6%8E%A5%E4%BA%A4%E4%BA%92">3.1 &#x8FDE;&#x63A5;&#x4EA4;&#x4E92;</h2><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-026031d941859b2597553c2a34789abb_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5728; nsq &#x5BA2;&#x6237;&#x7AEF;&#x90E8;&#x5206;&#xFF0C;&#x65E0;&#x8BBA;&#x662F;&#x751F;&#x4EA7;&#x8005; producer &#x8FD8;&#x662F;&#x6D88;&#x8D39;&#x8005; consumer&#xFF0C;&#x5728;<strong>&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x4EA4;&#x4E92;&#x65F6;</strong>&#xFF0C;&#x90FD;&#x662F;<strong>&#x901A;&#x8FC7;&#x5BA2;&#x6237;&#x7AEF;&#x5B9A;&#x4E49;&#x7C7B; Conn &#x6765;&#x5C01;&#x88C5;&#x8868;&#x793A;&#x4E24;&#x7AEF;&#x4E4B;&#x95F4;&#x5EFA;&#x7ACB;&#x7684;&#x8FDE;&#x63A5;</strong>.</p><h3 id="311-%E7%B1%BB%E5%AE%9A%E4%B9%89">3.1.1 &#x7C7B;&#x5B9A;&#x4E49;</h3><p>&#x5BA2;&#x6237;&#x7AEF;&#x5B9A;&#x4E49;&#x7684;&#x8FDE;&#x63A5;&#x7C7B; Conn &#x5B9A;&#x4E49;&#x5982;&#x4E0B;&#xFF0C;&#x5176;&#x4E2D;&#x6D89;&#x53CA;&#x5230;&#x7684;&#x6838;&#x5FC3;&#x5B57;&#x6BB5;&#xFF0C;&#x6211;&#x90FD;&#x8865;&#x5145;&#x4E86;&#x76F8;&#x5E94;&#x7684;&#x6CE8;&#x91CA;.</p><p>&#x8FD9;&#x91CC;&#x7A0D;&#x5FAE;&#x89E3;&#x91CA;&#x4E0B;<strong> inFlight </strong>&#x7684;&#x6982;&#x5FF5;&#xFF0C;&#x5176;&#x6307;&#x7684;&#x662F;<strong>&#x67D0;&#x6761;&#x6D88;&#x606F;&#x5DF2;&#x7ECF;&#x88AB;&#x5BA2;&#x6237;&#x7AEF;&#x63A5;&#x6536;&#x5230;&#xFF0C;&#x4F46;&#x662F;&#x8FD8;&#x672A;&#x7ED9;&#x4E88;&#x670D;&#x52A1;&#x7AEF; ack &#x7684;&#x72B6;&#x6001;.</strong></p><pre><code class="language-text">type Conn struct {
    // &#x8BB0;&#x5F55;&#x4E86;&#x6709;&#x591A;&#x5C11;&#x6D88;&#x606F;&#x5904;&#x4E8E;&#x672A; ack &#x72B6;&#x6001;
    messagesInFlight int64
    // ...


    // &#x4E92;&#x65A5;&#x9501;&#xFF0C;&#x4FDD;&#x8BC1;&#x4E34;&#x754C;&#x8D44;&#x6E90;&#x4E00;&#x81F4;&#x6027;
    mtx sync.Mutex
    // ...


    // &#x771F;&#x6B63;&#x7684; tcp &#x8FDE;&#x63A5;
    conn    *net.TCPConn
    // ...
    // &#x8FDE;&#x63A5;&#x7684;&#x670D;&#x52A1;&#x7AEF;&#x5730;&#x5740;
    addr    string
    // ...
    
    // &#x8BFB;&#x5165;&#x53E3;
    r io.Reader
    // &#x5199;&#x51FA;&#x53E3;
    w io.Writer
    // writeLoop goroutine &#x7528;&#x4E8E;&#x63A5;&#x6536;&#x7528;&#x6237;&#x6307;&#x4EE4;&#x7684; channel
    cmdChan         chan *Command
    // write goroutine &#x901A;&#x8FC7;&#x6B64; channel &#x63A5;&#x6536;&#x6765;&#x81EA;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x54CD;&#x5E94;&#xFF0C;&#x53D1;&#x5F80;&#x670D;&#x52A1;&#x7AEF;
    msgResponseChan chan *msgResponse
    // &#x63A7;&#x5236; write goroutine &#x9000;&#x51FA;&#x7684; channel
    exitChan        chan int
    // &#x5E76;&#x53D1;&#x7B49;&#x5F85;&#x7EC4;&#xFF0C;&#x4FDD;&#x8BC1;&#x6240;&#x6709; goroutine &#x53CA;&#x65F6;&#x56DE;&#x6536;&#xFF0C;conn &#x624D;&#x80FD;&#x5173;&#x95ED;
    wg        sync.WaitGroup
    // ...
}</code></pre><h3 id="312-%E5%88%9B%E5%BB%BA%E8%BF%9E%E6%8E%A5">3.1.2 &#x521B;&#x5EFA;&#x8FDE;&#x63A5;</h3><p>&#x7531;&#x5BA2;&#x6237;&#x7AEF;&#x5B9E;&#x9645;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x8D77;&#x4E00;&#x7B14;&#x8FDE;&#x63A5;&#xFF0C;&#x5BF9;&#x5E94;&#x7684;&#x65B9;&#x6CD5;&#x662F; Conn.Connect()&#xFF0C;&#x5176;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x5305;&#x62EC;&#xFF1A;</p><ul><li>&#x901A;&#x8FC7; net &#x5305;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x8D77; tcp &#x8FDE;&#x63A5;</li><li>&#x5C06; Conn &#x4E0B;&#x7684; writer &#x548C; reader &#x8BBE;&#x7F6E;&#x4E3A;&#x8FD9;&#x7B14; tcp &#x8FDE;&#x63A5;</li><li><strong>&#x5F02;&#x6B65;&#x542F;&#x52A8; Conn &#x4F34;&#x751F;&#x7684; readLoop &#x548C; writeLoop goroutine</strong>&#xFF0C;&#x6301;&#x7EED;&#x8D1F;&#x8D23;&#x63A5;&#x6536;&#x548C;&#x53D1;&#x9001;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x4E4B;&#x95F4;&#x7684;&#x5F80;&#x6765;&#x6570;&#x636E;</li></ul><pre><code class="language-text">func (c *Conn) Connect() (*IdentifyResponse, error) {
    dialer := &amp;net.Dialer{
        LocalAddr: c.config.LocalAddr,
        Timeout:   c.config.DialTimeout,
    }




    conn, err := dialer.Dial(&quot;tcp&quot;, c.addr)
    // ...
    c.conn = conn.(*net.TCPConn)
    c.r = conn
    c.w = conn
    // var MagicV2 = []byte(&quot;  V2&quot;)
    _, err = c.Write(MagicV2)
    // ...
    c.wg.Add(2)
    // ...
    // &#x63A5;&#x6536;&#x6765;&#x81EA;&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x54CD;&#x5E94;
    go c.readLoop()
    // &#x53D1;&#x9001;&#x53D1;&#x5F80;&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x8BF7;&#x6C42;
    go c.writeLoop()
    return resp, nil
}</code></pre><p>&#x6709;&#x5173; readLoop &#x548C; writeLoop &#x7684;&#x8BBE;&#x8BA1;&#xFF0C;&#x5176;&#x6838;&#x5FC3;&#x4F18;&#x52BF;&#x5305;&#x62EC;&#xFF1A;</p><ul><li><strong>&#x89E3;&#x8026;&#x53D1;&#x9001;&#x8BF7;&#x6C42;&#x4E0E;&#x63A5;&#x6536;&#x54CD;&#x5E94;</strong>&#x7684;&#x4E32;&#x884C;&#x6D41;&#x7A0B;&#xFF0C;&#x80FD;&#x591F;&#x5B9E;&#x73B0;&#x66F4;&#x52A0;&#x81EA;&#x7531;&#x7684;<strong>&#x53CC;&#x5DE5;&#x901A;&#x4FE1;</strong></li><li>&#x5145;&#x5206;&#x5229;&#x7528; goroutine &#x548C; channel &#x7684;&#x4F18;&#x52BF;&#xFF0C;&#x901A;&#x8FC7; <strong>for &#x81EA;&#x65CB; + select &#x591A;&#x8DEF;&#x590D;&#x7528;</strong>&#x7684;&#x65B9;&#x5F0F;&#xFF0C;&#x4FDD;&#x8BC1;&#x4E24;&#x4E2A; <strong>loop goroutinie &#x80FD;&#x591F;&#x5728;&#x76D1;&#x542C;&#x5230;&#x9000;&#x51FA;&#x6307;&#x4EE4;&#x65F6;&#x7194;&#x65AD;&#x6D41;&#x7A0B;</strong>&#xFF0C;&#x6BD4;&#x5982; <strong>context &#x7684; cancel&#x3001;timeout &#x4E8B;&#x4EF6;</strong>&#xFF0C;&#x6BD4;&#x5982; exitChan &#x7684;&#x5173;&#x95ED;&#x4E8B;&#x4EF6;&#x7B49;</li></ul><p>&#x8FD9;&#x79CD;&#x8BFB;&#x5199; loop &#x6A21;&#x5F0F;&#x5728;&#x5F88;&#x591A; go &#x8BED;&#x8A00;&#x5E95;&#x5C42;&#x901A;&#x4FE1;&#x6846;&#x67B6;&#x4E2D;&#x90FD;&#x6709;&#x91C7;&#x7528;&#xFF0C;&#x6BD4;&#x8F83;&#x7ECF;&#x5178;&#x7684;&#x6848;&#x4F8B;&#x5305;&#x62EC; go &#x8BED;&#x8A00;&#x4E2D;&#x7684; net/http &#x6807;&#x51C6;&#x5E93;&#xFF0C;&#x5927;&#x5BB6;&#x5982;&#x679C;&#x611F;&#x5174;&#x8DA3;&#x53EF;&#x4EE5;&#x9605;&#x8BFB;&#x6211;&#x4E4B;&#x524D;&#x53D1;&#x8868;&#x7684;&#x8FD9;&#x7BC7;&#x6587;&#x7AE0;&#x2014;&#x2014;Golang HTTP &#x6807;&#x51C6;&#x5E93;&#x5B9E;&#x73B0;&#x539F;&#x7406;.</p><p>&#x6709;&#x5173; Conn &#x4E2D;&#x7684; readLoop&#x3001;writeLoop &#x90E8;&#x5206;&#x5185;&#x5BB9;&#xFF0C;&#x5728;&#x672C;&#x6587; 3.2&#x3001;3.3 &#x5C0F;&#x8282;&#x4ECB;&#x7ECD;&#x751F;&#x4EA7;&#x8005; producer &#x548C; &#x6D88;&#x8D39;&#x8005; consumer &#x6A21;&#x5757;&#x65F6;&#xFF0C;&#x4F1A;&#x7565;&#x4F5C;&#x5C55;&#x5F00;.</p><h2 id="32-%E7%94%9F%E4%BA%A7%E8%80%85">3.2 &#x751F;&#x4EA7;&#x8005;</h2><p>&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x6765;&#x4ECB;&#x7ECD;&#x4E00;&#x4E0B;&#xFF0C;&#x5728;&#x5BA2;&#x6237;&#x7AEF;&#x89C6;&#x89D2;&#x4E0B;&#xFF0C;&#x751F;&#x4EA7;&#x8005; producer &#x5411;&#x670D;&#x52A1;&#x7AEF;&#x751F;&#x4EA7;&#x6D88;&#x606F;&#x7684; publish &#x6D41;&#x7A0B;.</p><h3 id="321-%E7%B1%BB%E5%AE%9A%E4%B9%89">3.2.1 &#x7C7B;&#x5B9A;&#x4E49;</h3><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-5fd7b5dfe1216169e85eacecfe368f42_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x751F;&#x4EA7;&#x8005; producer &#x7C7B;&#x5B9A;&#x4E49;&#x5982;&#x4E0B;&#xFF0C;&#x6838;&#x5FC3;&#x5B57;&#x6BB5;&#x5747;&#x5DF2;&#x7ED9;&#x51FA;&#x76F8;&#x5E94;&#x6CE8;&#x91CA;.</p><p>&#x503C;&#x5F97;&#x4E00;&#x63D0;&#x7684;&#x662F;&#xFF0C;producer &#x5728;<strong>&#x521B;&#x5EFA;&#x597D;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x4EA4;&#x4E92;&#x7684;&#x8FDE;&#x63A5; Conn</strong> &#x540E;&#xFF0C;&#x4E5F;&#x4F1A;<strong>&#x542F;&#x52A8;&#x4E00;&#x4E2A;&#x5E38;&#x9A7B;&#x7684; router goroutine</strong>&#xFF0C;&#x8D1F;&#x8D23;<strong>&#x6301;&#x7EED;&#x63A5;&#x6536;&#x6765;&#x81EA;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x6307;&#x4EE4;</strong>&#xFF0C;&#x5E76;<strong>&#x590D;&#x7528; Conn &#x5C06;&#x6307;&#x4EE4;&#x53D1;&#x9001;&#x5230;&#x670D;&#x52A1;&#x7AEF;</strong>.</p><pre><code class="language-text">// &#x751F;&#x4EA7;&#x8005;
type Producer struct {
    // &#x751F;&#x4EA7;&#x8005;&#x6807;&#x8BC6; id
    id     int64
    // &#x8FDE;&#x63A5;&#x7684; nsqd &#x670D;&#x52A1;&#x5668;&#x5730;&#x5740;
    addr   string
    // &#x5185;&#x7F6E;&#x7684;&#x5BA2;&#x6237;&#x7AEF;&#x8FDE;&#x63A5;&#xFF0C;&#x5176;&#x5B9E;&#x73B0;&#x7C7B;&#x662F; 3.1 &#x5C0F;&#x8282;&#x4E2D;&#x7684; Conn. &#x6B21;&#x6570;&#x58F0;&#x660E;&#x4E3A; producerConn interface&#xFF0C;&#x662F;&#x4E3A; producer &#x5C4F;&#x853D;&#x4E86;&#x4E00;&#x4E9B;&#x751F;&#x4EA7;&#x8005;&#x65E0;&#x9700;&#x611F;&#x77E5;&#x7684;&#x7EC6;&#x8282;
    conn   producerConn
    // ...
    // &#x751F;&#x4EA7;&#x8005; router goroutine &#x63A5;&#x6536;&#x670D;&#x52A1;&#x7AEF;&#x54CD;&#x5E94;&#x7684; channel 
    responseChan chan []byte
    // &#x751F;&#x4EA7;&#x8005; router goroutine &#x63A5;&#x6536;&#x9519;&#x8BEF;&#x7684; channel
    errorChan    chan []byte
    // &#x751F;&#x4EA7;&#x8005; router goroutine &#x63A5;&#x6536;&#x751F;&#x4EA7;&#x8005;&#x5173;&#x95ED;&#x4FE1;&#x53F7;&#x7684; channel
    closeChan    chan int
    // &#x751F;&#x4EA7;&#x8005; router goroutine &#x63A5;&#x6536; publish &#x6307;&#x4EE4;&#x7684; channel
    transactionChan chan *ProducerTransaction
    // ...
    // &#x751F;&#x4EA7;&#x8005;&#x7684;&#x72B6;&#x6001;
    state           int32
    // &#x5F53;&#x524D;&#x6709;&#x591A;&#x5C11; publish &#x6307;&#x4EE4;&#x5E76;&#x53D1;&#x6267;&#x884C;
    concurrentProducers int32
    // &#x751F;&#x4EA7;&#x8005; router goroutine &#x63A5;&#x6536;&#x9000;&#x51FA;&#x4FE1;&#x53F7;&#x7684; channel
    exitChan            chan int
    // &#x5E76;&#x53D1;&#x7B49;&#x5F85;&#x7EC4;&#xFF0C;&#x4FDD;&#x8BC1; producer &#x5173;&#x95ED;&#x524D;&#x53CA;&#x65F6;&#x56DE;&#x6536;&#x6240;&#x6709; goroutine
    wg                  sync.WaitGroup
    // &#x4E92;&#x65A5;&#x9501;
    guard               sync.Mutex
}</code></pre><h3 id="322-publish-%E6%8C%87%E4%BB%A4">3.2.2 publish &#x6307;&#x4EE4;</h3><p>&#x751F;&#x4EA7;&#x8005; producer &#x751F;&#x4EA7;&#x6D88;&#x606F;&#x7684;&#x5165;&#x53E3;&#x65B9;&#x6CD5;&#x4E3A; Producer.Publish()&#xFF0C;&#x5E95;&#x5C42;&#x4F1A;&#x7EC4;&#x88C5;&#x51FA;&#x4E00;&#x4E2A; PUB &#x6307;&#x4EE4;&#xFF0C;&#x5E76;&#x8C03;&#x7528; Producer.sendCommand() &#x65B9;&#x6CD5;&#x53D1;&#x9001;&#x6307;&#x4EE4;.</p><pre><code class="language-text">// Publish synchronously publishes a message body to the specified topic, returning
// an error if publish failed
func (w *Producer) Publish(topic string, body []byte) error {
    return w.sendCommand(Publish(topic, body))
}</code></pre><p>PUB &#x6307;&#x4EE4;&#xFF1A;</p><pre><code class="language-text">// Publish creates a new Command to write a message to a given topic
func Publish(topic string, body []byte) *Command {
    var params = [][]byte{[]byte(topic)}
    return &amp;Command{[]byte(&quot;PUB&quot;), params, body}
}</code></pre><h3 id="323-%E5%8F%91%E9%80%81%E6%8C%87%E4%BB%A4">3.2.3 &#x53D1;&#x9001;&#x6307;&#x4EE4;</h3><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-7cc3000b88b9ee82398cbfab33b0da6f_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>producer &#x53D1;&#x9001;&#x6307;&#x4EE4;&#x7684;&#x4E3B;&#x6D41;&#x7A0B;&#x5982;&#x4E0A;&#x56FE;&#x6240;&#x793A;&#xFF0C;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x5305;&#x62EC;&#xFF1A;</p><ul><li>&#x9996;&#x6B21;&#x53D1;&#x9001;&#x6307;&#x4EE4;&#x65F6;&#xFF0C;&#x9700;&#x8981;&#x8C03;&#x7528; Producer.connect() &#x65B9;&#x6CD5;&#x521B;&#x5EFA;&#x4E00;&#x7B14;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x901A;&#x4FE1;&#x7684; Conn</li><li>&#x901A;&#x8FC7; Producer.transactionChan &#x901A;&#x9053;&#xFF0C;&#x5C06;&#x6307;&#x4EE4;&#x53D1;&#x9001;&#x5230; Producer &#x7684;&#x5B88;&#x62A4;&#x534F;&#x7A0B; router goroutine &#x5F53;&#x4E2D;</li><li>router goroutine &#x63A5;&#x6536;&#x5230;&#x6307;&#x4EE4;&#x540E;&#xFF0C;&#x4F1A;&#x8C03;&#x7528; Conn.WriteCommand() &#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x6307;&#x4EE4;&#x53D1;&#x653E;&#x670D;&#x52A1;&#x7AEF;</li></ul><pre><code class="language-text">func (w *Producer) sendCommand(cmd *Command) error {
    doneChan := make(chan *ProducerTransaction)
    err := w.sendCommandAsync(cmd, doneChan, nil)
    // ...
    t := &lt;-doneChan
    return t.Error
}
func (w *Producer) sendCommandAsync(cmd *Command, doneChan chan *ProducerTransaction, args []interface{}) error {
    // keep track of how many outstanding producers we&apos;re dealing with
    // in order to later ensure that we clean them all up...
    atomic.AddInt32(&amp;w.concurrentProducers, 1)
    defer atomic.AddInt32(&amp;w.concurrentProducers, -1)


    if atomic.LoadInt32(&amp;w.state) != StateConnected {
        err := w.connect()
        // ...
    }


    t := &amp;ProducerTransaction{
        cmd:      cmd,
        doneChan: doneChan,
        Args:     args,
    }


    select {
    case w.transactionChan &lt;- t:
    case &lt;-w.exitChan:
        return ErrStopped
    }


    return nil
}</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;&#x5728; Producer.connect() &#x65B9;&#x6CD5;&#x4E2D;&#xFF1A;</p><ul><li>&#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A; Conn &#x5B9E;&#x4F8B;</li><li><strong>&#x8C03;&#x7528; Conn.Connect() &#x65B9;&#x6CD5;</strong>&#x5B9E;&#x9645;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x8D77;&#x8FDE;&#x63A5;&#xFF08;&#x8FD9;&#x4E2A;&#x8FC7;&#x7A0B;&#x4E2D;&#x4E5F;&#x4F1A;&#x5B8C;&#x6210; readLoop &#x548C; writeLoop goroutine &#x7684;&#x542F;&#x52A8;&#xFF09;</li><li><strong>&#x5F02;&#x6B65;&#x542F;&#x52A8;&#x4E86; router goroutine&#xFF0C;&#x8D1F;&#x8D23;&#x6301;&#x7EED;&#x63A5;&#x6536;&#x6307;&#x4EE4;&#xFF0C;&#x5E76;&#x901A;&#x8FC7; Conn &#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x4EA4;&#x4E92;</strong></li></ul><pre><code class="language-text">func (w *Producer) connect() error {
    w.guard.Lock()
    defer w.guard.Unlock()


    // ...
    w.conn = NewConn(w.addr, &amp;w.config, &amp;producerConnDelegate{w})
    // ...
    // producer &#x521B;&#x5EFA;&#x548C; nsqd &#x4E4B;&#x95F4;&#x7684;&#x8FDE;&#x63A5;
    _, err := w.conn.Connect()
    // ...
    atomic.StoreInt32(&amp;w.state, StateConnected)
    w.closeChan = make(chan int)
    w.wg.Add(1)
    go w.router()


    return nil
}</code></pre><p>router goroutine &#x7684;&#x8FD0;&#x884C;&#x6846;&#x67B6;&#x5982;&#x4E0B;&#xFF0C;&#x4E3B;&#x8981;<strong>&#x901A;&#x8FC7; for + select &#x7684;&#x5F62;&#x5F0F;&#xFF0C;&#x6301;&#x7EED;&#x63A5;&#x6536;&#x6765;&#x81EA; Producer.transactionChan &#x901A;&#x9053;&#x7684;&#x6307;&#x4EE4;</strong>&#xFF0C;&#x5C06;&#x5176;&#x53D1;&#x5F80;&#x670D;&#x52A1;&#x7AEF;.</p><pre><code class="language-text">func (w *Producer) router() {
    for {
        select {
        case t := &lt;-w.transactionChan:
            w.transactions = append(w.transactions, t)
            err := w.conn.WriteCommand(t.cmd)
            // ...
        // ...
        case &lt;-w.closeChan:
            goto exit
        case &lt;-w.exitChan:
            goto exit
        }
    }


// ...
}</code></pre><h3 id="324-%E6%8E%A5%E6%94%B6%E5%93%8D%E5%BA%94">3.2.4 &#x63A5;&#x6536;&#x54CD;&#x5E94;</h3><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-36884831b216db4b03ef4b18d5b3d3f8_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x6765;&#x7406;&#x4E00;&#x4E0B;&#xFF0C;producer &#x5728;&#x53D1;&#x9001;&#x5B8C; PUB &#x6307;&#x4EE4;&#x540E;&#xFF0C;&#x53C8;&#x8981;&#x5982;&#x4F55;&#x63A5;&#x6536;&#x5230;&#x6765;&#x81EA;&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x54CD;&#x5E94;. &#x5927;&#x5BB6;&#x53EF;&#x4EE5;&#x7ED3;&#x5408;&#x4E0A;&#x9762;&#x8FD9;&#x5F20;&#x6D41;&#x7A0B;&#x56FE;&#xFF0C;&#x548C;&#x6211;&#x4EEC;&#x6DF1;&#x5165;&#x5230;&#x4E0B;&#x9762;&#x7684;&#x6E90;&#x7801;&#x8D70;&#x8BFB;&#x73AF;&#x8282;&#xFF1A;</p><p><strong>&#x6B65;&#x9AA4; I</strong>&#xFF1A;&#x5728; Conn.readLoop() &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x8BFB;&#x53D6;&#x5230;&#x6765;&#x81EA;&#x670D;&#x52A1;&#x7AEF;&#x7684;&#x54CD;&#x5E94;&#xFF0C;&#x901A;&#x8FC7;&#x8C03;&#x7528; Producer.onConnResponse() &#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x6570;&#x636E;&#x53D1;&#x9001;&#x5230; Producer.responseChan &#x5F53;&#x4E2D;</p><pre><code class="language-text">func (c *Conn) readLoop() {
    delegate := &amp;connMessageDelegate{c}
    for {
        // ...


        frameType, data, err := ReadUnpackedResponse(c, c.config.MaxMsgSize)
        // ...


        switch frameType {
        case FrameTypeResponse:
            c.delegate.OnResponse(c, data)
        // ...
        }
    }
    // ...
}
func (d *producerConnDelegate) OnResponse(c *Conn, data []byte)       { d.w.onConnResponse(c, data) }
func (w *Producer) onConnResponse(c *Conn, data []byte) { w.responseChan &lt;- data }</code></pre><p><strong>&#x6B65;&#x9AA4;II&#xFF1A;</strong>Producer &#x7684; router goroutine &#x901A;&#x8FC7; Producer.responseChan &#x63A5;&#x6536;&#x5230;&#x54CD;&#x5E94;&#x6570;&#x636E;&#xFF0C;&#x901A;&#x8FC7;&#x8C03;&#x7528; Producer.popTransaction(...) &#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x54CD;&#x5E94;&#x63A8;&#x9001;&#x5230; doneChan &#x5F53;&#x4E2D;</p><pre><code class="language-text">func (w *Producer) router() {
    for {
        select {
        // ...
        case data := &lt;-w.responseChan:
            w.popTransaction(FrameTypeResponse, data)
        case data := &lt;-w.errorChan:
            w.popTransaction(FrameTypeError, data)
        // ...
    }


    // ...
}
func (w *Producer) popTransaction(frameType int32, data []byte) {
    // ...
    t := w.transactions[0]
    // ...
    t.finish()
}
func (t *ProducerTransaction) finish() {
    if t.doneChan != nil {
        t.doneChan &lt;- t
    }
}</code></pre><p><strong>&#x6B65;&#x9AA4;III&#xFF1A;</strong>&#x5BA2;&#x6237;&#x7AEF;&#x901A;&#x8FC7;&#x5728; Producer.sendCommand &#x65B9;&#x6CD5;&#x4E2D;&#x963B;&#x585E;&#x7B49;&#x5F85;&#x6765;&#x81EA; doneChan &#x7684;&#x6570;&#x636E;&#xFF0C;&#x63A5;&#x6536;&#x5230;&#x540E;&#x5C06;&#x5176;&#x4E2D;&#x7684;&#x9519;&#x8BEF;&#x8FD4;&#x56DE;&#x7ED9;&#x4E0A;&#x5C42;.</p><pre><code class="language-text">func (w *Producer) sendCommand(cmd *Command) error {
    doneChan := make(chan *ProducerTransaction)
    err := w.sendCommandAsync(cmd, doneChan, nil)
    // ...
    t := &lt;-doneChan
    return t.Error
}</code></pre><h2 id="33-%E6%B6%88%E8%B4%B9%E8%80%85">3.3 &#x6D88;&#x8D39;&#x8005;</h2><p>&#x63A5;&#x4E0B;&#x6765;&#x68B3;&#x7406;&#x4E00;&#x4E0B;&#xFF0C;&#x6D88;&#x8D39;&#x8005; consumer &#x8BA2;&#x9605;&#x3001;&#x6D88;&#x8D39;&#x4EE5;&#x53CA; ack &#x7684;&#x6D41;&#x7A0B;.</p><h3 id="331-%E7%B1%BB%E5%AE%9A%E4%B9%89">3.3.1 &#x7C7B;&#x5B9A;&#x4E49;</h3><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-d4af10ca3de88f89cdd9fb37323220be_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5BA2;&#x6237;&#x7AEF;&#x5173;&#x4E8E;&#x6D88;&#x8D39;&#x8005;&#x7684;&#x7C7B;&#x5B9A;&#x4E49;&#x5982;&#x4E0B;. &#x6BCF;&#x5F53;&#x7528;&#x6237;<strong>&#x6CE8;&#x518C;&#x6D88;&#x606F;&#x56DE;&#x8C03;&#x5904;&#x7406;&#x51FD;&#x6570; handler &#x65F6;&#xFF0C;consumer &#x5C31;&#x4F1A;&#x542F;&#x52A8;&#x4E00;&#x4E2A; handleLoop goroutine&#xFF0C;&#x8D1F;&#x8D23;&#x63A5;&#x6536;&#x6D88;&#x606F;&#x5E76;&#x8C03;&#x7528;&#x76F8;&#x5E94;&#x7684;&#x5904;&#x7406;&#x51FD;&#x6570;</strong>.</p><p>&#x9700;&#x8981;&#x6CE8;&#x610F;&#xFF0C;<strong>consumer &#x5728;&#x88AB;&#x521B;&#x5EFA;&#x51FA;&#x6765;&#x65F6;</strong>&#xFF0C;&#x5C31;&#x9700;&#x8981;<strong>&#x660E;&#x786E;&#x6307;&#x5B9A;&#x5176;&#x8BA2;&#x9605;&#x7684; topic &#x4EE5;&#x53CA; chanel.</strong></p><pre><code class="language-text">type Consumer struct {
    // ...
    // &#x4E92;&#x65A5;&#x9501;
    mtx sync.RWMutex


    // ...
    // &#x6D88;&#x8D39;&#x8005;&#x6807;&#x8BC6; id
    id      int64
    // &#x6D88;&#x8D39;&#x8005;&#x8BA2;&#x9605;&#x7684; topic
    topic   string
    // &#x6D88;&#x8D39;&#x8005;&#x8BA2;&#x9605;&#x7684; channel
    channel string
    // ...
    // &#x7528;&#x4E8E;&#x63A5;&#x6536;&#x6D88;&#x606F;&#x7684; channel
    incomingMessages chan *Message


    // ...
    pendingConnections map[string]*Conn
    connections        map[string]*Conn
  
    // &#x8FDE;&#x63A5;&#x7684; nsqd &#x5730;&#x5740;
    nsqdTCPAddrs []string


    // ...
}</code></pre><h3 id="332-%E6%B7%BB%E5%8A%A0-handler">3.3.2 &#x6DFB;&#x52A0; handler</h3><p>&#x7528;&#x6237;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;<strong>&#x8C03;&#x7528; Consumer.AddHandler(...) &#x65B9;&#x6CD5;&#xFF0C;&#x9488;&#x5BF9;&#x6BCF;&#x4E2A; handler &#x4F1A;&#x542F;&#x52A8;&#x4E00;&#x4E2A; handleLoop goroutine</strong> &#x7528;&#x4E8E;&#x5728;&#x6D88;&#x8D39;&#x5230;&#x6D88;&#x606F;&#x65F6;&#x6267;&#x884C;&#x9884;&#x5B9A;&#x4E49;&#x7684;&#x56DE;&#x8C03;&#x51FD;&#x6570;.</p><p>&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#xFF0C;<strong>&#x5018;&#x82E5;&#x7528;&#x6237;&#x6CE8;&#x518C;&#x4E86;&#x591A;&#x4E2A; handler&#xFF0C;&#x6700;&#x7EC8;&#x6BCF;&#x6761;&#x6D88;&#x606F;&#x53EA;&#x4F1A;&#x968F;&#x673A;&#x88AB;&#x5176;&#x4E2D;&#x4E00;&#x4E2A; handler &#x5904;&#x7406;</strong>.</p><pre><code class="language-text">func (r *Consumer) AddHandler(handler Handler) {
    r.AddConcurrentHandlers(handler, 1)
}
func (r *Consumer) AddConcurrentHandlers(handler Handler, concurrency int) {
    // ...
    atomic.AddInt32(&amp;r.runningHandlers, int32(concurrency))
    for i := 0; i &lt; concurrency; i++ {
        go r.handlerLoop(handler)
    }
}
func (r *Consumer) handlerLoop(handler Handler) {
    // ...
    for {
        message, ok := &lt;-r.incomingMessages
        // ...
        err := handler.HandleMessage(message)
        // ...
    }


    // ...
}</code></pre><h3 id="333-%E8%BF%9E%E6%8E%A5%E6%9C%8D%E5%8A%A1%E7%AB%AF">3.3.3 &#x8FDE;&#x63A5;&#x670D;&#x52A1;&#x7AEF;</h3><p>&#x6D88;&#x8D39;&#x8005;&#x901A;&#x8FC7;&#x8C03;&#x7528; Consumer.ConnectToNSQD(...) &#x65B9;&#x6CD5;&#xFF0C;&#x5B9E;&#x73B0;&#x4E0E; nsqd &#x670D;&#x52A1;&#x7AEF;&#x7684;&#x8FDE;&#x63A5;&#x4EA4;&#x4E92;&#xFF0C;&#x5176;&#x4E2D;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x5305;&#x62EC;&#xFF1A;</p><ul><li><strong>&#x8C03;&#x7528; NewConn(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x521B;&#x5EFA; Conn &#x5B9E;&#x4F8B;</li><li><strong>&#x8C03;&#x7528; Conn.Connect(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x5B9E;&#x9645;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x8D77;&#x8FDE;&#x63A5;</li><li><strong>&#x8C03;&#x7528; Conn.WriteCommand(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x9001; SUB &#x6307;&#x4EE4;</li></ul><pre><code class="language-text">func (r *Consumer) ConnectToNSQD(addr string) error {
    // &#x521B;&#x5EFA;&#x94FE;&#x63A5;
    conn := NewConn(addr, &amp;r.config, &amp;consumerConnDelegate{r})
    // ...
    r.mtx.Lock()
    _, pendingOk := r.pendingConnections[addr]
    _, ok := r.connections[addr]
    // ...
    r.pendingConnections[addr] = conn
    if idx := indexOf(addr, r.nsqdTCPAddrs); idx == -1 {
        r.nsqdTCPAddrs = append(r.nsqdTCPAddrs, addr)
    }
    r.mtx.Unlock()


    // ...
    resp, err := conn.Connect()
    // ...


    // ...
    cmd := Subscribe(r.topic, r.channel)
    err = conn.WriteCommand(cmd)
    // ...
    r.mtx.Lock()
    delete(r.pendingConnections, addr)
    r.connections[addr] = conn
    r.mtx.Unlock()
    // ...
    return nil
}</code></pre><h3 id="334-%E6%B6%88%E8%B4%B9%E6%B6%88%E6%81%AF">3.3.4 &#x6D88;&#x8D39;&#x6D88;&#x606F;</h3><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-a9509952b1097f032427e80e983f22ae_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5F53;&#x6307;&#x5B9A; topic channel &#x4E0B;&#x6709;&#x65B0;&#x6D88;&#x606F;&#x4EA7;&#x751F;&#x65F6;&#xFF0C;<strong>consumer &#x6301;&#x6709;&#x7684; conn &#x4F1A;&#x901A;&#x8FC7; readLoop goroutine &#x63A5;&#x6536;&#x5230;&#x5BF9;&#x5E94;&#x7684;&#x6D88;&#x606F;</strong>&#xFF0C;&#x5E76;&#x8C03;&#x7528; Consumer.onConnMessage(...) &#x65B9;&#x6CD5;&#xFF0C;<strong>&#x5C06;&#x6D88;&#x606F;&#x63A8;&#x9001;&#x5230; Consumer.incomingMessages </strong>&#x901A;&#x9053;&#x4E2D;.</p><pre><code class="language-text">func (c *Conn) readLoop() {
    delegate := &amp;connMessageDelegate{c}
    for {
        // ...


        frameType, data, err := ReadUnpackedResponse(c, c.config.MaxMsgSize)
        // ...


        switch frameType {
        // ...
        case FrameTypeMessage:
            msg, err := DecodeMessage(data)
            // ...           
            c.delegate.OnMessage(c, msg)
        // ...
    }


    // ...
}
func (d *consumerConnDelegate) OnMessage(c *Conn, m *Message)         { d.r.onConnMessage(c, m) }
func (r *Consumer) onConnMessage(c *Conn, msg *Message) {
    // ...
    r.incomingMessages &lt;- msg
}</code></pre><p>&#x6B64;&#x524D;&#x5728;&#x6CE8;&#x518C; consumer handler &#x65F6;&#x542F;&#x52A8;&#x7684; <strong>handlerLoop goroutine &#x4FBF;&#x4F1A;&#x901A;&#x8FC7; Consumer.incomingMessages &#x901A;&#x9053;&#x83B7;&#x53D6;&#x5230;&#x6D88;&#x606F;</strong>&#xFF0C;&#x5E76;<strong>&#x8C03;&#x7528;&#x76F8;&#x5E94;&#x7684; handler</strong> &#x6267;&#x884C;&#x56DE;&#x8C03;&#x5904;&#x7406;&#x903B;&#x8F91;.</p><pre><code class="language-text">func (r *Consumer) handlerLoop(handler Handler) {
    // ...
    for {
        message, ok := &lt;-r.incomingMessages
        // ...
        err := handler.HandleMessage(message)
        // ...
    }




    // ...
}</code></pre><h3 id="335-%E6%B6%88%E6%81%AF-ack">3.3.5 &#x6D88;&#x606F; ack</h3><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-9d48a23634526b6748d4a94490a544dc_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x4E3A;&#x9632;&#x6B62;&#x6D88;&#x606F;&#x4E22;&#x5931;&#xFF0C;nsq &#x4E2D;&#x540C;&#x6837;&#x652F;&#x6301;&#x4E86; <strong>consumer ack &#x673A;&#x5236;</strong>.</p><p>consumer &#x5728;&#x63A5;&#x6536;&#x5230;&#x6D88;&#x606F;&#x5E76;&#x6210;&#x529F;&#x8C03;&#x7528; handler &#x56DE;&#x8C03;&#x5904;&#x7406;&#x51FD;&#x6570;&#x540E;&#xFF0C;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;<strong>&#x8C03;&#x7528; Message.Finish() &#x65B9;&#x6CD5;&#xFF0C;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x9001; ack &#x6307;&#x4EE4;</strong>&#xFF0C;&#x786E;&#x8BA4;&#x6D88;&#x606F;&#x5DF2;&#x6210;&#x529F;&#x63A5;&#x6536;.</p><p>&#x5018;&#x82E5;&#x670D;&#x52A1;&#x7AEF;&#x8D85;&#x65F6;&#x672A;&#x6536;&#x5230; ack &#x54CD;&#x5E94;&#xFF0C;&#x5219;&#x4F1A;&#x9ED8;&#x8BA4;&#x6D88;&#x606F;&#x5DF2;&#x4E22;&#x5931;&#xFF0C;&#x4F1A;&#x91CD;&#x65B0;&#x63A8;&#x9001;&#x4E00;&#x8F6E;&#x6D88;&#x606F;.</p><p>consumer ack &#x6D41;&#x7A0B;&#x7684;&#x6838;&#x5FC3;&#x4EE3;&#x7801;&#x5C55;&#x793A;&#x5982;&#x4E0B;&#xFF0C;&#x5728; Conn.onMessageFinish(...) &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x4F1A;<strong>&#x901A;&#x8FC7; Conn.msgResponseChan </strong>&#x901A;&#x9053;&#x5C06;&#x6570;&#x636E;<strong>&#x63A8;&#x9001;&#x5230; Conn writeLoop goroutine </strong>&#x5F53;&#x4E2D;&#xFF0C;&#x7531;&#x5176;&#x8D1F;&#x8D23;&#x5C06;&#x8BF7;&#x6C42;&#x53D1;&#x5F80; nsqd &#x670D;&#x52A1;&#x7AEF;.</p><pre><code class="language-text">func (m *Message) Finish() {
    .// ..
    m.Delegate.OnFinish(m)
}
func (d *connMessageDelegate) OnFinish(m *Message) { d.c.onMessageFinish(m) }
func (c *Conn) onMessageFinish(m *Message) {
    c.msgResponseChan &lt;- &amp;msgResponse{msg: m, cmd: Finish(m.ID), success: true}
}</code></pre><p><strong>Conn.writeLoop</strong> &#x662F; Conn &#x8D1F;&#x8D23;&#x5411;&#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x9001;&#x6307;&#x4EE4;&#x7684;&#x5E38;&#x9A7B; goroutine&#xFF0C;&#x5176;&#x5728;<strong>&#x63A5;&#x6536;&#x5230;&#x6765;&#x81EA; Consumer.msgResponseChan &#x901A;&#x9053;</strong>&#x7684;&#x6570;&#x636E;&#x540E;&#xFF0C;&#x4F1A;&#x6839;&#x636E;&#x5176;&#x6210;&#x529F;&#x72B6;&#x6001;&#xFF0C;&#x9009;&#x62E9;<strong>&#x8C03;&#x7528; OnMessageFinished &#x6216;&#x8005; OnMessageRequeued </strong>&#x5C06;&#x5176;&#x5C01;&#x88C5;&#x6210; ack &#x6216;&#x8005;&#x91CD;&#x8BD5;&#x6307;&#x4EE4;<strong>&#xFF0C;</strong>&#x6700;&#x540E;&#x8C03;&#x7528; <strong>Conn.WriteCommand(...) &#x65B9;&#x6CD5;</strong>&#x5C06;&#x6307;&#x4EE4;&#x53D1;&#x5F80;&#x670D;&#x52A1;&#x7AEF;.</p><pre><code class="language-text">func (c *Conn) writeLoop() {
    for {
        select {
        // ...
        // ...  
        case resp := &lt;-c.msgResponseChan:
            // ...
            msgsInFlight := atomic.AddInt64(&amp;c.messagesInFlight, -1)


            if resp.success {
                c.log(LogLevelDebug, &quot;FIN %s&quot;, resp.msg.ID)
                c.delegate.OnMessageFinished(c, resp.msg)
                c.delegate.OnResume(c)
            } else {
                c.log(LogLevelDebug, &quot;REQ %s&quot;, resp.msg.ID)
                c.delegate.OnMessageRequeued(c, resp.msg)
                if resp.backoff {
                    c.delegate.OnBackoff(c)
                } else {
                    c.delegate.OnContinue(c)
                }
            }


            err := c.WriteCommand(resp.cmd)
            // ...
        }
    }
    // ...
}</code></pre><h2 id="4-%E6%9C%8D%E5%8A%A1%E7%AB%AF">4 &#x670D;&#x52A1;&#x7AEF;</h2><p>&#x63A5;&#x4E0B;&#x6765;&#x8FDB;&#x5165;&#x672C;&#x6587;&#x6700;&#x6838;&#x5FC3;&#x7684;&#x7AE0;&#x8282;&#xFF0C;&#x6211;&#x4EEC;&#x6765;&#x63ED;&#x793A;&#x4E00;&#x4E0B; nsq &#x670D;&#x52A1;&#x7AEF;&#x7684;&#x5E95;&#x5C42;&#x5B9E;&#x73B0;&#x539F;&#x7406;.</p><p>nsq &#x670D;&#x52A1;&#x7AEF;&#x5F00;&#x6E90;&#x5730;&#x5740;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//github.com/nsqio/nsq" rel="nofollow noreferrer">https://github.com/nsqio/nsq</a> &#x672C;&#x6587;<strong>&#x8D70;&#x8BFB;&#x6E90;&#x7801;&#x7684;&#x7248;&#x672C;&#x4E3A;: v1.2.1</strong></p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-2c3ee1b10c0b98316efd3929174c3330_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h2 id="41-%E6%A0%B8%E5%BF%83%E7%B1%BB">4.1 &#x6838;&#x5FC3;&#x7C7B;</h2><p>&#x9996;&#x5148;&#x7EDF;&#x4E00;&#x68B3;&#x7406;&#x4E00;&#x4E0B;&#xFF0C;nsq &#x670D;&#x52A1;&#x7AEF;&#x6240;&#x6D89;&#x53CA;&#x5230;&#x7684;&#x51E0;&#x4E2A;&#x6838;&#x5FC3;&#x7C7B;.</p><h3 id="411-nsqd">4.1.1 nsqd</h3><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-a12108c06f2a2467f7f143178104f05f_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>NSQD &#x7C7B;&#x5BF9;&#x5E94;&#x4E8E;&#x4E00;&#x4E2A; nsqd &#x8282;&#x70B9;&#xFF0C;&#x5176;&#x4E2D;&#x5C01;&#x88C5;&#x4E86;&#x5404;&#x7C7B;&#x91CD;&#x8981;&#x4FE1;&#x606F;&#xFF1A;</p><ul><li><strong>topicMap&#xFF1A;</strong>&#x5F53;&#x524D; nsqd &#x8282;&#x70B9;&#x4E0B;&#x5305;&#x542B;&#x7684; topic &#x96C6;&#x5408;</li><li>lookupPeers&#xFF1A;&#x5018;&#x82E5;&#x542F;&#x7528;&#x96C6;&#x7FA4;&#x6A21;&#x5F0F;&#xFF0C;&#x8BE5;&#x5B57;&#x6BB5;&#x6807;&#x8BC6;&#x51FA;&#x96C6;&#x7FA4;&#x4E2D;&#x5176;&#x4ED6;&#x8282;&#x70B9;&#x7684;&#x4FE1;&#x606F;</li><li><strong>tcpServer&#xFF1A;</strong>nsqd &#x8282;&#x70B9;&#x4E0B;&#x7684; tcp &#x670D;&#x52A1;&#xFF0C;&#x7528;&#x4E8E;&#x63A5;&#x6536;&#x5904;&#x7406;&#x6765;&#x81EA;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x5404;&#x79CD;&#x8BF7;&#x6C42;&#x6307;&#x4EE4;</li></ul><pre><code class="language-text">type NSQD struct {
    // &#x8282;&#x70B9;&#x5185;&#x9012;&#x589E;&#x7684;&#x5BA2;&#x6237;&#x7AEF; id &#x5E8F;&#x53F7;&#xFF0C;&#x4E3A;&#x6BCF;&#x4E2A;&#x5230;&#x6765;&#x7684;&#x5BA2;&#x6237;&#x7AEF;&#x8BF7;&#x6C42;&#x5206;&#x914D;&#x552F;&#x4E00;&#x7684;&#x6807;&#x8BC6; id
    clientIDSequence int64
    // &#x4E00;&#x628A;&#x8BFB;&#x5199;&#x9501;&#xFF0C;&#x4FDD;&#x8BC1;&#x4E34;&#x754C;&#x8D44;&#x6E90;&#x5E76;&#x53D1;&#x5B89;&#x5168;
    sync.RWMutex
    
    // ...
    // &#x5B58;&#x5728;&#x7684; topic &#x96C6;&#x5408;
    topicMap map[string]*Topic


    // &#x96C6;&#x7FA4;&#x4E2D;&#x7684;&#x5176;&#x4ED6; nsqd &#x8282;&#x70B9; 
    lookupPeers atomic.Value
    // &#x8FD0;&#x884C;&#x7684; tcp server
    tcpServer     *tcpServer
    // tcp server &#x4F7F;&#x7528;&#x7684;&#x7AEF;&#x53E3;&#x76D1;&#x542C;&#x5668;
    tcpListener   net.Listener
    // http server &#x4F7F;&#x7528;&#x7684;&#x7AEF;&#x53E3;&#x76D1;&#x542C;&#x5668;
    httpListener  net.Listener
    // https server &#x4F7F;&#x7528;&#x7684;&#x7AEF;&#x53E3;&#x76D1;&#x542C;&#x5668;
    httpsListener net.Listener
    // ...


    // &#x7528;&#x4E8E;&#x56DE;&#x6536;&#x6D3E;&#x751F;&#x51FA;&#x53BB;&#x7684; goroutine  
    exitChan             chan int
    // &#x5E76;&#x53D1;&#x7B49;&#x5F85;&#x7EC4;&#x5DE5;&#x5177;&#xFF0C;&#x4FDD;&#x8BC1;&#x6D3E;&#x53D1;&#x51FA;&#x53BB;&#x7684; goroutine &#x90FD;&#x80FD;&#x5F97;&#x5230;&#x53CA;&#x65F6;&#x56DE;&#x6536;
    waitGroup            util.WaitGroupWrapper
    // &#x96C6;&#x7FA4;&#x4FE1;&#x606F;
    ci *clusterinfo.ClusterInfo
}</code></pre><h3 id="412-topic">4.1.2 topic</h3><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-be3480d1d8d57433ea0e9eaa28c69fbc_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>Topic &#x5BF9;&#x5E94;&#x4E3A;&#x4E00;&#x4E2A;&#x6D88;&#x606F;&#x4E3B;&#x9898;&#xFF0C;&#x5176;&#x4E0B;&#x5305;&#x542B;&#x6838;&#x5FC3;&#x5B57;&#x6BB5;&#xFF1A;</p><ul><li><strong>channelMap</strong>&#xFF1A;topic &#x4E0B;&#x7684; channel &#x96C6;&#x5408;</li><li><strong>memoryMsgChan&#xFF1A;</strong>&#x6709;&#x65B0;&#x6D88;&#x606F;&#x5230;&#x8FBE;&#x65F6;&#xFF0C;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x901A;&#x8FC7;&#x6B64;&#x901A;&#x9053;&#x5411; topic &#x4F20;&#x9012;&#x6D88;&#x606F;</li><li><strong>backend&#xFF1A;&#x5F53; memoryMsgChan &#x5BB9;&#x91CF;&#x8FBE;&#x5230;&#x4E0A;&#x9650;&#x65F6;</strong>&#xFF0C;&#x5219;&#x901A;&#x8FC7;&#x78C1;&#x76D8;&#x6587;&#x4EF6;&#x5411; topic &#x4F20;&#x9012;&#x6D88;&#x606F;</li><li>nsqd&#xFF1A;&#x4ECE;&#x5C5E;&#x7684; nsqd &#x6A21;&#x5757;</li></ul><pre><code class="language-text">type Topic struct {
    // &#x7EDF;&#x8BA1;&#x6D88;&#x606F;&#x6570;&#x91CF;&#x548C;&#x5927;&#x5C0F;
    messageCount uint64
    messageBytes uint64
    
    // &#x8BFB;&#x5199;&#x9501;&#xFF0C;&#x4FDD;&#x8BC1;&#x4E34;&#x754C;&#x8D44;&#x6E90;&#x5E76;&#x53D1;&#x5B89;&#x5168;
    sync.RWMutex


    // &#x5F53;&#x524D; topic &#x540D;&#x79F0;
    name              string
    // &#x5F53;&#x524D; topic &#x4E0B;&#x5B58;&#x5728;&#x7684; channel &#x96C6;&#x5408;
    channelMap        map[string]*Channel
    // &#x5F53; memoryMsgChan &#x6EE1;&#x4E86;&#xFF0C;&#x6D88;&#x606F;&#x901A;&#x8FC7;&#x8BE5;&#x7EC4;&#x4EF6;&#x6301;&#x4E45;&#x5316;&#x843D;&#x76D8;
    backend           BackendQueue
    // &#x7528;&#x4E8E;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x4F20;&#x9012;&#x5F53;&#x524D; topic &#x4E0B;&#x7684;&#x6D88;&#x606F;
    memoryMsgChan     chan *Message
    // &#x901A;&#x77E5; pump goroutine &#x542F;&#x52A8;
    startChan         chan int
    // &#x901A;&#x77E5; pump goroutine &#x9000;&#x51FA;
    exitChan          chan int
    // &#x901A;&#x77E5; pump goroutine channels &#x6709;&#x66F4;&#x65B0;
    channelUpdateChan chan int
    // &#x7B49;&#x5F85;&#x7EC4;&#x5DE5;&#x5177;&#xFF0C;&#x4FDD;&#x8BC1;&#x5F53;&#x524D; topic &#x4E0B;&#x6D3E;&#x751F;&#x51FA;&#x7684; goroutine &#x80FD;&#x591F;&#x88AB;&#x56DE;&#x6536;
    waitGroup         util.WaitGroupWrapper
    // &#x6D88;&#x606F; id &#x751F;&#x6210;&#x5668;
    idFactory         *guidFactory


    // ...
    // &#x4ECE;&#x5C5E;&#x7684; nsqd &#x6A21;&#x5757;
    nsqd *NSQD
}</code></pre><p>&#x5728; topic &#x88AB;&#x6784;&#x9020;&#x51FA;&#x6765;&#x65F6;&#xFF0C;&#x4F1A;<strong>&#x8C03;&#x7528; Topic.messagePump(...) &#x65B9;&#x6CD5;&#xFF0C;&#x5F02;&#x6B65;&#x542F;&#x52A8;&#x4E00;&#x4E2A; goroutine</strong>&#xFF0C;&#x8D1F;&#x8D23;&#x6301;&#x7EED;<strong>&#x63A5;&#x6536;&#x5206;&#x914D;&#x7ED9;&#x8BE5; topic &#x7684;&#x6D88;&#x606F;</strong>&#xFF0C;&#x5E76;<strong>&#x5C06;&#x6D88;&#x606F;&#x9010;&#x4E00;&#x53D1;&#x9001;&#x7ED9;&#x8BE5; topic &#x4E0B;&#x7684;&#x6BCF;&#x4E2A; channel</strong></p><pre><code class="language-text">// Topic constructor
func NewTopic(topicName string, nsqd *NSQD, deleteCallback func(*Topic)) *Topic {
    // &#x6784;&#x9020; topic &#x5B9E;&#x4F8B;
    t := &amp;Topic{
        // ...
    }
    // ...


    // &#x542F;&#x52A8; topic &#x4E0B;&#x7684; pump goroutine
    t.waitGroup.Wrap(t.messagePump)


    // ...
    // &#x8FD4;&#x56DE; topic &#x5B9E;&#x4F8B;
    return t
}</code></pre><p>topic.messagePump &#x65B9;&#x6CD5;&#x975E;&#x5E38;&#x6838;&#x5FC3;&#xFF0C;&#x8FD9;&#x91CC;&#x5148;&#x5C55;&#x793A;&#x4E00;&#x4E0B;&#x5176;&#x6838;&#x5FC3;&#x6E90;&#x7801;&#xFF0C;&#x8BE5;&#x65B9;&#x6CD5;&#x5728;&#x540E;&#x7EED; 4.3 &#x5C0F;&#x8282;&#x7684; publish &#x6D41;&#x7A0B;&#x4E2D;&#x8FD8;&#x4F1A;&#x6709;&#x6240;&#x6D89;&#x53CA;.</p><pre><code class="language-text">func (t *Topic) messagePump() {
    var msg *Message
    var buf []byte
    var err error
    var chans []*Channel
    var memoryMsgChan chan *Message
    var backendChan &lt;-chan []byte


    // ...
    t.RLock()
    for _, c := range t.channelMap {
        chans = append(chans, c)
    }
    t.RUnlock()
    if len(chans) &gt; 0 &amp;&amp; !t.IsPaused() {
        // &#x83B7;&#x53D6;&#x57FA;&#x4E8E;&#x5185;&#x5B58;&#x7684; memoryChan &#x548C;&#x57FA;&#x4E8E;&#x78C1;&#x76D8;&#x7684; backendChan
        memoryMsgChan = t.memoryMsgChan
        backendChan = t.backend.ReadChan()
    }




    // main message loop
    for {
        select {
        // &#x901A;&#x8FC7;&#x5185;&#x5B58;&#x901A;&#x9053;&#x63A5;&#x6536;&#x6D88;&#x606F;
        case msg = &lt;-memoryMsgChan:
        // &#x901A;&#x8FC7;&#x78C1;&#x76D8;&#x901A;&#x9053;&#x63A5;&#x6536;&#x6D88;&#x606F;
        case buf = &lt;-backendChan:
            msg, err = decodeMessage(buf)
            // ...
        // &#x5018;&#x82E5;&#x548C; lookupd &#x901A;&#x4FE1;&#x53D1;&#x9001; channel &#x6709;&#x53D8;&#x66F4;&#xFF0C;&#x5219;&#x9700;&#x8981;&#x5BF9; channels list &#x8FDB;&#x884C;&#x66F4;&#x65B0;
        case &lt;-t.channelUpdateChan:
            chans = chans[:0]
            t.RLock()
            for _, c := range t.channelMap {
                chans = append(chans, c)
            }
            t.RUnlock()
            if len(chans) == 0 || t.IsPaused() {
                memoryMsgChan = nil
                backendChan = nil
            } else {
                memoryMsgChan = t.memoryMsgChan
                backendChan = t.backend.ReadChan()
            }
            continue
        // ...
        }


        // &#x904D;&#x5386; topic &#x4E0B;&#x6240;&#x6709; channel&#xFF0C;&#x4E00;&#x4E00;&#x5C06;&#x6D88;&#x606F;&#x6295;&#x9012;&#x8FC7;&#x53BB;
        for i, channel := range chans {
            chanMsg := msg
            // ...
            // &#x5018;&#x82E5;&#x6D88;&#x606F;&#x7C7B;&#x578B;&#x4E3A;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#xFF0C;&#x5219;&#x5C06;&#x5176;&#x6DFB;&#x52A0;&#x5230;&#x5EF6;&#x65F6;&#x961F;&#x5217;
            if chanMsg.deferred != 0 {
                channel.PutMessageDeferred(chanMsg, chanMsg.deferred)
                continue
            }
            // &#x5C06;&#x6D88;&#x606F;&#x9010;&#x4E00;&#x6295;&#x9012;&#x5230; topic &#x4E0B;&#x7684;&#x6BCF;&#x4E2A; channel &#x4E2D;
            err := channel.PutMessage(chanMsg)
            // ...
        }
    }


    // ...
}</code></pre><h3 id="413-channel">4.1.3 channel</h3><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-2c3865c05738909524aed9d1744da0c8_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>Channel &#x5BF9;&#x5E94;&#x4E3A;&#x4E00;&#x4E2A;&#x6D88;&#x606F;&#x9891;&#x9053;&#xFF0C;</p><ul><li><strong>memoryMsgChan&#xFF1A;</strong>&#x6709;&#x65B0;&#x6D88;&#x606F;&#x5230;&#x8FBE;&#x65F6;&#xFF0C;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x901A;&#x8FC7;&#x6B64;&#x901A;&#x9053;&#x5411; channel &#x4F20;&#x9012;&#x6D88;&#x606F;</li><li><strong>backend&#xFF1A;&#x5F53; memoryMsgChan &#x5BB9;&#x91CF;&#x8FBE;&#x5230;&#x4E0A;&#x9650;&#x65F6;</strong>&#xFF0C;&#x5219;&#x901A;&#x8FC7;&#x78C1;&#x76D8;&#x6587;&#x4EF6;&#x5411; channel &#x4F20;&#x9012;&#x6D88;&#x606F;</li><li><strong>clients: </strong>&#x8BA2;&#x9605;&#x8BE5; channel &#x7684; consumer &#x96C6;&#x5408;</li><li><strong>deferredPQ&#xFF1A;</strong>channel &#x4E0B;&#x7684;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x961F;&#x5217;&#xFF0C;&#x57FA;&#x4E8E;&#x5C0F;&#x9876;&#x5806;&#x5B9E;&#x73B0;</li><li><strong>inFlightPQ&#xFF1A;</strong>channel &#x4E0B;&#x7684;&#x5F85; ack &#x786E;&#x8BA4;&#x6D88;&#x606F;&#x961F;&#x5217;&#xFF0C;&#x57FA;&#x4E8E;&#x5C0F;&#x9876;&#x5806;&#x5B9E;&#x73B0;</li></ul><p>&#x503C;&#x5F97;&#x4E00;&#x63D0;&#x7684;&#x662F;&#xFF0C;channel &#x4E0B;&#x7684; <strong>memoryMsgChan &#x548C; backend</strong> &#x4F1A;&#x540C;&#x65F6;<strong>&#x88AB;&#x6240;&#x6709;&#x8BA2;&#x9605;&#x4E86;&#x8BE5; channel &#x7684; consumer client goroutine &#x6240;&#x63A5;&#x6536;</strong>&#xFF0C;&#x56E0;&#x6B64; <strong>channel &#x4E0B;&#x7684;&#x540C;&#x4E00;&#x6761;&#x6D88;&#x606F;&#x53EA;&#x4F1A;&#x968F;&#x673A;&#x88AB;&#x67D0;&#x4E2A; consumer &#x6D88;&#x8D39;&#x5230;</strong>.</p><pre><code class="language-text">type Channel struct {
    // &#x4E00;&#x4E9B;&#x8BA1;&#x6570;&#x5668;
    requeueCount uint64
    messageCount uint64
    timeoutCount uint64


    // &#x8BFB;&#x5199;&#x9501;&#xFF0C;&#x4FDD;&#x8BC1;&#x4E34;&#x754C;&#x8D44;&#x6E90;&#x5E76;&#x53D1;&#x5B89;&#x5168;
    sync.RWMutex
    // &#x4ECE;&#x5C5E;&#x7684; topic &#x540D;&#x79F0;
    topicName string
    // &#x5F53;&#x524D; channel &#x540D;&#x79F0;
    name      string
    // &#x4ECE;&#x5C5E;&#x7684; nsqd &#x6A21;&#x5757;
    nsqd      *NSQD
    // &#x5F53; memoryMsgChan &#x6EE1;&#x4E86;&#xFF0C;&#x5219;&#x901A;&#x8FC7;&#x8BE5;&#x7EC4;&#x4EF6;&#x5C06;&#x6D88;&#x606F;&#x843D;&#x76D8;&#x4F20;&#x9012;
    backend BackendQueue
    // &#x7528;&#x4E8E;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x4F20;&#x9012;&#x5F53;&#x524D; channel &#x4E0B;&#x7684;&#x6D88;&#x606F;
    memoryMsgChan chan *Message
    // ...
    // &#x8BB0;&#x5F55;&#x5F53;&#x524D; channel &#x4E0B;&#x7684; consumer &#x96C6;&#x5408;
    clients        map[int64]Consumer
    // &#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x96C6;&#x5408;
    deferredMessages map[MessageID]*pqueue.Item
    // &#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x961F;&#x5217;&#xFF0C;&#x5E95;&#x5C42;&#x57FA;&#x4E8E;&#x4E00;&#x4E2A;&#x5C0F;&#x9876;&#x5806;&#x5B9E;&#x73B0;&#xFF0C;&#x4EE5;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x6233;&#x4F5C;&#x4E3A;&#x6392;&#x5E8F;&#x7684;&#x952E;
    deferredPQ       pqueue.PriorityQueue
    // &#x4FDD;&#x62A4;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x961F;&#x5217;&#x7684;&#x4E92;&#x65A5;&#x9501;
    deferredMutex    sync.Mutex
    // &#x91CD;&#x8BD5;(&#x5F85;&#x786E;&#x8BA4;)&#x6D88;&#x606F;&#x96C6;&#x5408;
    inFlightMessages map[MessageID]*Message
    // &#x91CD;&#x8BD5;(&#x5F85;&#x786E;&#x8BA4;)&#x6D88;&#x606F;&#x961F;&#x5217;&#xFF0C;&#x5E95;&#x5C42;&#x57FA;&#x4E8E;&#x4E00;&#x4E2A;&#x5C0F;&#x9876;&#x5806;&#x5B9E;&#x73B0;&#xFF0C;&#x4EE5;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x6233;&#x4F5C;&#x4E3A;&#x6392;&#x5E8F;&#x7684;&#x952E;
    inFlightPQ       inFlightPqueue
    // &#x4FDD;&#x62A4;&#x91CD;&#x8BD5;(&#x5F85;&#x786E;&#x8BA4;)&#x6D88;&#x606F;&#x961F;&#x5217;&#x7684;&#x4E92;&#x65A5;&#x9501;
    inFlightMutex    sync.Mutex
}</code></pre><h3 id="414-deferredpq">4.1.4 deferredPQ</h3><p>&#x5EF6;&#x65F6;&#x961F;&#x5217; deferredQ &#x548C;&#x5F85; ack &#x961F;&#x5217; inFlightPQ &#x5E95;&#x5C42;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x7C7B;&#x4F3C;&#xFF0C;&#x90FD;&#x662F;&#x57FA;&#x4E8E;&#x65F6;&#x95F4;&#x6233;&#x8FDB;&#x884C;&#x6392;&#x5E8F;&#x7684;&#x5C0F;&#x9876;&#x5806;. &#x8FD9;&#x91CC;&#x6211;&#x4EEC;&#x4EE5; deferredPQ &#x4E3A;&#x4F8B;&#x5C55;&#x5F00;&#x4ECB;&#x7ECD;.</p><p>&#x5728; deferredQ &#x4E2D;&#x4F7F;&#x7528;&#x4E86; golang container/heap &#x6807;&#x51C6;&#x5E93;&#x4E2D;&#x7684;&#x5806;&#x7ED3;&#x6784;&#xFF0C;&#x5176;&#x4E2D;&#x5B9A;&#x4E49;&#x7684;&#x5806; interface &#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">type Interface interface {
    sort.Interface
    Push(x any) // add x as element Len()
    Pop() any   // remove and return element Len() - 1.
}
type Interface interface {
    // &#x8FD4;&#x56DE;&#x5806;&#x7684;&#x957F;&#x5EA6;
    Len() int


    // &#x5224;&#x65AD;&#x5806;&#x4E2D;&#x5143;&#x7D20;&#x5927;&#x5C0F;&#x7684;&#x89C4;&#x5219;
    Less(i, j int) bool


    // &#x4EA4;&#x6362; index = i &#x548C; index = j &#x7684;&#x4E24;&#x4E2A;&#x5143;&#x7D20;
    Swap(i, j int)
}</code></pre><p>&#x5728; nsq &#x4E2D;&#x5B9A;&#x4E49;&#x4E86;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#x7C7B;&#x578B; PriorityQueue&#xFF0C;&#x9010;&#x4E00;&#x5B9E;&#x73B0;&#x4E86;&#x4E0A;&#x8FF0; interface &#x7684;&#x5404;&#x4E2A;&#x65B9;&#x6CD5;. &#x5176;&#x4E2D;&#xFF0C;&#x7528;&#x4E8E;&#x6BD4;&#x8F83;&#x5143;&#x7D20;&#x5927;&#x5C0F;&#x7684; Item.Priority &#x5BF9;&#x5E94;&#x5C31;&#x662F;&#x4E00;&#x6761;&#x6D88;&#x606F;&#x7684;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x6233;.</p><pre><code class="language-text">type Item struct {
    Value    interface{}
    Priority int64
    Index    int
}


// this is a priority queue as implemented by a min heap
// ie. the 0th element is the *lowest* value
type PriorityQueue []*Item




func New(capacity int) PriorityQueue {
    return make(PriorityQueue, 0, capacity)
}




func (pq PriorityQueue) Len() int {
    return len(pq)
}




func (pq PriorityQueue) Less(i, j int) bool {
    return pq[i].Priority &lt; pq[j].Priority
}




func (pq PriorityQueue) Swap(i, j int) {
    pq[i], pq[j] = pq[j], pq[i]
    pq[i].Index = i
    pq[j].Index = j
}




func (pq *PriorityQueue) Push(x interface{}) {
    n := len(*pq)
    c := cap(*pq)
    if n+1 &gt; c {
        npq := make(PriorityQueue, n, c*2)
        copy(npq, *pq)
        *pq = npq
    }
    *pq = (*pq)[0 : n+1]
    item := x.(*Item)
    item.Index = n
    (*pq)[n] = item
}




func (pq *PriorityQueue) Pop() interface{} {
    n := len(*pq)
    c := cap(*pq)
    if n &lt; (c/2) &amp;&amp; c &gt; 25 {
        npq := make(PriorityQueue, n, c/2)
        copy(npq, *pq)
        *pq = npq
    }
    item := (*pq)[n-1]
    item.Index = -1
    *pq = (*pq)[0 : n-1]
    return item
}</code></pre><p>&#x5728; PriorityQueue &#x4E2D;&#x4E13;&#x95E8;<strong>&#x5B9E;&#x73B0;&#x4E86;&#x4E00;&#x4E2A; PriorityQueue.PeekAndShift(...) </strong>&#x65B9;&#x6CD5;&#xFF0C;&#x5176;&#x4F5C;&#x7528;&#x662F;<strong>&#x4F20;&#x5165;&#x4E00;&#x4E2A;&#x6307;&#x5B9A;&#x65F6;&#x95F4;&#x6233; max&#xFF0C;&#x5018;&#x82E5;&#x5806;&#x9876;&#x6D88;&#x606F;&#x65F6;&#x95F4;&#x6233;&#x5C0F;&#x4E8E;&#x7B49;&#x4E8E; max&#xFF0C;&#x5219; pop &#x5F39;&#x51FA;</strong>&#xFF0C;&#x5426;&#x5219;&#x4E0D;&#x6267;&#x884C;&#x4EFB;&#x4F55;&#x64CD;&#x4F5C;.</p><pre><code class="language-text">func (pq *PriorityQueue) PeekAndShift(max int64) (*Item, int64) {
    if pq.Len() == 0 {
        return nil, 0
    }


    item := (*pq)[0]
    if item.Priority &gt; max {
        return nil, item.Priority - max
    }
    heap.Remove(pq, 0)




    return item, 0
}</code></pre><p><strong>&#x5F80;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#x4E2D;&#x6DFB;&#x52A0;&#x6D88;&#x606F;&#x7684;&#x65B9;&#x6CD5;&#x5165;&#x53E3;&#x4E3A; Channel.addToDeferredPQ(...)</strong>&#xFF0C;&#x5176;&#x4E2D;&#x4F1A;&#x628A;&#x4E00;&#x6761;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x5C01;&#x88C5;&#x6210;&#x4E00;&#x4E2A; pqueue.Item&#xFF0C;&#x7136;&#x540E;<strong>&#x8C03;&#x7528; container/heap &#x5305;&#x4E0B;&#x7684; Push &#x65B9;&#x6CD5;&#xFF0C;&#x91CC;&#x9762;&#x4F1A;&#x5B9E;&#x73B0;&#x65B0;&#x5143;&#x7D20;&#x5165;&#x5806;&#x7684; heapInsert &#x64CD;&#x4F5C;</strong>.</p><pre><code class="language-text">func (c *Channel) addToDeferredPQ(item *pqueue.Item) {
    c.deferredMutex.Lock()
    heap.Push(&amp;c.deferredPQ, item)
    c.deferredMutex.Unlock()
}</code></pre><p>&#x4ECB;&#x7ECD;&#x5B8C;&#x51E0;&#x4E2A;&#x6838;&#x5FC3;&#x7C7B;&#x4E4B;&#x540E;&#xFF0C;&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x5F00;&#x59CB;&#x9488;&#x5BF9;&#x51E0;&#x4E2A;&#x6838;&#x5FC3;&#x6D41;&#x7A0B;&#x8FDB;&#x884C;&#x68B3;&#x7406;&#x603B;&#x7ED3;.</p><h2 id="42-%E6%9C%8D%E5%8A%A1%E8%BF%90%E8%A1%8C">4.2 &#x670D;&#x52A1;&#x8FD0;&#x884C;</h2><p>&#x9996;&#x5148;&#x6211;&#x4EEC;&#x4ECB;&#x7ECD;&#x4E00;&#x4E0B;&#xFF0C;nsqd &#x670D;&#x52A1;&#x7AEF;&#x662F;&#x5982;&#x4F55;&#x542F;&#x52A8;&#x8FD0;&#x884C;&#x7684;.</p><h3 id="421-%E5%AE%8F%E8%A7%82%E6%B5%81%E7%A8%8B">4.2.1 &#x5B8F;&#x89C2;&#x6D41;&#x7A0B;</h3><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-8f72346b9b0f9a11979b24b33594617a_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x9996;&#x5148;&#xFF0C;nsqd &#x670D;&#x52A1;&#x7AEF;&#x7684;&#x542F;&#x52A8;&#x5165;&#x53E3;&#x4F4D;&#x4E8E; apps/nsqd/main.go &#x6587;&#x4EF6;&#x7684; main &#x65B9;&#x6CD5;&#x4E2D;&#xFF1A;</p><pre><code class="language-text">func main() {
    prg := &amp;program{}
    if err := svc.Run(prg, syscall.SIGINT, syscall.SIGTERM); err != nil {
        logFatal(&quot;%s&quot;, err)
    }
}</code></pre><p>&#x6B64;&#x5904; nsq &#x4F7F;&#x7528;&#x4E86; go-svc &#x811A;&#x624B;&#x67B6;&#xFF1A;<a href="https://link.zhihu.com/?target=https%3A//github.com/judwhite/go-svc" rel="nofollow noreferrer">https://github.com/judwhite/go-svc</a> .</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-7542db68f401790c7a5dcc5b7c597953_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5728; svc &#x6846;&#x67B6;&#x4E2D;&#xFF0C;&#x4F1A;&#x5206;&#x522B;&#x8C03;&#x7528; program &#x7684; Init() &#x548C; Start() &#x65B9;&#x6CD5;&#xFF0C;&#x7528;&#x4E8E;&#x521D;&#x59CB;&#x5316;&#x548C;&#x8FD0;&#x884C; nsqd &#x540E;&#x53F0;&#x7A0B;&#x5E8F;.</p><p><strong>I program.Init</strong></p><p>&#x5728; program.Init() &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x4F1A;&#x8BFB;&#x53D6;&#x7528;&#x6237;&#x8F93;&#x5165;&#x7684;&#x914D;&#x7F6E;&#xFF0C;&#x7136;&#x540E;&#x6784;&#x9020;&#x51FA; nsqd &#x5B9E;&#x4F8B;&#xFF1A;</p><pre><code class="language-text">func (p *program) Init(env svc.Environment) error {
    // ...
    
    // &#x521D;&#x59CB;&#x5316; nsqd &#x5B9E;&#x4F8B;
    nsqd, err := nsqd.New(opts)
    // ...
    p.nsqd = nsqd


    return nil
}</code></pre><p><strong>II program.Start</strong></p><p>&#x5728; program.Start() &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x4F1A;&#x5F02;&#x6B65;&#x8C03;&#x7528; NSQD.Main() &#x65B9;&#x6CD5;&#xFF0C;&#x5E76;&#x5206;&#x522B;&#x5728;&#x5176;&#x4E2D;&#x542F;&#x52A8;&#x5982;&#x4E0B;&#x51E0;&#x4E2A;&#x5F02;&#x6B65;&#x4EFB;&#x52A1;&#xFF1A;</p><ul><li><strong>&#x542F;&#x52A8; tcp server&#xFF1A;</strong>&#x9762;&#x5411;&#x5BA2;&#x6237;&#x7AEF;&#x63D0;&#x4F9B;&#x670D;&#x52A1;&#xFF0C;&#x5904;&#x7406;&#x5404;&#x79CD;&#x8BF7;&#x6C42;&#x6307;&#x4EE4;</li><li>&#x542F;&#x52A8; http/https server&#xFF1A;&#x9762;&#x5411;&#x5BA2;&#x6237;&#x7AEF;&#x63D0;&#x4F9B;&#x751F;&#x4EA7;&#x6D88;&#x606F;&#x90E8;&#x5206;&#x670D;&#x52A1;</li><li><strong>&#x542F;&#x52A8; queueScanLoop&#xFF1A;</strong>&#x6267;&#x884C;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#x3001;&#x5F85; ack &#x961F;&#x5217;&#x7684;&#x626B;&#x63CF;&#x4EFB;&#x52A1;</li><li>&#x542F;&#x52A8; lookupLoop&#xFF1A;&#x4E0E; nsqlookupd &#x4EA4;&#x4E92;&#xFF0C;&#x66F4;&#x65B0;&#x5143;&#x6570;&#x636E;&#x4FE1;&#x606F;</li></ul><pre><code class="language-text">func (p *program) Start() error {
    // program &#x542F;&#x52A8;&#x524D;&#x4F1A;&#x52A0;&#x8F7D;&#x4E4B;&#x524D;&#x5B58;&#x50A8;&#x7684;&#x5386;&#x53F2;&#x6570;&#x636E;&#x4FE1;&#x606F;
    err := p.nsqd.LoadMetadata()
    // ...
    err = p.nsqd.PersistMetadata()
    // ...


    go func() {
        // &#x8C03;&#x7528; nsqd.Main &#x65B9;&#x6CD5;&#xFF0C;&#x542F;&#x52A8; nsqd &#x5E38;&#x9A7B; goroutine
        err := p.nsqd.Main()
        // ...
    }()


    return nil
}
func (n *NSQD) Main() error {
    // ...
    // &#x542F;&#x52A8; tcp &#x670D;&#x52A1;&#xFF0C;&#x63D0;&#x4F9B; publish &#x548C; subscribe 
    n.waitGroup.Wrap(func() {
        exitFunc(protocol.TCPServer(n.tcpListener, n.tcpServer, n.logf))
    })    
    // &#x542F;&#x52A8; http server&#xFF0C;&#x63D0;&#x4F9B; publish &#x6D41;&#x7A0B;&#x6709;&#x5173;&#x7684; api
    if n.httpListener != nil {
        httpServer := newHTTPServer(n, false, n.getOpts().TLSRequired == TLSRequired)
        n.waitGroup.Wrap(func() {
            exitFunc(http_api.Serve(n.httpListener, httpServer, &quot;HTTP&quot;, n.logf))
        })
    }
    // &#x542F;&#x52A8; https server
    if n.httpsListener != nil {
        httpsServer := newHTTPServer(n, true, true)
        n.waitGroup.Wrap(func() {
            exitFunc(http_api.Serve(n.httpsListener, httpsServer, &quot;HTTPS&quot;, n.logf))
        })
    }


    n.waitGroup.Wrap(n.queueScanLoop)
    // &#x542F;&#x52A8;
    n.waitGroup.Wrap(n.lookupLoop)
    // ...


    err := &lt;-exitCh
    return err
}</code></pre><h3 id="422-tcp-server">4.2.2 tcp server</h3><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-7157e9d338472c15c6bc3f48cd8cfb5d_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>nsqd &#x7684; tcp server &#x90E8;&#x5206;&#x91C7;&#x7528;&#x7684;&#x662F;<strong>&#x670D;&#x52A1;&#x7AEF;&#x4E2D;&#x7ECF;&#x5178;&#x7684; for + listen &#x6A21;&#x5F0F;</strong>&#xFF0C;&#x6BCF;&#x5F53;&#x901A;&#x8FC7; <strong>listener.Accept() &#x65B9;&#x6CD5;</strong>&#x63A5;&#x6536;&#x5230;&#x4E00;&#x7B14;&#x6765;&#x81EA;&#x4E8E;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x8FDE;&#x63A5;&#x540E;&#xFF0C;&#x4F1A;<strong>&#x4E3A;&#x8FD9;&#x7B14;&#x8FDE;&#x63A5;&#x5206;&#x914D;&#x4E00;&#x4E2A; goroutine</strong> &#x5904;&#x7406;&#x540E;&#x7EED;&#x5230;&#x6765;&#x7684;&#x8BF7;&#x6C42;.</p><p>&#x8FD9;&#x90E8;&#x5206;&#x5B9E;&#x73B0;&#x4E0E; go&#x8BED;&#x8A00; net/http &#x6807;&#x51C6;&#x5E93;&#x7C7B;&#x4F3C;&#xFF0C;listener.Accept() &#x65B9;&#x6CD5;&#x5411;&#x4E0B;&#x5EF6;&#x4F38;&#x4F1A;&#x4F7F;&#x7528;&#x5230; linux &#x7684; epoll &#x591A;&#x8DEF;&#x590D;&#x7528;&#x6307;&#x4EE4;&#xFF0C;&#x8FD9;&#x90E8;&#x5206;&#x5185;&#x5BB9;&#x5927;&#x5BB6;&#x5982;&#x679C;&#x611F;&#x5174;&#x8DA3;&#x7684;&#x8BDD;&#xFF0C;&#x53EF;&#x4EE5;&#x9605;&#x8BFB;&#x4E00;&#x4E0B;&#x6211;&#x4E4B;&#x524D;&#x53D1;&#x8868;&#x7684;&#x4E24;&#x7BC7;&#x6587;&#x7AE0;&#xFF1A;</p><ul><li>Golang HTTP &#x6807;&#x51C6;&#x5E93;&#x5B9E;&#x73B0;&#x539F;&#x7406;</li><li>&#x89E3;&#x6790; Golang &#x7F51;&#x7EDC; IO &#x6A21;&#x578B;&#x4E4B; EPOLL</li></ul><p>&#x56DE;&#x5F52;&#x6B63;&#x9898;&#xFF0C;tcp server &#x7684;&#x8FD0;&#x884C;&#x65B9;&#x6CD5;&#x5C55;&#x793A;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">func TCPServer(listener net.Listener, handler TCPHandler, logf lg.AppLogFunc) error {
    // ...


    var wg sync.WaitGroup


    for {
        // &#x63A5;&#x6536;&#x65B0;&#x7684; tcp &#x8BF7;&#x6C42;
        clientConn, err := listener.Accept()
        // ...
        wg.Add(1)
        go func() {
            // &#x5904;&#x7406;&#x8BF7;&#x6C42;
            handler.Handle(clientConn)
            wg.Done()
        }()
    }


    // ...
    wg.Wait()
    // ...


    return nil
}</code></pre><p>&#x9488;&#x5BF9;&#x4E8E;&#x6BCF;&#x7B14;&#x5230;&#x6765;&#x7684;&#x8FDE;&#x63A5;&#xFF0C;nsqd &#x670D;&#x52A1;&#x7AEF;&#x4F1A;&#xFF1A;</p><ul><li>&#x5C06; conn &#x5C01;&#x88C5;&#x6210;&#x4E00;&#x4E2A; client</li><li><strong>&#x8C03;&#x7528; protocolV2.IOLoop() &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x4E3A;&#x8FD9;&#x4E2A;&#x8FDE;&#x63A5;&#x63D0;&#x4F9B;&#x670D;&#x52A1;</li></ul><pre><code class="language-text">func (p *tcpServer) Handle(conn net.Conn) {
    // ...
    buf := make([]byte, 4)
    _, err := io.ReadFull(conn, buf)
    // ...
    protocolMagic := string(buf)
    // ...
    var prot protocol.Protocol
    switch protocolMagic {
    case &quot;  V2&quot;:
        prot = &amp;protocolV2{nsqd: p.nsqd}
    default:
        // ...
        return
    }


    // &#x57FA;&#x4E8E;&#x5F53;&#x524D;&#x8BF7;&#x6C42;&#x7684; conn&#xFF0C;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x65B0;&#x7684; client &#x5B9E;&#x4F8B;
    client := prot.NewClient(conn)
    p.conns.Store(conn.RemoteAddr(), client)
 
    // &#x5F53;&#x524D;&#x8BF7;&#x6C42;&#x7EF4;&#x5EA6;&#x7684;&#x5E38;&#x9A7B;&#x5904;&#x7406;&#x6D41;&#x7A0B;
    err = prot.IOLoop(client)
    // ...
    p.conns.Delete(conn.RemoteAddr())
    client.Close()
}</code></pre><p>protocolV2.IOLoop() &#x65B9;&#x6CD5;&#x662F;&#x5904;&#x7406;&#x4E00;&#x7B14;&#x5BA2;&#x6237;&#x7AEF;&#x8FDE;&#x63A5;&#x7684;&#x4E3B;&#x65B9;&#x6CD5;&#xFF0C;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x5305;&#x62EC;&#xFF1A;</p><ul><li><strong>&#x5F02;&#x6B65;&#x8FD0;&#x884C; protocolV2.messagePump(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x5728;&#x5176;&#x4E2D;&#x4F1A;&#x6301;&#x7EED;&#x8D1F;&#x8D23;&#x5C06;&#x9700;&#x8981;&#x53D1;&#x9001;&#x7684;&#x6D88;&#x606F;&#x63A8;&#x9001;&#x8BE5;&#x5BA2;&#x6237;&#x7AEF;</li><li>&#x8BFB;&#x53D6;&#x6765;&#x81EA;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x8BF7;&#x6C42;&#x6307;&#x4EE4;&#xFF0C;<strong>&#x8C03;&#x7528; protocolV2.Exec(...) &#x65B9;&#x6CD5;</strong>&#x5206;&#x7C7B;&#x5904;&#x7406;&#x6BCF;&#x4E00;&#x79CD;&#x6307;&#x4EE4;</li></ul><pre><code class="language-text">func (p *protocolV2) IOLoop(c protocol.Client) error {
    var err error
    var line []byte
    var zeroTime time.Time


    client := c.(*clientV2)


    // synchronize the startup of messagePump in order
    // to guarantee that it gets a chance to initialize
    // goroutine local state derived from client attributes
    // and avoid a potential race with IDENTIFY (where a client
    // could have changed or disabled said attributes)
    messagePumpStartedChan := make(chan bool)
    go p.messagePump(client, messagePumpStartedChan)
    &lt;-messagePumpStartedChan


    // &#x542F;&#x52A8;
    for {
        // ...
        line, err = client.Reader.ReadSlice(&apos;\n&apos;)
        // ...
        var response []byte
        response, err = p.Exec(client, params)
        // ...


        if response != nil {
            err = p.Send(client, frameTypeResponse, response)
            // ...
        }
    }


    // ...      
    close(client.ExitChan)
    if client.Channel != nil {
        client.Channel.RemoveClient(client.ID)
    }
    return err
}</code></pre><p>protocolV2.Exec(...) &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x4F1A;&#x6839;&#x636E;&#x5404;&#x7C7B;&#x6307;&#x4EE4;&#xFF0C;dispatch &#x5230;&#x5404;&#x79CD;&#x5904;&#x7406;&#x65B9;&#x6CD5;&#x5F53;&#x4E2D;. &#x672C;&#x6587;&#x91CD;&#x70B9;&#x4ECB;&#x7ECD;&#x7684;&#x6307;&#x4EE4;&#x5305;&#x62EC;&#xFF1A;</p><ul><li><strong>PUB&#xFF1A;</strong>&#x751F;&#x4EA7;&#x8005; <strong>publish &#x6D88;&#x606F;</strong>&#x7684;&#x6307;&#x4EE4;&#xFF0C;&#x672C;&#x6587; 4.3 &#x5C0F;&#x8282;&#x8BE6;&#x7EC6;&#x5C55;&#x5F00;</li><li><strong>SUB&#xFF1A;</strong>&#x6D88;&#x8D39;&#x8005; <strong>subscribe topic + channel </strong>&#x7684;&#x6307;&#x4EE4;&#xFF0C;&#x672C;&#x6587; 4.4. &#x5C0F;&#x8282;&#x8BE6;&#x7EC6;&#x5C55;&#x5F00;</li><li><strong>FIN&#xFF1A;</strong>&#x6D88;&#x8D39;&#x8005; <strong>ack &#x6D88;&#x606F;</strong>&#x7684;&#x6307;&#x4EE4;&#xFF0C;&#x672C;&#x6587; 4.5.3 &#x5C0F;&#x8282;&#x4E2D;&#x8BE6;&#x7EC6;&#x5C55;&#x5F00;</li></ul><pre><code class="language-text">func (p *protocolV2) Exec(client *clientV2, params [][]byte) ([]byte, error) {
    // ...
    switch {
    // ...
    case bytes.Equal(params[0], []byte(&quot;PUB&quot;)):
        return p.PUB(client, params)
    // ...
    case bytes.Equal(params[0], []byte(&quot;SUB&quot;)):
        return p.SUB(client, params)
    // ...
    case bytes.Equal(params[0], []byte(&quot;FIN&quot;)):
        return p.FIN(client, params)    
    }
    return nil, protocol.NewFatalClientErr(nil, &quot;E_INVALID&quot;, fmt.Sprintf(&quot;invalid command %s&quot;, params[0]))
}</code></pre><h2 id="43-publish-%E6%B5%81%E7%A8%8B">4.3 publish &#x6D41;&#x7A0B;</h2><p>&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x5C55;&#x5F00; nsqd &#x670D;&#x52A1;&#x7AEF;&#x9488;&#x5BF9; PUB &#x6307;&#x4EE4;&#x7684;&#x5904;&#x7406;&#x6D41;&#x7A0B;. &#x8FD9;&#x90E8;&#x5206;&#x5C5E;&#x4E8E;&#x672C;&#x6587;&#x4E2D;&#x7EDD;&#x5BF9;&#x6838;&#x5FC3;&#x7684;&#x5185;&#x5BB9;.</p><h3 id="431-topicchannel">4.3.1 topic -&gt; channel</h3><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-cbd4ac8d734963b2a9c2c26d7cacfb53_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5728; protocolV2.PUB(...) &#x65B9;&#x6CD5;&#x4E2D;&#xFF1A;</p><ul><li>&#x8C03;&#x7528;<strong> io.ReadFull(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x8BFB;&#x53D6;&#x6D88;&#x606F;&#x6570;&#x636E;</li><li>&#x8C03;&#x7528; <strong>NSQD.GetTopic(...) &#x65B9;&#x6CD5;</strong>&#x83B7;&#x53D6;&#x5230;&#x6D88;&#x606F;&#x6240;&#x5C5E;&#x7684; topic&#xFF08;&#x4E00;&#x6761;&#x88AB;&#x751F;&#x4EA7;&#x51FA;&#x6765;&#x7684;&#x6D88;&#x606F;&#x4F1A;&#x660E;&#x786E;&#x4ECE;&#x5C5E;&#x4E8E;&#x67D0;&#x4E00;&#x4E2A; topic&#xFF09;</li><li>&#x8C03;&#x7528; <strong>topic.PutMessage(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x5C06;&#x6D88;&#x606F;&#x63A8;&#x9001;&#x7ED9;&#x5BF9;&#x5E94;&#x7684; topic. &#x5176;&#x672C;&#x8D28;&#x4E0A;&#x4F1A;<strong>&#x901A;&#x8FC7; Topic.memoryMsgChan &#x6216; Topic.backend &#x8FDB;&#x884C;&#x6D88;&#x606F;&#x4F20;&#x9012;</strong>&#xFF0C;&#x8BA9; topic &#x7684;&#x5E38;&#x9A7B;&#x8FD0;&#x884C; <strong>goroutine Topic.messagePump(...) &#x65B9;&#x6CD5;&#x63A5;&#x6536;&#x5230;&#x8FD9;&#x6761;&#x6D88;&#x606F;</strong></li></ul><pre><code class="language-text">func (p *protocolV2) PUB(client *clientV2, params [][]byte) ([]byte, error) {
    var err error


    // ...
    topicName := string(params[1])
    // ...


    bodyLen, err := readLen(client.Reader, client.lenSlice)
    // ...
    messageBody := make([]byte, bodyLen)
    _, err = io.ReadFull(client.Reader, messageBody)
    // ...


    topic := p.nsqd.GetTopic(topicName)
    msg := NewMessage(topic.GenerateID(), messageBody)
    err = topic.PutMessage(msg)
    // ...


    client.PublishedMessage(topicName, 1)


    return okBytes, nil
}
// PutMessage writes a Message to the queue
func (t *Topic) PutMessage(m *Message) error {
    t.RLock()
    defer t.RUnlock()
    // ...
    err := t.put(m)
    // ...
    return nil
}</code></pre><p>nsqd &#x670D;&#x52A1;&#x7AEF;&#x5904;&#x7406; sub &#x6307;&#x4EE4;&#x6D41;&#x7A0B;&#xFF1A;</p><pre><code class="language-text">func (t *Topic) put(m *Message) error {
    // ...
    if cap(t.memoryMsgChan) &gt; 0 || t.ephemeral || m.deferred != 0 {
        select {
        // &#x5199;&#x5230;&#x5185;&#x5B58;&#x4E2D;
        case t.memoryMsgChan &lt;- m:
            return nil
        // &#x5185;&#x5B58; chan &#x5DF2;&#x6EE1;&#xFF0C;&#x5219;&#x5199;&#x5165;&#x5230;&#x78C1;&#x76D8;
        default:
            break // write to backend
        }
    }
    err := writeMessageToBackend(m, t.backend)
    // ...
    return nil
}</code></pre><p>&#x63A5;&#x4E0B;&#x6765;&#x6211;&#x4EEC;&#x518D;&#x89C2;&#x5BDF;&#x4E00;&#x4E0B; <strong>Topic.messagePump() &#x65B9;&#x6CD5;</strong>. &#x5176;&#x4E2D;&#x5728;&#x8BFB;&#x53D6;&#x5230;&#x65B0;&#x6D88;&#x606F;&#x540E;&#xFF0C;&#x4F1A;<strong>&#x904D;&#x5386;&#x5F53;&#x524D; topic &#x4E0B;&#x7684; channel&#xFF0C;&#x9010;&#x4E00;&#x8C03;&#x7528; Channel.PutMessage(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x5C06;&#x6D88;&#x606F;&#x4F20;&#x9012;&#x5230;&#x6BCF;&#x4E2A; channel &#x4E2D;.</p><pre><code class="language-text">func (t *Topic) messagePump() {
    // ...
    for {
        select {
        case msg = &lt;-memoryMsgChan:
        case buf = &lt;-backendChan:
            msg, err = decodeMessage(buf)
            // ...
        // ...
        }


        for i, channel := range chans {
            chanMsg := msg
            // ...            
            // &#x5EF6;&#x8FDF;&#x6D88;&#x606F;&#x7279;&#x6B8A;&#x5904;&#x7406;
            if chanMsg.deferred != 0 {
                channel.PutMessageDeferred(chanMsg, chanMsg.deferred)
                continue
            }
            err := channel.PutMessage(chanMsg)
            // ...
        }
    }
// ...
}</code></pre><p>&#x5728; <strong>Channel.PutMessage(...) &#x65B9;&#x6CD5;</strong>&#x4E2D;&#xFF0C;&#x4F1A;&#x5C06;&#x6D88;&#x606F;<strong>&#x901A;&#x8FC7; Channel.memoryMsgChan &#x6216;&#x8005; Channel.backend</strong>&#xFF0C;&#x5C06;&#x6D88;&#x606F;<strong>&#x968F;&#x673A;&#x4F20;&#x9012;</strong>&#x5230;&#x67D0;&#x4E2A;<strong>&#x8BA2;&#x9605;&#x4E86;&#x8BE5; channel &#x7684; consumer client</strong> &#x5BF9;&#x5E94;&#x7684; <strong>protocolV2.messagePump(...) goroutine</strong> &#x5F53;&#x4E2D;.</p><p>&#x6B64;&#x5904;&#x547C;&#x5E94;&#x4E86; 4.2.2 &#x5C0F;&#x8282;&#xFF0C;&#x8BE5;&#x65B9;&#x6CD5;&#x4F1A;&#x4E8E; 4.3.2 &#x5C0F;&#x8282;&#x8BE6;&#x7EC6;&#x5C55;&#x5F00;.</p><pre><code class="language-text">func (c *Channel) PutMessage(m *Message) error {
    c.exitMutex.RLock()
    defer c.exitMutex.RUnlock()
    // ...
    err := c.put(m)
    // ...
    atomic.AddUint64(&amp;c.messageCount, 1)
    return nil
}
func (c *Channel) put(m *Message) error {
    select {
    case c.memoryMsgChan &lt;- m:
    default:
        err := writeMessageToBackend(m, c.backend)
        c.nsqd.SetHealth(err)
        // ...
    }
    return nil
}</code></pre><h3 id="432-channelconsumer">4.3.2 channel -&gt; consumer</h3><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-76c5ab3ae37a77adf40c7c52a4eb043b_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x5F53;&#x4E00;&#x6761;&#x6D88;&#x606F;&#x4ECE; topic &#x88AB;&#x4E00;&#x4E00;&#x63A8;&#x9001;&#x5230;&#x6BCF;&#x4E2A; channel &#x7684; memoryMsgChan &#x548C; backendChan &#x4E2D;&#x65F6;&#xFF0C;&#x8FD9;&#x7B14;&#x6570;&#x636E;&#x4F1A;&#x968F;&#x673A;&#x88AB;&#x4E00;&#x4E2A;&#x8BA2;&#x9605;&#x4E86;&#x8BE5; channel &#x7684; consumer &#x6D88;&#x8D39;.</p><p>&#x8FD9;&#x79CD;<strong>&#x968F;&#x673A;&#x4E0E;&#x4E92;&#x65A5;&#x7684;&#x6027;&#x8D28;</strong>&#x5F97;&#x4EE5;&#x5B9E;&#x73B0;&#x7684;&#x539F;&#x56E0;&#x662F;&#xFF0C;&#x662F;<strong>&#x591A;&#x4E2A; consumer &#x7ADE;&#x4E89;&#x6D88;&#x8D39;&#x540C;&#x4E00;&#x4E2A; memoryMsgChan &#x548C; backendChan &#x4E2D;&#x7684;&#x6570;&#x636E;</strong>&#xFF0C;&#x56E0;&#x6B64;&#x540C;&#x4E00;&#x6761;&#x6570;&#x636E;&#x4E00;&#x5B9A;&#x53EA;&#x80FD;&#x88AB;&#x4E00;&#x4E2A; consumer client &#x6240;&#x83B7;&#x53D6;&#x5230;.</p><p>consumer &#x6D88;&#x8D39; channel &#x6570;&#x636E;&#x7684;&#x5185;&#x5BB9;&#x53EF;&#x4EE5;&#x53C2;&#x89C1;<strong>&#x65B9;&#x6CD5; protocolV2.messagePump()</strong>&#xFF0C;&#x8BE5;&#x65B9;&#x6CD5;&#x662F;<strong>&#x4E0E;&#x6BCF;&#x4E00;&#x4E2A;&#x8FDE;&#x63A5; nsqd &#x670D;&#x52A1;&#x7AEF;&#x7684;&#x5BA2;&#x6237;&#x7AEF;&#x8FDE;&#x63A5;&#x4E00;&#x4E00;&#x5BF9;&#x5E94;</strong>&#x7684;.</p><p>&#x503C;&#x5F97;&#x4E00;&#x63D0;&#x7684;&#x662F;&#xFF0C;<strong>&#x53EA;&#x6709;&#x67D0;&#x4E2A; client &#x6267;&#x884C;&#x4E86;&#x8BA2;&#x9605; channel &#x7684;&#x6307;&#x4EE4;&#xFF0C;&#x6B64;&#x65F6;&#x624D;&#x80FD;&#x4ECE; client.SubEventChan &#x4E0B;&#x63A5;&#x6536;&#x5230;&#x8BE5; channel &#x5BF9;&#x5E94;&#x7684; subChannel&#xFF0C;&#x5E76;&#x8FDB;&#x4E00;&#x6B65;&#x83B7;&#x5F97;&#x8BE5; channel &#x7684; memoryMsgChan &#x548C; backendChan</strong>. &#x8FD9;&#x90E8;&#x5206;&#x4F1A;&#x4E0E; 3.4 &#x5C0F;&#x8282;&#x7684;&#x5185;&#x5BB9;&#x5F62;&#x6210;&#x547C;&#x5E94;.</p><pre><code class="language-text">func (p *protocolV2) messagePump(client *clientV2, startedChan chan bool) {
    var err error
    var memoryMsgChan chan *Message
    var backendMsgChan &lt;-chan []byte
    var subChannel *Channel
    // ...
    // &#x5F53;&#x524D; client &#x7528;&#x4E8E;&#x63A5;&#x6536; subChannel &#x7684;&#x901A;&#x9053;
    subEventChan := client.SubEventChan
    // ...  


    for {
       
        // ...
        // &#x5018;&#x82E5;&#x5F53;&#x524D; client &#x6267;&#x884C; sub &#x6307;&#x4EE4;&#xFF0C;&#x6B21;&#x6570;&#x83B7;&#x53D6;&#x5230;&#x8BA2;&#x9605; channel &#x4E0B;&#x7528;&#x4E8E;&#x4F20;&#x9012;&#x6D88;&#x606F;&#x7684; memoryMsgChan
        memoryMsgChan = subChannel.memoryMsgChan
        backendMsgChan = subChannel.backend.ReadChan()
        flusherChan = outputBufferTicker.C
        
        // ...
        select {
        // ...      
        // &#x9996;&#x5148;&#xFF0C;&#x5018;&#x82E5;&#x5F53;&#x524D; client &#x6267;&#x884C;&#x7684;&#x662F; sub &#x6307;&#x4EE4;&#xFF0C;&#x5219;&#x6B64;&#x5904;&#x4F1A;&#x83B7;&#x53D6;&#x5230;&#x8BE5;&#x5BA2;&#x6237;&#x7AEF;&#x8BA2;&#x9605;&#x7684; channel
        // &#x5018;&#x82E5; client &#x53D1;&#x9001;&#x7684;&#x6307;&#x4EE4;&#x662F; SUB&#xFF0C;&#x5219;&#x5176;&#x8BA2;&#x9605;&#x7684; channel &#x4F1A;&#x901A;&#x8FC7; subEventChan &#x53D1;&#x9001;&#x8FC7;&#x6765;
        case subChannel = &lt;-subEventChan:
            // you can&apos;t SUB anymore
            subEventChan = nil
        // ...
        // &#x5C1D;&#x8BD5;&#x63A5;&#x6536;&#x8BA2;&#x9605; channel &#x4E0B;&#x7684; backendMsgChan
        case b := &lt;-backendMsgChan:
            // ...
            msg, err := decodeMessage(b)
            // ...
            // &#x53D1;&#x9001;&#x6D88;&#x606F;&#x524D;&#xFF0C;&#x5148;&#x5C06;&#x6D88;&#x606F;&#x6DFB;&#x52A0;&#x5230;&#x5F85; ack &#x786E;&#x8BA4;&#x961F;&#x5217;&#x4E2D;
            subChannel.StartInFlightTimeout(msg, client.ID, msgTimeout)
            client.SendingMessage()
            // &#x5C06;&#x6D88;&#x606F;&#x53D1;&#x9001;&#x5230; client
            err = p.SendMessage(client, msg)
            // ...
        // &#x5C1D;&#x8BD5;&#x63A5;&#x6536;&#x8BA2;&#x9605; channel &#x4E0B;&#x7684; memoryMsgChan
        case msg := &lt;-memoryMsgChan:
            // ...
            // &#x53D1;&#x9001;&#x6D88;&#x606F;&#x524D;&#xFF0C;&#x5148;&#x5C06;&#x6D88;&#x606F;&#x6DFB;&#x52A0;&#x5230;&#x5F85; ack &#x786E;&#x8BA4;&#x961F;&#x5217;&#x4E2D;
            subChannel.StartInFlightTimeout(msg, client.ID, msgTimeout)
            client.SendingMessage()
            // &#x5C06;&#x6D88;&#x606F;&#x53D1;&#x9001;&#x5230; client
            err = p.SendMessage(client, msg)
            // ...
        }
    }


    // ...
}</code></pre><p>&#x5411;&#x5BA2;&#x6237;&#x7AEF;&#x53D1;&#x9001;&#x6D88;&#x606F;&#x7684;&#x65B9;&#x6CD5;&#x94FE;&#x8DEF;&#x5C55;&#x793A;&#x5982;&#x4E0B;&#xFF0C;&#x6838;&#x5FC3;&#x662F;<strong>&#x83B7;&#x53D6; client &#x4E2D;&#x7684; tcp &#x8FDE;&#x63A5;</strong>&#xFF0C;&#x7136;&#x540E;<strong>&#x5411; io writer &#x4E2D;&#x5199;&#x5165;&#x6570;&#x636E;&#x53D1;&#x5F80;&#x5BA2;&#x6237;&#x7AEF;</strong>&#xFF1A;</p><pre><code class="language-text">func (p *protocolV2) SendMessage(client *clientV2, msg *Message) error {
    // ...
    buf := bufferPoolGet()
    defer bufferPoolPut(buf)


    _, err := msg.WriteTo(buf)
    // ...


    err = p.Send(client, frameTypeMessage, buf.Bytes())
    // ...
}
func (p *protocolV2) Send(client *clientV2, frameType int32, data []byte) error {
    // ...
    _, err := protocol.SendFramedResponse(client.Writer, frameType, data)
    // ...
}
func SendFramedResponse(w io.Writer, frameType int32, data []byte) (int, error) {
    // ...
    n, err = w.Write(data)
    // ...
}</code></pre><h2 id="44-subscribe-%E6%B5%81%E7%A8%8B">4.4 subscribe &#x6D41;&#x7A0B;</h2><p>&#x63A5;&#x4E0B;&#x6765;&#x6211;&#x4EEC;&#x4E00;&#x8D77;&#x68B3;&#x7406;&#x4E0B; consumer &#x5411; nsqd &#x670D;&#x52A1;&#x7AEF;&#x53D1;&#x8D77; subscribe &#x6307;&#x4EE4;&#x7684;&#x6D41;&#x7A0B;.</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-35bf2c6d677c1493c444545359681a0c_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><h3 id="441-sub-%E4%B8%BB%E6%B5%81%E7%A8%8B">4.4.1 sub &#x4E3B;&#x6D41;&#x7A0B;</h3><p>&#x5904;&#x7406; SUB &#x6307;&#x4EE4;&#x7684;&#x5165;&#x53E3;&#x65B9;&#x6CD5;&#x4E3A; protocolV2.SUB(...)&#xFF0C;&#x5176;&#x6838;&#x5FC3;&#x6B65;&#x9AA4;&#x662F;&#xFF1A;</p><ul><li>&#x5728;&#x8BA2;&#x9605; <strong>channel &#x7684; client &#x96C6;&#x5408;&#x4E2D;&#x6DFB;&#x52A0;&#x5F53;&#x524D; client</strong></li><li>&#x5C06;&#x8BA2;&#x9605;&#x7684; <strong>channel &#x53D1;&#x9001;&#x5230;&#x5F53;&#x524D; client &#x7684; SubEventChan</strong> &#x4E2D;&#xFF0C;<strong>&#x4F9B; protocolV2.messagePump() goroutine &#x63A5;&#x6536;&#x548C;&#x5904;&#x7406;</strong></li></ul><pre><code class="language-text">func (p *protocolV2) SUB(client *clientV2, params [][]byte) ([]byte, error) {
    // ...
    topicName := string(params[1])
    // ...


    channelName := string(params[2])
    // ...
    var channel *Channel
    for i := 1; ; i++ {
        topic := p.nsqd.GetTopic(topicName)
        channel = topic.GetChannel(channelName)
        if err := channel.AddClient(client.ID, client); err != nil {
            // ...
        }


        // ...
        break
    }
    atomic.StoreInt32(&amp;client.State, stateSubscribed)
    client.Channel = channel
    // update message pump
    client.SubEventChan &lt;- channel


    return okBytes, nil
}</code></pre><p>&#x5728; 1.2 &#x5C0F;&#x8282;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x6709;&#x63D0;&#x5230;&#xFF0C;channel &#x662F;&#x5728;&#x9996;&#x6B21;&#x88AB; consumer &#x8BA2;&#x9605;&#x65F6;&#x81EA;&#x52A8;&#x521B;&#x5EFA;&#x7684;&#xFF0C;&#x8BE5;&#x6D41;&#x7A0B;&#x5BF9;&#x5E94;&#x7684;&#x65B9;&#x6CD5;&#x94FE;&#x8DEF;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">func (t *Topic) GetChannel(channelName string) *Channel {
    t.Lock()
    channel, isNew := t.getOrCreateChannel(channelName)
    t.Unlock()
    // ...
    return channel
}
// this expects the caller to handle locking
func (t *Topic) getOrCreateChannel(channelName string) (*Channel, bool) {
    channel, ok := t.channelMap[channelName]
    if !ok {
        // ...
        channel = NewChannel(t.name, channelName, t.nsqd, deleteCallback)
        t.channelMap[channelName] = channel
        // ...
        return channel, true
    }
    return channel, false
}</code></pre><h3 id="442-pump-%E5%8D%8F%E7%A8%8B%E6%8E%A5%E6%94%B6-chan">4.4.2 pump &#x534F;&#x7A0B;&#x63A5;&#x6536; chan</h3><p><strong>&#x5BF9;&#x5E94;&#x4E8E;&#x6BCF;&#x4E2A; consumer client &#x4F1A;&#x6709;&#x4E00;&#x4E2A;&#x8FD0;&#x884C; protocolV2.messagePump(...) &#x65B9;&#x6CD5;&#x7684; goroutine</strong>&#xFF0C;&#x5176;&#x4E2D;&#x4F1A;<strong>&#x901A;&#x8FC7; client.SubEventChan &#x63A5;&#x6536;&#x5230;&#x8BA2;&#x9605;&#x7684; channel</strong>&#xFF0C;&#x7136;&#x540E;&#x4ECE;&#x5BF9;&#x5E94;&#x7684; memoryMsgChan &#x548C; backendChan &#x4E2D;&#x63A5;&#x6536;&#x6D88;&#x606F;&#xFF1A;</p><pre><code class="language-text">func (p *protocolV2) messagePump(client *clientV2, startedChan chan bool) {
    var err error
    var memoryMsgChan chan *Message
    var backendMsgChan &lt;-chan []byte
    var subChannel *Channel
    // ...
    subEventChan := client.SubEventChan
    // ...  


    for {
       
        // ...
        // &#x5018;&#x82E5;&#x5F53;&#x524D; client &#x6267;&#x884C; sub &#x6307;&#x4EE4;&#xFF0C;&#x6B21;&#x6570;&#x83B7;&#x53D6;&#x5230;&#x8BA2;&#x9605; channel &#x4E0B;&#x7528;&#x4E8E;&#x4F20;&#x9012;&#x6D88;&#x606F;&#x7684; memoryMsgChan
        memoryMsgChan = subChannel.memoryMsgChan
        backendMsgChan = subChannel.backend.ReadChan()
        flusherChan = outputBufferTicker.C
        
        // ...
        select {        
        case subChannel = &lt;-subEventChan:
            // you can&apos;t SUB anymore
            subEventChan = nil
        // ...         
        }
    }
    // ...
}</code></pre><h2 id="45-inflightack-%E6%9C%BA%E5%88%B6">4.5 inFlight&amp;ack &#x673A;&#x5236;</h2><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-aa5d6de559b75bd19ff485bc48722a45_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x634B;&#x4E00;&#x4E0B;&#xFF0C;nsq &#x4E3A;<strong>&#x4FDD;&#x8BC1;&#x6D88;&#x606F;&#x4E0D;&#x4E22;&#x5931;&#x800C;&#x63D0;&#x4F9B;&#x7684; inFlight &#x548C; ack &#x673A;&#x5236;</strong>.</p><h3 id="451-startinflight">4.5.1 StartInFlight</h3><p>&#x5728; protocolV2.messagePump(...) &#x65B9;&#x6CD5;&#x4E2D;&#xFF0C;&#x6BCF;&#x5F53;&#x4ECE; channel &#x4E2D;&#x63A5;&#x6536;&#x5230;&#x6D88;&#x606F;&#x8981;&#x53D1;&#x5F80;&#x5BA2;&#x6237;&#x7AEF;&#x4E4B;&#x524D;&#xFF0C;&#x90FD;&#x4F1A;&#x5148;<strong>&#x8C03;&#x7528; Channel.StartInFlightTimeout(...) &#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x6D88;&#x606F;&#x6DFB;&#x52A0;&#x5230;&#x5F85; ack &#x786E;&#x8BA4;&#x961F;&#x5217; inFlightPQ </strong>&#x5F53;&#x4E2D;&#xFF1A;</p><pre><code class="language-text">func (p *protocolV2) messagePump(client *clientV2, startedChan chan bool) {
    // ...
    for {
        // ...
        select {
        // ...
        case b := &lt;-backendMsgChan:
            // ...
            subChannel.StartInFlightTimeout(msg, client.ID, msgTimeout)
            // ...
            err = p.SendMessage(client, msg)
            // ...
        case msg := &lt;-memoryMsgChan:
            // ...
            subChannel.StartInFlightTimeout(msg, client.ID, msgTimeout)
            // ...
            err = p.SendMessage(client, msg)
            // ...
        }
    }
    // ...
}</code></pre><p>&#x6DFB;&#x52A0;&#x6D88;&#x606F;&#x8FDB;&#x5165; inFlightPQ &#x524D;&#xFF0C;&#x4F1A;&#x6839;&#x636E;&#x7528;&#x6237;&#x8BBE;&#x7F6E;&#x7684;&#x8D85;&#x65F6;&#x91CD;&#x8BD5;&#x65F6;&#x95F4;&#xFF0C;<strong>&#x63A8;&#x7B97;&#x51FA;&#x6D88;&#x606F;&#x91CD;&#x8BD5;&#x7684;&#x6267;&#x884C;&#x65F6;&#x95F4;&#xFF0C;&#x4EE5;&#x65F6;&#x95F4;&#x6233;&#x4F5C;&#x4E3A;&#x6392;&#x5E8F;&#x7684;&#x952E;&#xFF0C;&#x5C06;&#x6D88;&#x606F;&#x6DFB;&#x52A0;&#x8FDB;&#x5165;&#x5C0F;&#x9876;&#x5806;</strong>&#x4E2D;.</p><pre><code class="language-text">func (c *Channel) StartInFlightTimeout(msg *Message, clientID int64, timeout time.Duration) error {
    now := time.Now()
    msg.clientID = clientID
    msg.deliveryTS = now
    msg.pri = now.Add(timeout).UnixNano()
    err := c.pushInFlightMessage(msg)
    if err != nil {
        return err
    }
    c.addToInFlightPQ(msg)
    return nil
}
func (c *Channel) addToInFlightPQ(msg *Message) {
    c.inFlightMutex.Lock()
    c.inFlightPQ.Push(msg)
    c.inFlightMutex.Unlock()
}</code></pre><h3 id="452-queuescan">4.5.2 queueScan</h3><p>&#x5728; nsqd &#x8282;&#x70B9;&#x542F;&#x52A8;&#x65F6;&#xFF0C;&#x4F1A;<strong>&#x5F02;&#x6B65;&#x542F;&#x52A8;&#x4E00;&#x4E2A; gorouting &#x6267;&#x884C; NSQD.queueScanLoop() &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x8BE5;&#x65B9;&#x6CD5;&#x7684;&#x7528;&#x9014;&#x5C31;&#x662F;<strong>&#x5B9A;&#x65F6;&#x8F6E;&#x8BE2; inFlightPQ &#x548C; deferredPQ&#xFF0C;&#x53D6;&#x51FA;&#x5176;&#x4E2D;&#x8FBE;&#x5230;&#x65F6;&#x95F4;&#x6761;&#x4EF6;&#x7684;&#x6D88;&#x606F;&#x8FDB;&#x884C;&#x6267;&#x884C;</strong>&#xFF1A;</p><pre><code class="language-text">func (n *NSQD) Main() error {
    // ...
    n.waitGroup.Wrap(n.queueScanLoop)
    // ...
}
func (n *NSQD) queueScanLoop() {
    workCh := make(chan *Channel, n.getOpts().QueueScanSelectionCount)
    // ...
    // &#x8F6E;&#x8BE2;&#x65F6;&#x95F4;&#x95F4;&#x9694;
    workTicker := time.NewTicker(n.getOpts().QueueScanInterval)
    // ...
    refreshTicker := time.NewTicker(n.getOpts().QueueScanRefreshInterval)


    channels := n.channels()
    // &#x5728;&#x65B9;&#x6CD5;&#x4E2D;&#x4F1A;&#x542F;&#x52A8; scan worker goroutine
    n.resizePool(len(channels), workCh, responseCh, closeCh)
    // ...
    for {
        select {
        case &lt;-workTicker.C:
            // ...
        // ...
        }


        num := n.getOpts().QueueScanSelectionCount
        if num &gt; len(channels) {
            num = len(channels)
        }


        // ...
        // &#x5C06;&#x9700;&#x8981;&#x626B;&#x63CF;&#x7684; channel &#x901A;&#x8FC7; workCh &#x53D1;&#x7ED9; scan worker goroutine
        for _, i := range util.UniqRands(num, len(channels)) {
            workCh &lt;- channels[i]
        }


         // ...
    }   
}
func (n *NSQD) resizePool(num int, workCh chan *Channel, responseCh chan bool, closeCh chan int) {
    // ...
    for {
        // ...
        n.waitGroup.Wrap(func() {
            n.queueScanWorker(workCh, responseCh, closeCh)
        })
        n.poolSize++      
    }
}</code></pre><p>queueScanWorker &#x662F; nsqd &#x8282;&#x70B9;&#x4E0B;&#x5F02;&#x6B65;&#x8FD0;&#x884C;&#x7684; goroutine&#xFF0C;&#x6BCF;&#x5F53;<strong>&#x901A;&#x8FC7; workCh &#x63A5;&#x6536;&#x5230; channel &#x65F6;&#xFF0C;&#x4F1A;&#x8C03;&#x7528; Channel.processInFlightQueue(...) &#x65B9;&#x6CD5;</strong>&#xFF0C;&#x5B8C;&#x6210;&#x626B;&#x63CF;&#x4EFB;&#x52A1;&#xFF1A;</p><pre><code class="language-text">func (n *NSQD) queueScanWorker(workCh chan *Channel, responseCh chan bool, closeCh chan int) {
    for {
        select {
        case c := &lt;-workCh:
            now := time.Now().UnixNano()
            dirty := false
            if c.processInFlightQueue(now) {
                dirty = true
            }
            // ...
            responseCh &lt;- dirty
        // ...
        }
    }
}</code></pre><p>&#x5728;&#x626B;&#x63CF;&#x4EFB;&#x52A1;&#x4E2D;&#xFF0C;&#x6BCF;&#x6B21;&#x4F1A;&#x5C1D;&#x8BD5;<strong>&#x4ECE; inFlightPQ &#x5806;&#x9876;&#x5F39;&#x51FA;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x7684;&#x6D88;&#x606F;</strong>&#xFF0C;&#x7136;&#x540E;<strong>&#x8C03;&#x7528; Channel.put(...) &#x65B9;&#x6CD5;</strong>&#x5C06;&#x6D88;&#x606F;&#x4F20;&#x9012;&#x5230;&#x67D0;&#x4E2A;&#x8BA2;&#x9605;&#x4E86;&#x8BE5; channel &#x7684; client &#x624B;&#x4E2D;&#xFF1A;</p><pre><code class="language-text">func (c *Channel) processInFlightQueue(t int64) bool {
    c.exitMutex.RLock()
    defer c.exitMutex.RUnlock()


    if c.Exiting() {
        return false
    }


    dirty := false
    for {
        c.inFlightMutex.Lock()
        // &#x5018;&#x82E5;&#x5806;&#x9876;&#x7684;&#x6D88;&#x606F;&#x5DF2;&#x7ECF;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x65F6;&#x95F4;&#xFF0C;&#x5219;&#x5F39;&#x51FA;&#x5BF9;&#x5E94;&#x7684;&#x6D88;&#x606F;
        msg, _ := c.inFlightPQ.PeekAndShift(t)
        c.inFlightMutex.Unlock()


        // &#x5018;&#x82E5;&#x5806;&#x9876;&#x6D88;&#x606F;&#x672A;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x65F6;&#x95F4;&#xFF0C;&#x5219;&#x7ED3;&#x675F;&#x672C;&#x6B21;&#x4EFB;&#x52A1;
        if msg == nil {
            goto exit
        }
        dirty = true


        _, err := c.popInFlightMessage(msg.clientID, msg.ID)
        if err != nil {
            goto exit
        }
        atomic.AddUint64(&amp;c.timeoutCount, 1)
        c.RLock()
        client, ok := c.clients[msg.clientID]
        c.RUnlock()
        if ok {
            client.TimedOutMessage()
        }
        // &#x53D1;&#x9001;&#x91CD;&#x8BD5;&#x6D88;&#x606F;
        c.put(msg)
    }


exit:
    return dirty
}</code></pre><h3 id="453-ack">4.5.3 ack</h3><p>&#x5018;&#x82E5;&#x67D0;&#x6761;&#x6D88;&#x606F;&#x5DF2;&#x7ECF;&#x5F97;&#x5230;&#x4E86; consumer &#x7684; ack&#xFF0C;&#x5219; nsqd &#x670D;&#x52A1;&#x7AEF;&#x4F1A;<strong>&#x63A5;&#x6536;&#x5230;&#x6765;&#x81EA; consumer &#x53D1;&#x9001;&#x7684; FIN &#x6307;&#x4EE4;</strong>&#xFF0C;&#x7136;&#x540E;&#x6B65;&#x5165;&#x5230; <strong>protocolV2.FIN(...) &#x65B9;&#x6CD5;</strong>&#x5F53;&#x4E2D;&#xFF1A;</p><pre><code class="language-text">func (p *protocolV2) Exec(client *clientV2, params [][]byte) ([]byte, error) {
    // ...
    switch {
    case bytes.Equal(params[0], []byte(&quot;FIN&quot;)):
        return p.FIN(client, params)
    // ...
    }
    // ...
}</code></pre><p>&#x5728; <strong>protocolV2.FIN(...) &#x65B9;&#x6CD5;</strong>&#x4E2D;&#xFF0C;&#x4F1A;&#x83B7;&#x53D6;&#x5230;&#x6D88;&#x606F;&#x7684;&#x552F;&#x4E00; id&#xFF0C;&#x7136;&#x540E;<strong>&#x8C03;&#x7528; Channel.FinishMessage(...) &#x65B9;&#x6CD5;&#xFF0C;&#x5C06;&#x6D88;&#x606F;&#x4ECE; channel &#x7684; inFlightPQ &#x5F53;&#x4E2D;&#x79FB;&#x9664;</strong>&#xFF1A;</p><pre><code class="language-text">func (p *protocolV2) FIN(client *clientV2, params [][]byte) ([]byte, error) {
    // ...
    id, err := getMessageID(params[1])
    // ...
    err = client.Channel.FinishMessage(client.ID, *id)
    // ...
    client.FinishedMessage()


    return nil, nil
}
// FinishMessage successfully discards an in-flight message
func (c *Channel) FinishMessage(clientID int64, id MessageID) error {
    msg, err := c.popInFlightMessage(clientID, id)
    // ...
    c.removeFromInFlightPQ(msg)
    // ...
}
func (c *Channel) removeFromInFlightPQ(msg *Message) {
    c.inFlightMutex.Lock()
    // ...
    c.inFlightPQ.Remove(msg.index)
    c.inFlightMutex.Unlock()
}</code></pre><h2 id="46-deferred-%E6%9C%BA%E5%88%B6">4.6 deferred &#x673A;&#x5236;</h2><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-00883a0d84dc1bc8329358c120b0d929_720w.webp" class="kg-image" alt loading="lazy"></figure><p><br></p><p>&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x68B3;&#x7406;&#x4E00;&#x4E0B; nsq &#x5B9E;&#x73B0;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x7684;&#x6D41;&#x7A0B;.</p><h3 id="461-%E6%B7%BB%E5%8A%A0%E5%BB%B6%E6%97%B6%E9%98%9F%E5%88%97">4.6.1 &#x6DFB;&#x52A0;&#x5EF6;&#x65F6;&#x961F;&#x5217;</h3><p>&#x9996;&#x5148;&#x5728; publish &#x6D41;&#x7A0B;&#x4E2D;&#xFF0C;<strong>&#x6D88;&#x606F;&#x7531; topic &#x53D1;&#x653E;&#x6BCF;&#x4E2A; channel &#x524D;</strong>&#xFF0C;&#x4F1A;&#x5148;&#x5224;&#x65AD;&#x6D88;&#x606F;&#x662F;&#x5426;&#x4E3A;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#x7C7B;&#x578B;. <strong>&#x5018;&#x82E5;&#x4E3A;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#xFF0C;&#x5219;&#x4F1A;&#x8C03;&#x7528; Channel.PutMessageDeferred(...) &#x65B9;&#x6CD5;</strong>&#x8FFD;&#x52A0;&#x5230;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#x5F53;&#x4E2D;.</p><pre><code class="language-text">func (t *Topic) messagePump() {
    // ...
    for {
        select {
        case msg = &lt;-memoryMsgChan:
        case buf = &lt;-backendChan:
            msg, err = decodeMessage(buf)
            // ...
        // ...
        }


        for i, channel := range chans {
            chanMsg := msg
            // ...          
            // &#x5EF6;&#x8FDF;&#x6D88;&#x606F;&#x7279;&#x6B8A;&#x5904;&#x7406;
            if chanMsg.deferred != 0 {
                channel.PutMessageDeferred(chanMsg, chanMsg.deferred)
                continue
            }
            // ...
        }
    }
    // ...
}</code></pre><p>&#x6DFB;&#x52A0;&#x6D88;&#x606F;&#x8FDB;&#x5165;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#x7684;&#x65B9;&#x6CD5;&#x94FE;&#x8DEF;&#x5982;&#x4E0B;&#xFF0C;&#x5176;&#x4E2D;&#x4E3B;&#x8981;&#x662F;<strong>&#x901A;&#x8FC7;&#x5F53;&#x524D;&#x65F6;&#x523B;&#x7ED3;&#x5408;&#x5EF6;&#x65F6;&#x8BBE;&#x7F6E;&#xFF0C;&#x63A8;&#x7B97;&#x51FA;&#x6D88;&#x606F;&#x7684;&#x6267;&#x884C;&#x65F6;&#x523B;&#xFF0C;&#x7136;&#x540E;&#x4EE5;&#x8BE5;&#x65F6;&#x95F4;&#x6233;&#x4E3A;&#x6392;&#x5E8F;&#x952E;&#xFF0C;&#x5C06;&#x6D88;&#x606F;&#x6DFB;&#x52A0;&#x5230; deferredPQ &#x7684;&#x5C0F;&#x9876;&#x5806;</strong>&#x4E2D;.</p><pre><code class="language-text">func (c *Channel) PutMessageDeferred(msg *Message, timeout time.Duration) {
    atomic.AddUint64(&amp;c.messageCount, 1)
    c.StartDeferredTimeout(msg, timeout)
}
func (c *Channel) StartDeferredTimeout(msg *Message, timeout time.Duration) error {
    absTs := time.Now().Add(timeout).UnixNano()
    item := &amp;pqueue.Item{Value: msg, Priority: absTs}
    err := c.pushDeferredMessage(item)
    // ...
    c.addToDeferredPQ(item)
    return nil
}
func (c *Channel) pushDeferredMessage(item *pqueue.Item) error {
    c.deferredMutex.Lock()
    // TODO: these map lookups are costly
    id := item.Value.(*Message).ID
    _, ok := c.deferredMessages[id]
    if ok {
        c.deferredMutex.Unlock()
        return errors.New(&quot;ID already deferred&quot;)
    }
    c.deferredMessages[id] = item
    c.deferredMutex.Unlock()
    return nil
}
func (c *Channel) addToDeferredPQ(item *pqueue.Item) {
    c.deferredMutex.Lock()
    heap.Push(&amp;c.deferredPQ, item)
    c.deferredMutex.Unlock()
}</code></pre><h3 id="462-%E5%A4%84%E7%90%86%E5%BB%B6%E6%97%B6%E4%BB%BB%E5%8A%A1">4.6.2 &#x5904;&#x7406;&#x5EF6;&#x65F6;&#x4EFB;&#x52A1;</h3><p>&#x626B;&#x63CF;&#x6267;&#x884C;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#x7684;&#x6D41;&#x7A0B;&#x4E0E; 4.5.2 &#x5C0F;&#x8282;&#x4ECB;&#x7ECD;&#x7684;&#x5904;&#x7406;&#x5F85;&#x786E;&#x8BA4;&#x6D88;&#x606F;&#x7684;&#x6D41;&#x7A0B;&#x7C7B;&#x4F3C;&#xFF0C;&#x90FD;&#x662F;<strong>&#x4EE5; NSQD.queueScanWorker(...) &#x65B9;&#x6CD5;&#x4E3A;&#x5165;&#x53E3;</strong>&#xFF0C;&#x5B9A;&#x65F6;&#x8F6E;&#x8BE2;&#x5EF6;&#x65F6;&#x961F;&#x5217;&#xFF0C;<strong>&#x627E;&#x5230;&#x6EE1;&#x8DB3;&#x65F6;&#x95F4;&#x6761;&#x4EF6;&#x7684;&#x6D88;&#x606F;&#xFF0C;&#x8C03;&#x7528; Channel.put(...) &#x65B9;&#x6CD5;</strong>&#x53D1;&#x9001;&#x6D88;&#x606F;.</p><pre><code class="language-text">func (n *NSQD) queueScanWorker(workCh chan *Channel, responseCh chan bool, closeCh chan int) {
    for {
        select {
        case c := &lt;-workCh:
            now := time.Now().UnixNano()
            // ...
            if c.processDeferredQueue(now) {
                dirty = true
            }
        // ...
        }
    }
}</code></pre><p>&#x6267;&#x884C;</p><pre><code class="language-text">func (c *Channel) processDeferredQueue(t int64) bool {
    c.exitMutex.RLock()
    defer c.exitMutex.RUnlock()


    // ...
    dirty := false
    for {
        c.deferredMutex.Lock()
        // &#x5018;&#x82E5;&#x5806;&#x9876;&#x7684;&#x6D88;&#x606F;&#x5DF2;&#x7ECF;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x6761;&#x4EF6;&#xFF0C;&#x5219;&#x53D6;&#x51FA;&#x8FDB;&#x884C;&#x6267;&#x884C;
        item, _ := c.deferredPQ.PeekAndShift(t)
        c.deferredMutex.Unlock()
        // &#x5018;&#x82E5;&#x5806;&#x9876;&#x7684;&#x6D88;&#x606F;&#x90FD;&#x5C1A;&#x672A;&#x8FBE;&#x5230;&#x6267;&#x884C;&#x65F6;&#x95F4;&#x6761;&#x4EF6;&#xFF0C;&#x5219;&#x7ED3;&#x675F;&#x672C;&#x6B21;&#x4EFB;&#x52A1;
        if item == nil {
            goto exit
        }
        dirty = true




        msg := item.Value.(*Message)
        _, err := c.popDeferredMessage(msg.ID)
        if err != nil {
            goto exit
        }
        // &#x53D1;&#x9001;&#x5EF6;&#x65F6;&#x6D88;&#x606F;&#xFF0C;&#x7531;  protocolV2.messagePump(..) &#x65B9;&#x6CD5;&#x63A5;&#x6536;&#x5904;&#x7406;
        c.put(msg)
    }


exit:
    return dirty
}</code></pre><h2 id="5-%E6%80%BB%E7%BB%93">5 &#x603B;&#x7ED3;</h2><p>&#x672C;&#x671F;&#x5411;&#x5927;&#x5BB6;&#x8BE6;&#x7EC6;&#x5206;&#x4EAB;&#x4E86;&#x4E00;&#x6B3E;&#x5B8C;&#x5168;&#x57FA;&#x4E8E; go &#x8BED;&#x8A00;&#x5B9E;&#x73B0;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x6D88;&#x606F;&#x961F;&#x5217;&#x2014;&#x2014;nsq. &#x6587;&#x4E2D;&#x5206;&#x522B;&#x5411;&#x5927;&#x5BB6;&#x8BE6;&#x7EC6;&#x4ECB;&#x7ECD;&#x4E86;&#x6709;&#x5173; nsq &#x7684;&#x6838;&#x5FC3;&#x6982;&#x5FF5;&#x3001;&#x4F7F;&#x7528;&#x6559;&#x7A0B;&#xFF0C;&#x5E76;&#x4E14;&#x548C;&#x5927;&#x5BB6;&#x4E00;&#x8D77;&#x6DF1;&#x5165;&#x5230; nsq &#x9879;&#x76EE;&#x6E90;&#x7801;&#x5F53;&#x4E2D;&#xFF0C;&#x9010;&#x4E00;&#x5411;&#x5927;&#x5BB6;&#x63ED;&#x793A;&#x4E86; nsq &#x5BA2;&#x6237;&#x7AEF;&#x4E0E;&#x670D;&#x52A1;&#x7AEF;&#x9879;&#x76EE;&#x7684;&#x5E95;&#x5C42;&#x6280;&#x672F;&#x7EC6;&#x8282;.</p><p>&#x8FD9;&#x91CC;&#x6BD4;&#x8F83;&#x81EA;&#x4FE1;&#x5730;&#x8BF4;&#x4E00;&#x53E5;&#xFF0C;&#x53EA;&#x8981;&#x5927;&#x5BB6;&#x8BA4;&#x771F;&#x9605;&#x8BFB;&#x5B8C;&#x672C;&#x6587;&#xFF0C;&#x5BF9;&#x4E8E; nsq &#x7684;&#x7406;&#x89E3;&#x7A0B;&#x5EA6;&#x4E00;&#x5B9A;&#x80FD;&#x505A;&#x5230;<strong>&#x201C;&#x9065;&#x9065;&#x9886;&#x5148;&#x201D;</strong>&#xFF01;</p>]]></content:encoded></item><item><title><![CDATA[用 Go 创建一个简易负载均衡器]]></title><description><![CDATA[<p>&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x5728; Web &#x67B6;&#x6784;&#x4E2D;&#x626E;&#x6F14;&#x4E86;&#x5F88;&#x5173;&#x952E;&#x7684;&#x89D2;&#x8272;&#x3002;&#x5B83;&#x4EEC;&#x80FD;&#x5728;&#x4E00;&#x7EC4;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x5206;&#x914D;&#x8D1F;&#x8F7D;&#x3002;&#x8FD9;&#x4F7F;&#x5F97;&#x670D;&#x52A1;&#x6269;&#x5C55;&#x6027;&#x66F4;&#x597D;&#x3002;&#x56E0;&#x4E3A;&#x914D;&#x7F6E;</p>]]></description><link>http://www.net-e.cn/yong-go-chuang-jian-yi-ge-jian-yi-fu-zai-jun-heng-qi/</link><guid isPermaLink="false">61502b11681cac0001a7ef4f</guid><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Sun, 26 Sep 2021 08:12:16 GMT</pubDate><content:encoded><![CDATA[<p>&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x5728; Web &#x67B6;&#x6784;&#x4E2D;&#x626E;&#x6F14;&#x4E86;&#x5F88;&#x5173;&#x952E;&#x7684;&#x89D2;&#x8272;&#x3002;&#x5B83;&#x4EEC;&#x80FD;&#x5728;&#x4E00;&#x7EC4;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x5206;&#x914D;&#x8D1F;&#x8F7D;&#x3002;&#x8FD9;&#x4F7F;&#x5F97;&#x670D;&#x52A1;&#x6269;&#x5C55;&#x6027;&#x66F4;&#x597D;&#x3002;&#x56E0;&#x4E3A;&#x914D;&#x7F6E;&#x4E86;&#x5F88;&#x591A;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#xFF0C;&#x670D;&#x52A1;&#x4E5F;&#x56E0;&#x6B64;&#x80FD;&#x5728;&#x67D0;&#x6B21;&#x8BF7;&#x6C42;&#x5931;&#x8D25;&#x540E;&#x627E;&#x5230;&#x6B63;&#x5E38;&#x8FD0;&#x884C;&#x7684;&#x670D;&#x52A1;&#x5668;&#x800C;&#x53D8;&#x5F97;&#x9AD8;&#x53EF;&#x7528;&#x3002;</p><p>&#x5728;&#x4F7F;&#x7528;&#x4E86;&#x50CF; <strong><a href="https://link.zhihu.com/?target=https%3A//www.nginx.com/" rel="nofollow noreferrer">NGINX</a></strong> &#x7B49;&#x4E13;&#x4E1A;&#x7684;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x540E;&#xFF0C;&#x6211;&#x81EA;&#x5DF1;&#x4E5F;&#x5C1D;&#x8BD5;&#x7740;&#x7528; <strong><a href="https://link.zhihu.com/?target=https%3A//golang.org/" rel="nofollow noreferrer">Golang</a></strong> &#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A;&#x7B80;&#x6613;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x3002;Go &#x662F;&#x4E00;&#x79CD;&#x73B0;&#x4EE3;&#x8BED;&#x8A00;&#xFF0C;&#x7B2C;&#x4E00;&#x7279;&#x6027;&#x662F;&#x652F;&#x6301;&#x5E76;&#x53D1;&#x3002;Go &#x6709;&#x4E30;&#x5BCC;&#x7684;&#x6807;&#x51C6;&#x5E93;&#xFF0C;&#x4F7F;&#x7528;&#x8FD9;&#x4E9B;&#x5E93;&#x4F60;&#x53EF;&#x4EE5;&#x7528;&#x66F4;&#x5C11;&#x7684;&#x4EE3;&#x7801;&#x5199;&#x51FA;&#x9AD8;&#x6027;&#x80FD;&#x7684;&#x5E94;&#x7528;&#x7A0B;&#x5E8F;&#x3002;&#x5BF9;&#x6BCF;&#x4E00;&#x4E2A;&#x53D1;&#x884C;&#x7248;&#x672C;&#x5B83;&#x90FD;&#x6709;&#x9759;&#x6001;&#x94FE;&#x63A5;&#x5E93;&#x3002;</p><h2 id="%E6%88%91%E4%BB%AC%E7%9A%84%E7%AE%80%E6%98%93%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86"><strong>&#x6211;&#x4EEC;&#x7684;&#x7B80;&#x6613;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x5DE5;&#x4F5C;&#x539F;&#x7406;</strong></h2><p>&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x6709;&#x4E0D;&#x540C;&#x7684;&#x7B56;&#x7565;&#x7528;&#x6765;&#x5728;&#x4E00;&#x7EC4;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x4E2D;&#x5206;&#x644A;&#x8D1F;&#x8F7D;&#x3002;</p><p>&#x4F8B;&#x5982;&#xFF1A;</p><ul><li><strong>&#x8F6E;&#x8BE2;</strong> &#x5E73;&#x7B49;&#x5206;&#x644A;&#xFF0C;&#x8BA4;&#x4E3A;&#x540E;&#x7AEF;&#x7684;&#x6240;&#x6709;&#x673A;&#x5668;&#x5904;&#x7406;&#x80FD;&#x529B;&#x76F8;&#x540C;</li><li><strong>&#x52A0;&#x6743;&#x8F6E;&#x8BE2;</strong> &#x57FA;&#x4E8E;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x4E0D;&#x540C;&#x7684;&#x5904;&#x7406;&#x80FD;&#x529B;&#xFF0C;&#x4E3A;&#x5176;&#x52A0;&#x4E0A;&#x4E0D;&#x540C;&#x7684;&#x6743;&#x91CD;</li><li><strong>&#x6700;&#x5C11;&#x8FDE;&#x63A5;&#x6570;</strong> &#x8D1F;&#x8F7D;&#x88AB;&#x5206;&#x6D41;&#x5230;&#x6D3B;&#x8DC3;&#x8FDE;&#x63A5;&#x6700;&#x5C11;&#x7684;&#x670D;&#x52A1;&#x5668;</li></ul><p>&#x81F3;&#x4E8E;&#x6211;&#x4EEC;&#x7684;&#x7B80;&#x6613;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#xFF0C;&#x6211;&#x4EEC;&#x4F1A;&#x5B9E;&#x73B0;&#x8FD9;&#x91CC;&#x8FB9;&#x6700;&#x7B80;&#x5355;&#x7684;&#x65B9;&#x5F0F; <strong>&#x8F6E;&#x8BE2;</strong>&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-48a124475ffd4ade355da5705e559c9e_720w.jpg" class="kg-image" alt loading="lazy"></figure><h2 id="%E8%BD%AE%E8%AF%A2%E9%80%89%E6%8B%A9"><strong>&#x8F6E;&#x8BE2;&#x9009;&#x62E9;</strong></h2><p>&#x8F6E;&#x8BE2;&#x65E0;&#x7591;&#x662F;&#x5F88;&#x7B80;&#x5355;&#x7684;&#x3002;&#x5B83;&#x8F6E;&#x6D41;&#x7ED9;&#x6BCF;&#x4E2A; worker &#x76F8;&#x540C;&#x7684;&#x6267;&#x884C;&#x4EFB;&#x52A1;&#x7684;&#x673A;&#x4F1A;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-e743533f37253535652fb82956e7cf03_720w.jpg" class="kg-image" alt loading="lazy"></figure><p>&#x4E0A;&#x56FE;&#x5DF2;&#x7ECF;&#x8BF4;&#x660E;&#x4E86;&#xFF0C;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x5468;&#x671F;&#x6027;&#x5730;&#x9009;&#x62E9;&#x67D0;&#x53F0;&#x670D;&#x52A1;&#x5668;&#x3002;&#x4F46;&#x662F;&#x6211;&#x4EEC;&#x4E0D;&#x80FD;<em>&#x76F4;&#x63A5;</em>&#x4F7F;&#x7528;&#x5B83;&#xFF0C;&#x4E0D;&#x662F;&#x5417;&#xFF1F;</p><p><strong>&#x5982;&#x679C;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x5B95;&#x673A;&#x4E86;&#x600E;&#x4E48;&#x529E;&#xFF1F;&#x6050;&#x6015;&#x6211;&#x4EEC;&#x4E0D;&#x4F1A;&#x5E0C;&#x671B;&#x6D41;&#x91CF;&#x88AB;&#x8DEF;&#x7531;&#x5230;&#x6302;&#x6389;&#x7684;&#x673A;&#x5668;&#x4E0A;&#x53BB;&#x3002;&#x56E0;&#x6B64;&#x9664;&#x975E;&#x6211;&#x4EEC;&#x6DFB;&#x52A0;&#x4E00;&#x4E9B;&#x6761;&#x4EF6;&#xFF0C;&#x5426;&#x5219;&#x4E0D;&#x80FD;&#x76F4;&#x63A5;&#x4F7F;&#x7528;&#x8FD9;&#x4E2A;&#x7B97;&#x6CD5;&#x3002;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x628A;&#x6D41;&#x91CF;&#x53EA;&#x8DEF;&#x7531;&#x5230;&#x6CA1;&#x6709;&#x6302;&#x6389;&#x4E14;&#x6B63;&#x5E38;&#x8FD0;&#x884C;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x4E0A;</strong>&#x3002;</p><h2 id="%E5%AE%9A%E4%B9%89%E5%87%A0%E4%B8%AA%E7%BB%93%E6%9E%84%E4%BD%93"><strong>&#x5B9A;&#x4E49;&#x51E0;&#x4E2A;&#x7ED3;&#x6784;&#x4F53;</strong></h2><p>&#x4FEE;&#x6B63;&#x601D;&#x8DEF;&#x540E;&#xFF0C;&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x6E05;&#x695A;&#x6211;&#x4EEC;&#x662F;&#x60F3;&#x8981;&#x4E00;&#x79CD;&#x80FD;&#x8DDF;&#x8E2A;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x72B6;&#x6001;&#x4FE1;&#x606F;&#x7684;&#x65B9;&#x6CD5;&#x3002;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x68C0;&#x67E5;&#x673A;&#x5668;&#x662F;&#x5426;&#x5B58;&#x6D3B;&#xFF0C;&#x4E5F;&#x9700;&#x8981;&#x8DDF;&#x8E2A; Url&#x3002;</p><p>&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7B80;&#x5355;&#x5730;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x4E0B;&#x9762;&#x7684;&#x7ED3;&#x6784;&#x4F53;&#x6765;&#x7EF4;&#x62A4;&#x6211;&#x4EEC;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x3002;</p><pre><code class="language-text">type Backend struct {
    URL          *url.URL
    Alive        bool
    mux          sync.RWMutex
    ReverseProxy *httputil.ReverseProxy
}
</code></pre><p>&#x4E0D;&#x8981;&#x62C5;&#x5FC3;&#xFF0C;<strong>&#x540E;&#x9762;&#x6211;&#x4F1A;&#x89E3;&#x91CA; <code>Backend</code> &#x91CC;&#x7684;&#x5B57;&#x6BB5;</strong>&#x3002;</p><p>&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x8981;&#x5728;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x4E2D;&#x8DDF;&#x8E2A;&#x6240;&#x6709;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x7684;&#x72B6;&#x6001;&#xFF0C;&#x53EF;&#x4EE5;&#x7B80;&#x5355;&#x5730;&#x4F7F;&#x7528;&#x4E00;&#x4E2A;&#x5207;&#x7247;&#x6765;&#x5B9E;&#x73B0;&#x3002;&#x53E6;&#x5916;&#x8FD8;&#x9700;&#x8981;&#x4E00;&#x4E2A;&#x8BA1;&#x7B97;&#x53D8;&#x91CF;&#x3002;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x5B9A;&#x4E49;&#x4E3A; <code>ServerPool</code></p><pre><code class="language-text">type ServerPool struct {
    backends []*Backend
    current  uint64
}
</code></pre><h2 id="reverseproxy-%E7%9A%84%E4%BD%BF%E7%94%A8"><strong>ReverseProxy &#x7684;&#x4F7F;&#x7528;</strong></h2><p>&#x524D;&#x9762;&#x5DF2;&#x7ECF;&#x58F0;&#x660E;&#x8FC7;&#x4E86;&#xFF0C;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x662F;&#x4E13;&#x95E8;&#x7528;&#x6765;&#x628A;&#x6D41;&#x91CF;&#x8DEF;&#x7531;&#x5230;&#x4E0D;&#x540C;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x4EE5;&#x53CA;&#x628A;&#x7ED3;&#x679C;&#x8FD4;&#x56DE;&#x7ED9;&#x6765;&#x6E90;&#x5BA2;&#x6237;&#x7AEF;&#x7684;&#x3002;</p><p>Go &#x5B98;&#x65B9;&#x6587;&#x6863;&#x7684;&#x63CF;&#x8FF0;&#xFF1A;</p><blockquote>ReverseProxy &#x662F;&#x4E00;&#x79CD; HTTP Handler&#xFF0C;&#x63A5;&#x6536;&#x8BF7;&#x6C42;&#x5E76;&#x53D1;&#x9001;&#x5230;&#x53E6;&#x4E00;&#x53F0;&#x670D;&#x52A1;&#x5668;&#xFF0C;&#x628A;&#x54CD;&#x5E94;&#x4EE3;&#x7406;&#x56DE;&#x5BA2;&#x6237;&#x7AEF;&#x3002;</blockquote><p>**&#x800C;&#x8FD9;&#x6B63;&#x662F;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x7684;&#x3002;**&#x6211;&#x4EEC;&#x4E0D;&#x9700;&#x8981;&#x91CD;&#x590D;&#x9020;&#x8F6E;&#x5B50;&#x4E86;&#x3002;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7B80;&#x5355;&#x5730;&#x901A;&#x8FC7; <code>ReverseProxy</code> &#x8F6C;&#x53D1;&#x539F;&#x59CB;&#x8BF7;&#x6C42;&#x3002;</p><pre><code class="language-text">u, _ := url.Parse(&quot;http://localhost:8080&quot;)
rp := httputil.NewSingleHostReverseProxy(u)

// initialize your server and add this as handler
http.HandlerFunc(rp.ServeHTTP)
</code></pre><p>&#x901A;&#x8FC7; <code>httputil.NewSingleHostReverseProxy(url)</code> &#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x521D;&#x59CB;&#x5316;&#x4E00;&#x4E2A;&#x628A;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x7ED9; <code>url</code> &#x7684;&#x53CD;&#x5411;&#x4EE3;&#x7406;&#x3002;&#x5728;&#x4E0A;&#x9762;&#x7684;&#x4F8B;&#x5B50;&#x4E2D;&#xFF0C;&#x6240;&#x6709;&#x7684;&#x8BF7;&#x6C42;&#x4F1A;&#x88AB;&#x8F6C;&#x53D1;&#x5230; localhost:8080&#xFF0C;&#x7ED3;&#x679C;&#x4F1A;&#x53D1;&#x56DE;&#x5230;&#x6765;&#x6E90;&#x5BA2;&#x6237;&#x7AEF;&#x3002;&#x8FD9;&#x91CC;&#x4F60;&#x53EF;&#x4EE5;&#x627E;&#x5230;&#x66F4;&#x591A;&#x4F8B;&#x5B50;&#x3002;</p><p>&#x5982;&#x679C;&#x6211;&#x4EEC;&#x770B;&#x4E00;&#x4E0B; ServeHTTP &#x65B9;&#x6CD5;&#x7684;&#x7B7E;&#x540D;&#xFF0C;&#x5B83;&#x6709; HTTP handler &#x7684;&#x7B7E;&#x540D;&#xFF0C;&#x56E0;&#x6B64;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x628A;&#x5B83;&#x4F20;&#x7ED9; <code>http</code> &#x7684; <code>HandlerFunc</code>&#x3002;</p><p>&#x4F60;&#x53EF;&#x4EE5;&#x5728;<strong><a href="https://link.zhihu.com/?target=https%3A//golang.org/pkg/net/http/httputil/%23ReverseProxy" rel="nofollow noreferrer">&#x6587;&#x6863;</a></strong>&#x4E2D;&#x627E;&#x5230;&#x66F4;&#x591A;&#x4F8B;&#x5B50;&#x3002;</p><p>&#x5728;&#x6211;&#x4EEC;&#x7684;&#x7B80;&#x6613;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7528;&#x4E0E; <code>ReverseProxy</code> &#x76F8;&#x5173;&#x8054;&#x7684; <code>Backend</code> &#x4E2D;&#x7684; <code>URL</code> &#x521D;&#x59CB;&#x5316; <code>ReverseProxy</code>&#xFF0C;&#x8FD9;&#x6837; <code>ReverseProxy</code> &#x5C31;&#x4F1A;&#x628A;&#x6211;&#x4EEC;&#x8BF7;&#x6C42;&#x8DEF;&#x7531;&#x5230; <code>URL</code>.</p><h2 id="%E9%80%89%E6%8B%A9%E5%A4%84%E7%90%86%E8%BF%87%E7%A8%8B"><strong>&#x9009;&#x62E9;&#x5904;&#x7406;&#x8FC7;&#x7A0B;</strong></h2><p>&#x6211;&#x4EEC;&#x8981;&#x5728;&#x4E0B;&#x4E00;&#x6B21;&#x8F6E;&#x8BE2;&#x4E2D;<strong>&#x8DF3;&#x8FC7;&#x6302;&#x6389;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;</strong>&#x3002;&#x4F46;&#x662F;&#x65E0;&#x8BBA;&#x5982;&#x4F55;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x4E00;&#x79CD;&#x8BA1;&#x6570;&#x7684;&#x65B9;&#x5F0F;&#x3002;</p><p>&#x5F88;&#x591A;&#x5BA2;&#x6237;&#x7AEF;&#x4F1A;&#x8FDE;&#x63A5;&#x5230;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#xFF0C;&#x5F53;&#x67D0;&#x4E00;&#x4E2A;&#x5BA2;&#x6237;&#x7AEF;&#x53D1;&#x6765;&#x8BF7;&#x6C42;&#x65F6;&#xFF0C;&#x6211;&#x4EEC;&#x8981;&#x8F6C;&#x53D1;&#x6D41;&#x91CF;&#x7684;&#x76EE;&#x6807;&#x673A;&#x5668;&#x4F1A;&#x51FA;&#x73B0;&#x7ADE;&#x4E89;&#x3002;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x4F7F;&#x7528; <code>mutex</code> &#x4E3A; <code>ServerPool</code> &#x52A0;&#x9501;&#x6765;&#x907F;&#x514D;&#x8FD9;&#x79CD;&#x73B0;&#x8C61;&#x3002;&#x4F46;&#x8FD9;&#x662F;&#x4E00;&#x79CD;&#x8FC7;&#x72B9;&#x4E0D;&#x53CA;&#x7684;&#x624B;&#x6BB5;&#xFF0C;&#x6BD5;&#x7ADF;&#x6211;&#x4EEC;&#x4E0D;&#x5E0C;&#x671B;&#x9501;&#x4F4F; ServerPool&#x3002;&#x6211;&#x4EEC;&#x7684;&#x9700;&#x6C42;&#x53EA;&#x662F;&#x8BA9;&#x8BA1;&#x6570;&#x5668;&#x52A0; 1.</p><p>&#x4E3A;&#x4E86;&#x6EE1;&#x8DB3;&#x8FD9;&#x4E2A;&#x9700;&#x6C42;&#xFF0C;&#x6700;&#x7406;&#x60F3;&#x7684;&#x89E3;&#x51B3;&#x65B9;&#x6848;&#x662F;&#x8BA9;&#x52A0; 1 &#x6210;&#x4E3A;&#x539F;&#x5B50;&#x64CD;&#x4F5C;&#x3002;Go &#x7684; <code>atomic</code> &#x5305;&#x80FD;&#x5B8C;&#x7F8E;&#x652F;&#x6301;&#x3002;</p><pre><code class="language-text">func (s *ServerPool) NextIndex() int {
    return int(atomic.AddUint64(&amp;s.current, uint64(1)) % uint64(len(s.backends)))
}
</code></pre><p>&#x8FD9;&#x91CC;&#x6211;&#x4EEC;&#x7684;&#x52A0; 1 &#x662F;&#x539F;&#x5B50;&#x64CD;&#x4F5C;&#xFF0C;&#x901A;&#x8FC7;&#x5BF9;&#x5207;&#x7247;&#x7684;&#x957F;&#x5EA6;&#x53D6;&#x6A21;&#x8FD4;&#x56DE;&#x4E86; index&#x3002;&#x8FD9;&#x610F;&#x5473;&#x7740;&#x8FD4;&#x56DE;&#x7684;&#x503C;&#x4E00;&#x5B9A;&#x5728; 0 &#x4E0E;&#x5207;&#x7247;&#x957F;&#x5EA6;&#x4E4B;&#x95F4;&#x3002;&#x5F52;&#x6839;&#x7ED3;&#x5E95;&#xFF0C;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x7684;&#x662F;&#x4E00;&#x4E2A;&#x7279;&#x5B9A;&#x7684; index&#xFF0C;&#x800C;&#x4E0D;&#x662F;&#x6240;&#x6709;&#x6570;&#x3002;</p><h2 id="%E9%80%89%E4%B8%AD%E5%AD%98%E6%B4%BB%E7%9A%84%E5%90%8E%E7%AB%AF%E6%9C%BA%E5%99%A8"><strong>&#x9009;&#x4E2D;&#x5B58;&#x6D3B;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;</strong></h2><p>&#x6211;&#x4EEC;&#x5DF2;&#x7ECF;&#x77E5;&#x9053;&#x6211;&#x4EEC;&#x7684;&#x8BF7;&#x6C42;&#x662F;&#x88AB;&#x5468;&#x671F;&#x6027;&#x7684;&#x8DEF;&#x7531;&#x5230;&#x6BCF;&#x53F0;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x4E0A;&#x7684;&#x3002;&#x6211;&#x4EEC;&#x8981;&#x505A;&#x7684;&#x5C31;&#x662F;&#x8DF3;&#x8FC7;&#x6302;&#x6389;&#x7684;&#x673A;&#x5668;&#x3002;</p><p><code>GetNext()</code> &#x8FD4;&#x56DE;&#x7684;&#x4E00;&#x5B9A;&#x662F; 0 &#x4E0E; &#x5207;&#x7247;&#x957F;&#x5EA6;&#x4E4B;&#x95F4;&#x7684;&#x503C;&#x3002;&#x6BCF;&#x6B21;&#x6211;&#x4EEC;&#x8981;&#x8F6C;&#x53D1;&#x8BF7;&#x6C42;&#x5230;&#x540E;&#x7AEF;&#x67D0;&#x53F0;&#x673A;&#x5668;&#x65F6;&#xFF0C;&#x5982;&#x679C;&#x5B83;&#x6302;&#x6389;&#x4E86;&#xFF0C;&#x6211;&#x4EEC;&#x5FC5;&#x987B;&#x5FAA;&#x73AF;&#x5730;&#x67E5;&#x627E;&#x6574;&#x4E2A;&#x5207;&#x7247;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-fe8eea4e2b52ae079c662a4b1fbe7450_720w.jpg" class="kg-image" alt loading="lazy"></figure><p>&#x4ECE;&#x4E0A;&#x56FE;&#x53EF;&#x4EE5;&#x770B;&#x51FA;&#xFF0C;&#x6211;&#x4EEC;&#x8981;&#x60F3;&#x4ECE; next &#x5F00;&#x59CB;&#x904D;&#x5386;&#x6574;&#x4E2A; list&#xFF0C;&#x53EA;&#x9700;&#x8981;&#x904D;&#x5386; <code>next + length</code>&#x3002;&#x4F46;&#x662F;&#x6211;&#x4EEC;&#x8981;&#x8986;&#x76D6;&#x6574;&#x4E2A;&#x5207;&#x7247;&#x7684;&#x957F;&#x5EA6;&#x624D;&#x80FD;&#x9009;&#x4E2D;&#x4E00;&#x4E2A; index&#x3002;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7528;&#x53D6;&#x6A21;&#x64CD;&#x4F5C;&#x5F88;&#x5BB9;&#x6613;&#x5730;&#x5B9E;&#x73B0;&#x3002;</p><p>&#x5F53;&#x6211;&#x4EEC;&#x901A;&#x8FC7;&#x641C;&#x7D22;&#x627E;&#x5230;&#x4E86;&#x4E00;&#x53F0;&#x6B63;&#x5E38;&#x5DE5;&#x4F5C;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x65F6;&#xFF0C;&#x6211;&#x4EEC;&#x628A;&#x5B83;&#x6807;&#x8BB0;&#x4E3A; current&#x3002;</p><p>&#x4E0B;&#x9762;&#x662F;&#x5BF9;&#x5E94;&#x4E0A;&#x9762;&#x64CD;&#x4F5C;&#x7684;&#x4EE3;&#x7801;&#x3002;</p><pre><code class="language-text">// GetNextPeer returns next active peer to take a connection
func (s *ServerPool) GetNextPeer() *Backend {
    // loop entire backends to find out an Alive backend
    next := s.NextIndex()
    l := len(s.backends) + next // start from next and move a full cycle
    for i := next; i &lt; l; i++ {
        idx := i % len(s.backends) // take an index by modding with length
        // if we have an alive backend, use it and store if its not the original one
        if s.backends[idx].IsAlive() {
            if i != next {
                atomic.StoreUint64(&amp;s.current, uint64(idx)) // mark the current one
            }
            return s.backends[idx]
        }
    }
    return nil
}
</code></pre><h2 id="%E5%9C%A8-backend-%E7%BB%93%E6%9E%84%E4%BD%93%E4%B8%AD%E9%81%BF%E5%85%8D%E7%AB%9E%E4%BA%89%E6%9D%A1%E4%BB%B6"><strong>&#x5728; Backend &#x7ED3;&#x6784;&#x4F53;&#x4E2D;&#x907F;&#x514D;&#x7ADE;&#x4E89;&#x6761;&#x4EF6;</strong></h2><p>&#x6211;&#x4EEC;&#x9700;&#x8981;&#x8003;&#x8651;&#x4E00;&#x4E2A;&#x5F88;&#x4E25;&#x91CD;&#x7684;&#x95EE;&#x9898;&#x3002;&#x6211;&#x4EEC;&#x7684; <code>Backend</code> &#x7ED3;&#x6784;&#x4F53;&#x6709;&#x4E00;&#x4E2A;&#x53EF;&#x80FD;&#x88AB;&#x4E0D;&#x540C;&#x534F;&#x7A0B;&#x540C;&#x65F6;&#x4FEE;&#x6539;&#x6216;&#x8BBF;&#x95EE;&#x7684;&#x53D8;&#x91CF;&#x3002;</p><p>&#x6211;&#x4EEC;&#x77E5;&#x9053;&#x8BFB;&#x7684;&#x534F;&#x7A0B;&#x6570;&#x6BD4;&#x5199;&#x7684;&#x591A;&#x3002;&#x56E0;&#x6B64;&#x6211;&#x4EEC;&#x7528; <code>RWMutex</code> &#x6765;&#x4E32;&#x884C;&#x5316;&#x5BF9; <code>Alive</code> &#x7684;&#x8BFB;&#x5199;&#x3002;</p><pre><code class="language-text">// SetAlive for this backend
func (b *Backend) SetAlive(alive bool) {
    b.mux.Lock()
    b.Alive = alive
    b.mux.Unlock()
}

// IsAlive returns true when backend is alive
func (b *Backend) IsAlive() (alive bool) {
    b.mux.RLock()
    alive = b.Alive
    b.mux.RUnlock()
    return
}
</code></pre><h2 id="%E8%AE%A9%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E5%99%A8%E5%8F%91%E8%AF%B7%E6%B1%82"><strong>&#x8BA9;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x53D1;&#x8BF7;&#x6C42;</strong></h2><p>&#x6240;&#x6709;&#x7684;&#x51C6;&#x5907;&#x5DE5;&#x4F5C;&#x90FD;&#x505A;&#x5B8C;&#x4E86;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7528;&#x4E0B;&#x9762;&#x7684;&#x65B9;&#x6CD5;&#x5BF9;&#x6211;&#x4EEC;&#x7684;&#x8BF7;&#x6C42;&#x5B9E;&#x73B0;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x3002;&#x53EA;&#x6709;&#x5728;&#x6240;&#x6709;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x90FD;&#x79BB;&#x7EBF;&#x540E;&#x5B83;&#x624D;&#x4F1A;&#x8FD4;&#x56DE;&#x5931;&#x8D25;&#x3002;</p><pre><code class="language-text">// lb load balances the incoming request
func lb(w http.ResponseWriter, r *http.Request) {
    peer := serverPool.GetNextPeer()
    if peer != nil {
        peer.ReverseProxy.ServeHTTP(w, r)
        return
    }
    http.Error(w, &quot;Service not available&quot;, http.StatusServiceUnavailable)
}
</code></pre><p>&#x8FD9;&#x4E2A;&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x7B80;&#x5355;&#x5730;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A; <code>HandleFunc</code> &#x4F20;&#x7ED9; http server&#x3002;</p><pre><code class="language-text">server := http.Server{
    Addr:    fmt.Sprintf(&quot;:%d&quot;, port),
    Handler: http.HandlerFunc(lb),
}
</code></pre><h2 id="%E4%BB%85%E6%8A%8A%E6%B5%81%E9%87%8F%E8%B7%AF%E7%94%B1%E5%88%B0%E5%81%A5%E5%BA%B7%E7%9A%84%E5%90%8E%E7%AB%AF%E6%9C%BA%E5%99%A8"><strong>&#x4EC5;&#x628A;&#x6D41;&#x91CF;&#x8DEF;&#x7531;&#x5230;&#x5065;&#x5EB7;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;</strong></h2><p>&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x7684; <code>lb</code> &#x6709;&#x4E2A;&#x4E25;&#x91CD;&#x7684;&#x95EE;&#x9898;&#x3002;&#x6211;&#x4EEC;&#x4E0D;&#x77E5;&#x9053;&#x540E;&#x7AEF;&#x67D0;&#x53F0;&#x673A;&#x5668;&#x662F;&#x5426;&#x5065;&#x5EB7;&#x3002;&#x6211;&#x4EEC;&#x5FC5;&#x987B;&#x5411;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x53D1;&#x9001;&#x8BF7;&#x6C42;&#x518D;&#x68C0;&#x67E5;&#x5B83;&#x662F;&#x5426;&#x5B58;&#x6D3B;&#x624D;&#x80FD;&#x77E5;&#x9053;&#x3002;</p><p>&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7528;&#x4E24;&#x79CD;&#x65B9;&#x6CD5;&#x5B9E;&#x73B0;&#xFF1A;</p><ul><li>**&#x4E3B;&#x52A8;&#xFF1A;**&#x5728;&#x5904;&#x7406;&#x5F53;&#x524D;&#x7684;&#x8BF7;&#x6C42;&#x65F6;&#xFF0C;&#x9009;&#x4E2D;&#x7684;&#x67D0;&#x53F0;&#x673A;&#x5668;&#x6CA1;&#x6709;&#x54CD;&#x5E94;&#xFF0C;&#x6211;&#x4EEC;&#x628A;&#x5B83;&#x6807;&#x8BB0;&#x4E3A;&#x6302;&#x6389;&#x3002;</li><li>**&#x88AB;&#x52A8;&#xFF1A;**&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x4EE5;&#x56FA;&#x5B9A;&#x7684;&#x5468;&#x671F; ping &#x540E;&#x7AEF;&#x673A;&#x5668;&#xFF0C;&#x68C0;&#x67E5;&#x5176;&#x72B6;&#x6001;</li></ul><h2 id="%E4%B8%BB%E5%8A%A8%E6%A3%80%E6%9F%A5%E5%90%8E%E7%AB%AF%E5%81%A5%E5%BA%B7%E6%9C%BA%E5%99%A8"><strong>&#x4E3B;&#x52A8;&#x68C0;&#x67E5;&#x540E;&#x7AEF;&#x5065;&#x5EB7;&#x673A;&#x5668;</strong></h2><p><code>ReverseProxy</code> &#x5728;&#x6709;&#x9519;&#x8BEF;&#x65F6;&#x4F1A;&#x89E6;&#x53D1;&#x4E00;&#x4E2A;&#x56DE;&#x8C03;&#x51FD;&#x6570; <code>ErrorHandler</code>&#x3002;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7528;&#x5B83;&#x6765;&#x68C0;&#x6D4B;&#x5931;&#x8D25;&#x3002;&#x4E0B;&#x9762;&#x662F;&#x5176;&#x5B9E;&#x73B0;&#xFF1A;</p><pre><code class="language-text">proxy.ErrorHandler = func(writer http.ResponseWriter, request *http.Request, e error) {
    log.Printf(&quot;[%s] %s\n&quot;, serverUrl.Host, e.Error())
    retries := GetRetryFromContext(request)
    if retries &lt; 3 {
        select {
            case &lt;-time.After(10 * time.Millisecond):
                ctx := context.WithValue(request.Context(), Retry, retries+1)
                proxy.ServeHTTP(writer, request.WithContext(ctx))
            }
            return
        }

    // after 3 retries, mark this backend as down
    serverPool.MarkBackendStatus(serverUrl, false)

    // if the same request routing for few attempts with different backends, increase the count
    attempts := GetAttemptsFromContext(request)
    log.Printf(&quot;%s(%s) Attempting retry %d\n&quot;, request.RemoteAddr, request.URL.Path, attempts)
    ctx := context.WithValue(request.Context(), Attempts, attempts+1)
    lb(writer, request.WithContext(ctx))
}
</code></pre><p>&#x8FD9;&#x91CC;&#x6211;&#x4EEC;&#x5229;&#x7528;&#x95ED;&#x5305;&#x7684;&#x7279;&#x6027;&#x6765;&#x8BBE;&#x8BA1;&#x8FD9;&#x4E2A;&#x9519;&#x8BEF; handler&#x3002;&#x6211;&#x4EEC;&#x80FD;&#x628A; serverUrl &#x7B49;&#x5916;&#x90E8;&#x7684;&#x53D8;&#x91CF;&#x6355;&#x83B7;&#x5230;&#x65B9;&#x6CD5;&#x5185;&#x3002;&#x5B83;&#x4F1A;&#x68C0;&#x67E5;&#x5DF2;&#x5B58;&#x5728;&#x7684;&#x91CD;&#x8BD5;&#x6B21;&#x6570;&#xFF0C;&#x5982;&#x679C;&#x5C0F;&#x4E8E; 3&#xFF0C;&#x5C31;&#x4F1A;&#x518D;&#x53D1;&#x9001;&#x540C;&#x6837;&#x7684;&#x8BF7;&#x6C42;&#x5230;&#x540C;&#x4E00;&#x53F0;&#x673A;&#x5668;&#x3002;&#x8FD9;&#x4E48;&#x505A;&#x7684;&#x539F;&#x56E0;&#x662F;&#x53EF;&#x80FD;&#x4F1A;&#x6709;&#x4E34;&#x65F6;&#x7684;&#x9519;&#x8BEF;&#xFF0C;&#x670D;&#x52A1;&#x5668;&#x53EF;&#x80FD;&#x6682;&#x65F6;&#x62D2;&#x7EDD;&#x4F60;&#x7684;&#x8BF7;&#x6C42;&#x800C;&#x5728;&#x77ED;&#x6682;&#x7684;&#x5EF6;&#x8FDF;&#x4E4B;&#x540E;&#x53C8;&#x53D8;&#x5F97;&#x53EF;&#x7528;&#x4E86;&#xFF08;&#x53EF;&#x80FD;&#x670D;&#x52A1;&#x5668;&#x4E3A;&#x4E86;&#x63A5;&#x53D7;&#x66F4;&#x591A;&#x7684;&#x5BA2;&#x6237;&#x7AEF;&#x8017;&#x5C3D;&#x4E86; socket&#xFF09;&#x3002;&#x56E0;&#x6B64;&#x6211;&#x4EEC;&#x52A0;&#x4E86;&#x4E00;&#x4E2A;&#x5B9A;&#x65F6;&#x5668;&#xFF0C;&#x5EF6;&#x8FDF; 10 &#x6BEB;&#x79D2;&#x5DE6;&#x53F3;&#x8FDB;&#x884C;&#x91CD;&#x8BD5;&#x3002;&#x6BCF;&#x6B21;&#x8BF7;&#x6C42;&#x90FD;&#x4F1A;&#x52A0;&#x4E00;&#x6B21;&#x91CD;&#x8BD5;&#x6B21;&#x6570;&#x7684;&#x8BA1;&#x6570;&#x3002;</p><p>3 &#x6B21;&#x8BF7;&#x6C42;&#x90FD;&#x5931;&#x8D25;&#x540E;&#xFF0C;&#x6211;&#x4EEC;&#x628A;&#x8FD9;&#x53F0;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x6807;&#x8BB0;&#x4E3A;&#x6302;&#x6389;&#x3002;</p><p>&#x4E0B;&#x4E00;&#x6B65;&#x8981;&#x505A;&#x7684;&#x662F;&#xFF0C;&#x628A;&#x8FD9;&#x4E2A;&#x8BF7;&#x6C42;&#x53D1;&#x9001;&#x5230;&#x53E6;&#x5916;&#x4E00;&#x53F0;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x3002;&#x6211;&#x4EEC;&#x901A;&#x8FC7;&#x4F7F;&#x7528; context &#x5305;&#x6765;&#x7EF4;&#x62A4;&#x4E00;&#x4E2A;&#x5C1D;&#x8BD5;&#x6B21;&#x6570;&#x7684;&#x8BA1;&#x6570;&#x6765;&#x5B9E;&#x73B0;&#x3002;&#x589E;&#x52A0;&#x4E86;&#x5C1D;&#x8BD5;&#x6B21;&#x6570;&#x7684;&#x8BA1;&#x6570;&#x540E;&#xFF0C;&#x6211;&#x4EEC;&#x628A;&#x5B83;&#x8FD4;&#x56DE;&#x7ED9; <code>lb</code>&#xFF0C;&#x5BFB;&#x627E;&#x4E0B;&#x4E00;&#x53F0;&#x53EF;&#x7528;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x6765;&#x5904;&#x7406;&#x8FD9;&#x4E2A;&#x8BF7;&#x6C42;&#x3002;</p><p>&#x6211;&#x4EEC;&#x4E0D;&#x80FD;&#x65E0;&#x9650;&#x5730;&#x91CD;&#x590D;&#x8FD9;&#x4E2A;&#x8FC7;&#x7A0B;&#xFF0C;&#x56E0;&#x6B64;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x5728; <code>lb</code> &#x4E2D;&#x68C0;&#x67E5;&#x5728;&#x7EE7;&#x7EED;&#x5904;&#x7406;&#x8BE5;&#x8BF7;&#x6C42;&#x4E4B;&#x524D;&#x662F;&#x5426;&#x5DF2;&#x8FBE;&#x5230;&#x4E86;&#x6700;&#x5927;&#x5C1D;&#x8BD5;&#x6B21;&#x6570;&#x3002;</p><p>&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7B80;&#x5355;&#x5730;&#x4ECE;&#x8BF7;&#x6C42;&#x4E2D;&#x53D6;&#x5F97;&#x5C1D;&#x8BD5;&#x6B21;&#x6570;&#xFF0C;&#x5982;&#x679C;&#x5B83;&#x8D85;&#x8FC7;&#x4E86;&#x6700;&#x5927;&#x6570;&#xFF0C;&#x53D6;&#x6D88;&#x8FD9;&#x6B21;&#x8BF7;&#x6C42;&#x3002;</p><pre><code class="language-text">// lb load balances the incoming request
func lb(w http.ResponseWriter, r *http.Request) {
    attempts := GetAttemptsFromContext(r)
    if attempts &gt; 3 {
        log.Printf(&quot;%s(%s) Max attempts reached, terminating\n&quot;, r.RemoteAddr, r.URL.Path)
        http.Error(w, &quot;Service not available&quot;, http.StatusServiceUnavailable)
        return
    }

    peer := serverPool.GetNextPeer()
    if peer != nil {
        peer.ReverseProxy.ServeHTTP(w, r)
        return
    }
    http.Error(w, &quot;Service not available&quot;, http.StatusServiceUnavailable)
}
</code></pre><p>&#x8FD9;&#x4E2A;&#x5B9E;&#x73B0;&#x662F;&#x9012;&#x5F52;&#x7684;&#x3002;</p><h2 id="context-%E7%9A%84%E4%BD%BF%E7%94%A8"><strong>context &#x7684;&#x4F7F;&#x7528;</strong></h2><p><code>context</code> &#x5305;&#x80FD;&#x8BA9;&#x4F60;&#x4FDD;&#x5B58; HTTP &#x8BF7;&#x6C42;&#x4E2D;&#x6709;&#x7528;&#x7684;&#x6570;&#x636E;&#x3002;&#x6211;&#x4EEC;&#x5927;&#x91CF;&#x5730;&#x4F7F;&#x7528;&#x4E86;&#x5B83;&#x6765;&#x8DDF;&#x8E2A;&#x8BF7;&#x6C42;&#x4E2D;&#x7279;&#x5B9A;&#x7684;&#x6570;&#x636E;&#xFF0C;&#x5982;&#x5C1D;&#x8BD5;&#x6B21;&#x6570;&#x548C;&#x91CD;&#x8BD5;&#x6B21;&#x6570;&#x3002;</p><p>&#x9996;&#x5148;&#xFF0C;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x6307;&#x5B9A; context &#x7684; key&#x3002;&#x63A8;&#x8350;&#x7528;&#x4E0D;&#x91CD;&#x590D;&#x7684;&#x6574;&#x578B;&#x800C;&#x4E0D;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#x4F5C;&#x4E3A; key&#x3002;Go &#x63D0;&#x4F9B;&#x4E86; <code>iota</code> &#x5173;&#x952E;&#x5B57;&#x5B9E;&#x73B0;&#x5E38;&#x91CF;&#x7684;&#x589E;&#x52A0;&#xFF0C;&#x6BCF;&#x4E2A; <code>iota</code> &#x542B;&#x6709;&#x4E00;&#x4E2A;&#x72EC;&#x4E00;&#x65E0;&#x4E8C;&#x7684;&#x503C;&#x3002;&#x8FD9;&#x662F;&#x4E00;&#x4E2A;&#x5B9A;&#x4E49;&#x6574;&#x578B; key &#x7684;&#x5B8C;&#x7F8E;&#x89E3;&#x51B3;&#x65B9;&#x6848;&#x3002;</p><pre><code class="language-text">const (
    Attempts int = iota
    Retry
)
</code></pre><p>&#x7136;&#x540E;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x50CF;&#x5728; HashMap &#x4E2D;&#x68C0;&#x7D22;&#x503C;&#x4E00;&#x6837;&#x68C0;&#x7D22;&#x5B9A;&#x4E49;&#x7684;&#x503C;&#x3002;&#x8FD4;&#x56DE;&#x7684;&#x9ED8;&#x8BA4;&#x503C;&#x968F;&#x5B9E;&#x9645;&#x7528;&#x4F8B;&#x7684;&#x4E0D;&#x540C;&#x800C;&#x4E0D;&#x540C;&#x3002;</p><pre><code class="language-text">// GetAttemptsFromContext returns the attempts for request
func GetRetryFromContext(r *http.Request) int {
    if retry, ok := r.Context().Value(Retry).(int); ok {
        return retry
    }
    return 0
}
</code></pre><h2 id="%E8%A2%AB%E5%8A%A8%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5"><strong>&#x88AB;&#x52A8;&#x5065;&#x5EB7;&#x68C0;&#x67E5;</strong></h2><p>&#x901A;&#x8FC7;&#x88AB;&#x52A8;&#x5065;&#x5EB7;&#x68C0;&#x67E5;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x6062;&#x590D;&#x6302;&#x6389;&#x7684;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x6216;&#x8BC6;&#x522B;&#x5B83;&#x4EEC;&#x3002;&#x6211;&#x4EEC;&#x4EE5;&#x56FA;&#x5B9A;&#x7684;&#x65F6;&#x95F4;&#x5468;&#x671F; ping &#x540E;&#x7AEF;&#x673A;&#x5668;&#x6765;&#x68C0;&#x67E5;&#x5B83;&#x4EEC;&#x7684;&#x72B6;&#x6001;&#x3002;</p><p>&#x6211;&#x4EEC;&#x5C1D;&#x8BD5;&#x5EFA;&#x7ACB; TCP &#x8FDE;&#x63A5;&#x6765; ping &#x673A;&#x5668;&#x3002;&#x5982;&#x679C;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x6709;&#x54CD;&#x5E94;&#xFF0C;&#x6211;&#x4EEC;&#x628A;&#x5B83;&#x6BD4;&#x8F83;&#x4E3A;&#x5B58;&#x6D3B;&#x7684;&#x3002;&#x5982;&#x679C;&#x4F60;&#x613F;&#x610F;&#xFF0C;&#x8FD9;&#x79CD;&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x4FEE;&#x6539;&#x4E3A;&#x8BF7;&#x6C42;&#x4E00;&#x4E2A;&#x7C7B;&#x4F3C; <code>/status</code> &#x7684;&#x7279;&#x5B9A;&#x7684;&#x670D;&#x52A1;&#x7EC8;&#x7AEF;&#x3002;&#x5EFA;&#x7ACB;&#x8FDE;&#x63A5;&#x4E4B;&#x540E;&#x4E0D;&#x8981;&#x5FD8;&#x8BB0;&#x5173;&#x95ED;&#x8FDE;&#x63A5;&#xFF0C;&#x4EE5;&#x514D;&#x5BF9;&#x670D;&#x52A1;&#x5668;&#x9020;&#x6210;&#x989D;&#x5916;&#x7684;&#x8D1F;&#x8F7D;&#x3002;&#x5426;&#x5219;&#xFF0C;&#x5B83;&#x4F1A;&#x5C1D;&#x8BD5;&#x4E00;&#x76F4;&#x7EF4;&#x6301;&#x8FDE;&#x63A5;&#x6700;&#x7EC8;&#x8017;&#x5C3D;&#x8D44;&#x6E90;&#x3002;</p><pre><code class="language-text">// isAlive checks whether a backend is Alive by establishing a TCP connection
func isBackendAlive(u *url.URL) bool {
    timeout := 2 * time.Second
    conn, err := net.DialTimeout(&quot;tcp&quot;, u.Host, timeout)
    if err != nil {
        log.Println(&quot;Site unreachable, error: &quot;, err)
        return false
    }
    _ = conn.Close() // close it, we dont need to maintain this connection
    return true
}
</code></pre><p>&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x50CF;&#x4E0B;&#x9762;&#x8FD9;&#x6837;&#x904D;&#x5386;&#x670D;&#x52A1;&#x5668;&#x5E76;&#x6807;&#x8BB0;&#x5B83;&#x4EEC;&#x7684;&#x72B6;&#x6001;&#x3002;</p><pre><code class="language-text">// HealthCheck pings the backends and update the status
func (s *ServerPool) HealthCheck() {
    for _, b := range s.backends {
        status := &quot;up&quot;
        alive := isBackendAlive(b.URL)
        b.SetAlive(alive)
        if !alive {
            status = &quot;down&quot;
        }
        log.Printf(&quot;%s [%s]\n&quot;, b.URL, status)
    }
}
</code></pre><p>&#x5728; Go &#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x8D77;&#x4E00;&#x4E2A;&#x5B9A;&#x65F6;&#x5668;&#x6765;&#x5468;&#x671F;&#x6027;&#x5730;&#x8FD0;&#x884C;&#x5B83;&#x3002;&#x5F53;&#x5B9A;&#x65F6;&#x5668;&#x521B;&#x5EFA;&#x540E;&#xFF0C;&#x4F60;&#x53EF;&#x4EE5;&#x7528;&#x901A;&#x9053;&#x76D1;&#x542C;&#x4E8B;&#x4EF6;&#x3002;</p><pre><code class="language-text">// healthCheck runs a routine for check status of the backends every 20 secs
func healthCheck() {
    t := time.NewTicker(time.Second * 20)
    for {
        select {
        case &lt;-t.C:
            log.Println(&quot;Starting health check...&quot;)
            serverPool.HealthCheck()
            log.Println(&quot;Health check completed&quot;)
        }
    }
}
</code></pre><p>&#x5728;&#x4E0A;&#x4E00;&#x6BB5;&#x4E2D;&#xFF0C;<code>&lt;-t.C</code> &#x901A;&#x9053;&#x4F1A;&#x6BCF; 20 &#x79D2;&#x63A5;&#x6536;&#x4E00;&#x6B21;&#x6570;&#x636E;&#x3002;<code>select</code> &#x63A2;&#x6D4B;&#x8FD9;&#x4E2A;&#x4E8B;&#x4EF6;&#x3002;&#x5982;&#x679C;&#x6CA1;&#x6709; <code>default</code> &#x5206;&#x652F;&#xFF0C;<code>select</code> &#x4F1A;&#x4E00;&#x76F4;&#x7B49;&#x5F85;&#xFF0C;&#x76F4;&#x5230;&#x81F3;&#x5C11;&#x4E00;&#x4E2A;&#x5206;&#x652F;&#x6267;&#x884C;&#x3002;</p><p>&#x6700;&#x540E;&#xFF0C;&#x5728;&#x4E00;&#x4E2A;&#x5355;&#x72EC;&#x7684;&#x534F;&#x7A0B;&#x4E2D;&#x8FD0;&#x884C;&#x3002;</p><h2 id="%E6%80%BB%E7%BB%93"><strong>&#x603B;&#x7ED3;</strong></h2><p>&#x672C;&#x6587;&#x8BB2;&#x4E86;&#x5F88;&#x591A;</p><ul><li>&#x8F6E;&#x8BE2;&#x9009;&#x62E9;</li><li>&#x6807;&#x51C6;&#x5E93;&#x4E2D;&#x7684; ReverseProxy</li><li>Mutex</li><li>&#x539F;&#x5B50;&#x64CD;&#x4F5C;</li><li>&#x95ED;&#x5305;</li><li>&#x56DE;&#x8C03;</li><li>select &#x64CD;&#x4F5C;</li></ul><p>&#x8FD8;&#x6709;&#x5F88;&#x591A;&#x53EF;&#x4EE5;&#x505A;&#x7684;&#x6765;&#x6539;&#x8FDB;&#x6211;&#x4EEC;&#x7684;&#x7B80;&#x6613;&#x8D1F;&#x8F7D;&#x5747;&#x8861;&#x5668;&#x3002;</p><p>&#x4F8B;&#x5982;&#xFF1A;</p><ul><li>&#x7528;&#x5806;&#x6765;&#x5BF9;&#x540E;&#x7AEF;&#x673A;&#x5668;&#x8FDB;&#x884C;&#x6392;&#x5E8F;&#xFF0C;&#x51CF;&#x5C11;&#x641C;&#x7D22;&#x8303;&#x56F4;</li><li>&#x91C7;&#x96C6;&#x7EDF;&#x8BA1;&#x4FE1;&#x606F;</li><li>&#x5B9E;&#x73B0;&#x52A0;&#x6743;&#x8F6E;&#x8BE2;/&#x6700;&#x5C11;&#x8FDE;&#x63A5;</li><li>&#x652F;&#x6301;&#x914D;&#x7F6E;&#x6587;&#x4EF6;</li></ul><p>&#x7B49;&#x7B49;&#x3002;</p><p>&#x4F60;&#x53EF;&#x4EE5;&#x5728;<strong><a href="https://link.zhihu.com/?target=https%3A//github.com/kasvith/simplelb/" rel="nofollow noreferrer">&#x8FD9;&#x91CC;</a></strong>&#x627E;&#x5230;&#x4EE3;&#x7801;&#x5E93;&#x3002;</p>]]></content:encoded></item><item><title><![CDATA[深度剖析 Go 中的 Go 协程 (goroutines) -- Go 的并发]]></title><description><![CDATA[<blockquote>Go &#x534F;&#x7A0B; (goroutine) &#x662F;&#x6307;&#x5728;&#x540E;&#x53F0;&#x4E2D;&#x8FD0;&#x884C;&#x7684;&#x8F7B;&#x91CF;&#x7EA7;&#x6267;&#x884C;&#x7EBF;&#x7A0B;&#xFF0C;go &#x534F;&#x7A0B;&#x662F; Go &#x4E2D;&#x5B9E;&#x73B0;&#x5E76;&#x53D1;&#x7684;&#x5173;&#x952E;&#x7EC4;&#x6210;&#x90E8;&#x5206;&#x3002;</blockquote><p>&#x7531;&#x4E8E; Go &#x534F;&#x7A0B;&#x76F8;&#x5BF9;&#x4E8E;&#x4F20;&#x7EDF;&#x64CD;</p>]]></description><link>http://www.net-e.cn/shen-du-pou-xi-go-zhong-de-go-xie-cheng-goroutines-go-de-bing-fa/</link><guid isPermaLink="false">61502a1e681cac0001a7ef44</guid><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Sun, 26 Sep 2021 08:08:26 GMT</pubDate><content:encoded><![CDATA[<blockquote>Go &#x534F;&#x7A0B; (goroutine) &#x662F;&#x6307;&#x5728;&#x540E;&#x53F0;&#x4E2D;&#x8FD0;&#x884C;&#x7684;&#x8F7B;&#x91CF;&#x7EA7;&#x6267;&#x884C;&#x7EBF;&#x7A0B;&#xFF0C;go &#x534F;&#x7A0B;&#x662F; Go &#x4E2D;&#x5B9E;&#x73B0;&#x5E76;&#x53D1;&#x7684;&#x5173;&#x952E;&#x7EC4;&#x6210;&#x90E8;&#x5206;&#x3002;</blockquote><p>&#x7531;&#x4E8E; Go &#x534F;&#x7A0B;&#x76F8;&#x5BF9;&#x4E8E;&#x4F20;&#x7EDF;&#x64CD;&#x4F5C;&#x7CFB;&#x7EDF;&#x4E2D;&#x7684;&#x7EBF;&#x7A0B; (thread) &#x662F;&#x975E;&#x5E38;&#x8F7B;&#x91CF;&#x7EA7;&#x7684;&#xFF0C;&#x56E0;&#x6B64;&#x5BF9;&#x4E8E;&#x4E00;&#x4E2A;&#x5178;&#x578B;&#x7684; Go &#x5E94;&#x7528;&#x6765;&#x8BF4;&#xFF0C;&#x6709;&#x6570;&#x4EE5;&#x5343;&#x8BA1;&#x7684; Go &#x534F;&#x7A0B;&#x5E76;&#x53D1;&#x8FD0;&#x884C;&#x7684;&#x60C5;&#x5F62;&#x662F;&#x5341;&#x5206;&#x5E38;&#x89C1;&#x7684;&#x3002;&#x5E76;&#x53D1;&#x53EF;&#x4EE5;&#x663E;&#x8457;&#x5730;&#x63D0;&#x5347;&#x5E94;&#x7528;&#x7684;&#x8FD0;&#x884C;&#x901F;&#x5EA6;&#xFF0C;&#x5E76;&#x4E14;&#x53EF;&#x4EE5;&#x5E2E;&#x52A9;&#x6211;&#x4EEC;&#x7F16;&#x5199;&#x5173;&#x6CE8;&#x70B9;&#x5206;&#x79BB;&#xFF08;Separation of concerns&#xFF0C;Soc&#xFF09;&#x7684;&#x4EE3;&#x7801;&#x3002;</p><h2 id="%E4%BB%80%E4%B9%88%E6%98%AF-go-%E5%8D%8F%E7%A8%8B%EF%BC%9F"><strong>&#x4EC0;&#x4E48;&#x662F; Go &#x534F;&#x7A0B;&#xFF1F;</strong></h2><p>&#x6211;&#x4EEC;&#x4E5F;&#x8BB8;&#x5728;&#x7406;&#x8BBA;&#x4E0A;&#x5DF2;&#x7ECF;&#x77E5;&#x6653; Go &#x534F;&#x7A0B;&#x662F;&#x5982;&#x4F55;&#x5DE5;&#x4F5C;&#x7684;&#xFF0C;&#x4F46;&#x662F;&#x5728;&#x4EE3;&#x7801;&#x5C42;&#x7EA7;&#x4E0A;&#xFF0C;go &#x534F;&#x7A0B;&#x4F55;&#x8BB8;&#x7269;&#x4E5F;&#xFF1F;&#x5176;&#x5B9E;&#xFF0C;go &#x534F;&#x7A0B;&#x770B;&#x8D77;&#x6765;&#x53EA;&#x662F;&#x4E00;&#x4E2A;&#x4E0E;&#x5176;&#x4ED6;&#x4F17; Go &#x534F;&#x7A0B;&#x5E76;&#x53D1;&#x8FD0;&#x884C;&#x7684;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x51FD;&#x6570;&#x6216;&#x8005;&#x65B9;&#x6CD5;&#xFF0C;&#x4F46;&#x662F;&#x6211;&#x4EEC;&#x5E76;&#x4E0D;&#x80FD;&#x60F3;&#x5F53;&#x7136;&#x5730;&#x4ECE;&#x51FD;&#x6570;&#x6216;&#x8005;&#x65B9;&#x6CD5;&#x4E2D;&#x7684;&#x5B9A;&#x4E49;&#x6765;&#x786E;&#x5B9A;&#x4E00;&#x4E2A; Go &#x534F;&#x7A0B;&#xFF0C;go &#x534F;&#x7A0B;&#x7684;&#x786E;&#x5B9A;&#x8FD8;&#x662F;&#x8981;&#x53D6;&#x51B3;&#x4E8E;&#x6211;&#x4EEC;&#x5982;&#x4F55;&#x53BB;&#x8C03;&#x7528;&#x3002;</p><p>Go &#x4E2D;&#x63D0;&#x4F9B;&#x4E86;&#x4E00;&#x4E2A;&#x5173;&#x952E;&#x5B57; <code>go</code> &#x6765;&#x8BA9;&#x6211;&#x4EEC;&#x521B;&#x5EFA;&#x4E00;&#x4E2A; Go &#x534F;&#x7A0B;&#xFF0C;&#x5F53;&#x6211;&#x4EEC;&#x5728;&#x51FD;&#x6570;&#x6216;&#x65B9;&#x6CD5;&#x7684;&#x8C03;&#x7528;&#x4E4B;&#x524D;&#x6DFB;&#x52A0;&#x4E00;&#x4E2A;&#x5173;&#x952E;&#x5B57; <code>go</code>&#xFF0C;&#x8FD9;&#x6837;&#x6211;&#x4EEC;&#x5C31;&#x5F00;&#x542F;&#x4E86;&#x4E00;&#x4E2A; Go &#x534F;&#x7A0B;&#xFF0C;&#x8BE5;&#x51FD;&#x6570;&#x6216;&#x8005;&#x65B9;&#x6CD5;&#x5C31;&#x4F1A;&#x5728;&#x8FD9;&#x4E2A; Go &#x534F;&#x7A0B;&#x4E2D;&#x8FD0;&#x884C;&#x3002;</p><p>&#x4E3E;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x6817;&#x5B50;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-8a8760f78d1ad2042a4e043ddad83ade_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/pIGsToIA2hL" rel="nofollow noreferrer">https://play.golang.org/p/pIGsToIA2hL</a></p><p>&#x5728;&#x4E0A;&#x9762;&#x7684;&#x4EE3;&#x7801;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x5B9A;&#x4E49;&#x4E86;&#x4E00;&#x4E2A;&#x53EF;&#x4EE5;&#x5728;&#x63A7;&#x5236;&#x53F0;&#x8F93;&#x51FA; <code>Hello World</code> &#x5B57;&#x7B26;&#x4E32;&#x7684; <code>printHello</code> &#x7684;&#x51FD;&#x6570;&#xFF0C;&#x5728; <code>main</code> &#x51FD;&#x6570;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x5C31;&#x50CF;&#x5E73;&#x65F6;&#x90A3;&#x6837;&#x8C03;&#x7528; <code>printHello</code> &#x51FD;&#x6570;&#xFF0C;&#x6700;&#x7EC8;&#x4E5F;&#x662F;&#x7406;&#x6240;&#x5F53;&#x7136;&#x5730;&#x83B7;&#x5F97;&#x4E86;&#x671F;&#x671B;&#x7684;&#x7ED3;&#x679C;&#x3002;</p><p>&#x4E0B;&#x9762;&#xFF0C;&#x8BA9;&#x6211;&#x4EEC;&#x5C1D;&#x8BD5;&#x4ECE;&#x540C;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#x521B;&#x5EFA; Go &#x534F;&#x7A0B;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-c24a22d0d81cfd8aaa5bce6d558df000_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/LWXAgDpTcJP" rel="nofollow noreferrer">https://play.golang.org/p/LWXAgDpTcJP</a></p><p>&#x6839;&#x636E; Go &#x534F;&#x7A0B;&#x7684;&#x8BED;&#x6CD5;&#xFF0C;&#x6211;&#x4EEC;&#x5728;&#x51FD;&#x6570;&#x8C03;&#x7528;&#x7684;&#x524D;&#x9762;&#x589E;&#x52A0;&#x4E86;&#x4E00;&#x4E2A; <code>go</code> &#x5173;&#x952E;&#x5B57;&#xFF0C;&#x4E4B;&#x540E;&#x7A0B;&#x5E8F;&#x8FD0;&#x884C;&#x6B63;&#x5E38;&#xFF0C;&#x8F93;&#x51FA;&#x4E86;&#x4EE5;&#x4E0B;&#x7684;&#x7ED3;&#x679C;&#xFF1A;</p><pre><code class="language-text">main execution started
main execution stopped
</code></pre><p>&#x5947;&#x602A;&#x7684;&#x662F;&#xFF0C;<code>Hello World</code> &#x5E76;&#x6CA1;&#x6709;&#x5982;&#x540C;&#x6211;&#x4EEC;&#x9884;&#x6599;&#x7684;&#x90A3;&#x6837;&#x8F93;&#x51FA;&#xFF0C;&#x8FD9;&#x671F;&#x95F4;&#x7A76;&#x7ADF;&#x53D1;&#x751F;&#x4E86;&#x4EC0;&#x4E48;&#xFF1F;</p><p>go &#x534F;&#x7A0B;&#x603B;&#x662F;&#x5728;&#x540E;&#x53F0;&#x8FD0;&#x884C;&#xFF0C;&#x5F53;&#x4E00;&#x4E2A; Go &#x534F;&#x7A0B;&#x6267;&#x884C;&#x7684;&#x65F6;&#x5019;&#xFF08;&#x5728;&#x8FD9;&#x4E2A;&#x4F8B;&#x5B50;&#x4E2D;&#x662F; <code>go printHello()</code>&#xFF09;, Go &#x5E76;&#x4E0D;&#x4F1A;&#x50CF;&#x5728;&#x4E4B;&#x524D;&#x7684;&#x90A3;&#x4E2A;&#x4F8B;&#x5B50;&#x4E2D;&#x5728;&#x6267;&#x884C; <code>printHello</code> &#x4E2D;&#x7684;&#x529F;&#x80FD;&#x65F6;&#x963B;&#x585E; main &#x51FD;&#x6570;&#x4E2D;&#x5269;&#x4E0B;&#x8BED;&#x53E5;&#x7684;&#x6267;&#x884C;&#xFF0C;&#x800C;&#x662F;&#x76F4;&#x63A5;&#x5FFD;&#x7565;&#x4E86; Go &#x534F;&#x7A0B;&#x7684;&#x8FD4;&#x56DE;&#x5E76;&#x7EE7;&#x7EED;&#x6267;&#x884C; main &#x51FD;&#x6570;&#x5269;&#x4E0B;&#x7684;&#x8BED;&#x53E5;&#x3002;<strong>&#x5373;&#x4FBF;&#x5982;&#x6B64;&#xFF0C;&#x6211;&#x4EEC;&#x4E3A;&#x4EC0;&#x4E48;&#x6CA1;&#x6CD5;&#x770B;&#x5230;&#x51FD;&#x6570;&#x7684;&#x8F93;&#x51FA;&#x5462;&#xFF1F;</strong></p><p>&#x5728;&#x9ED8;&#x8BA4;&#x60C5;&#x51B5;&#x4E0B;&#xFF0C;&#x6BCF;&#x4E2A;&#x72EC;&#x7ACB;&#x7684; Go &#x5E94;&#x7528;&#x8FD0;&#x884C;&#x65F6;&#x5C31;&#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A; Go &#x534F;&#x7A0B;&#xFF0C;&#x5176; <code>main</code> &#x51FD;&#x6570;&#x5C31;&#x5728;&#x8FD9;&#x4E2A; Go &#x534F;&#x7A0B;&#x4E2D;&#x8FD0;&#x884C;&#xFF0C;&#x8FD9;&#x4E2A; Go &#x534F;&#x7A0B;&#x5C31;&#x88AB;&#x79F0;&#x4E3A; <code>go &#x4E3B;&#x534F;&#x7A0B;&#xFF08;main Goroutine&#xFF0C;&#x4E0B;&#x9762;&#x7B80;&#x79F0;&#x4E3B;&#x534F;&#x7A0B;&#xFF09;</code>&#x3002;&#x5728;&#x4E0A;&#x9762;&#x7684;&#x4F8B;&#x5B50;&#x4E2D;&#xFF0C;<code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x4E2D;&#x53C8;&#x4EA7;&#x751F;&#x4E86;&#x4E00;&#x4E2A; <code>printHello</code> &#x8FD9;&#x4E2A;&#x51FD;&#x6570;&#x7684; Go &#x534F;&#x7A0B;&#xFF0C;&#x6211;&#x4EEC;&#x6682;&#x4E14;&#x53EB;&#x5B83; <code>printHello &#x534F;&#x7A0B;</code> &#x5427;&#xFF0C;&#x56E0;&#x800C;&#x6211;&#x4EEC;&#x5728;&#x6267;&#x884C;&#x4E0A;&#x9762;&#x7684;&#x7A0B;&#x5E8F;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x5C31;&#x4F1A;&#x5B58;&#x5728;&#x4E24;&#x4E2A; Go &#x534F;&#x7A0B;&#xFF08;<code>main</code> &#x548C; <code>printHello</code>&#xFF09;&#x540C;&#x65F6;&#x8FD0;&#x884C;&#x3002;&#x6B63;&#x5982;&#x540C;&#x4EE5;&#x524D;&#x7684;&#x7A0B;&#x5E8F;&#x90A3;&#x6837;&#xFF0C;go &#x534F;&#x7A0B;&#x4EEC;&#x4F1A;&#x8FDB;&#x884C;&#x534F;&#x540C;&#x8C03;&#x5EA6;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x5F53; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x8FD0;&#x884C;&#x7684;&#x65F6;&#x5019;&#xFF0C;Go &#x8C03;&#x5EA6;&#x5668;&#x5728; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x6267;&#x884C;&#x5B8C;&#x4E4B;&#x524D;&#x5E76;&#x4E0D;&#x4F1A;&#x5C06;&#x63A7;&#x5236;&#x6743;&#x79FB;&#x4EA4;&#x7ED9; <code>printHello &#x534F;&#x7A0B;</code>&#x3002;&#x4E0D;&#x5E78;&#x7684;&#x662F;&#xFF0C;&#x4E00;&#x65E6; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x6267;&#x884C;&#x5B8C;&#x6BD5;&#xFF0C;&#x6574;&#x4E2A;&#x7A0B;&#x5E8F;&#x4F1A;&#x7ACB;&#x5373;&#x7EC8;&#x6B62;&#xFF0C;&#x8C03;&#x5EA6;&#x5668;&#x518D;&#x4E5F;&#x6CA1;&#x6709;&#x65F6;&#x95F4;&#x7559;&#x7ED9; <code>printHello &#x534F;&#x7A0B;</code> &#x53BB;&#x8FD0;&#x884C;&#x4E86;&#x3002;</p><p>&#x4F46;&#x6B63;&#x5982;&#x6211;&#x4EEC;&#x4ECE;&#x5176;&#x4ED6;&#x8BFE;&#x7A0B;&#x6240;&#x77E5;&#xFF0C;&#x901A;&#x8FC7;&#x963B;&#x585E;&#x6761;&#x4EF6;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x624B;&#x52A8;&#x5C06;&#x63A7;&#x5236;&#x6743;&#x8F6C;&#x79FB;&#x7ED9;&#x5176;&#x4ED6;&#x7684; Go &#x534F;&#x7A0B; , &#x4E5F;&#x53EF;&#x4EE5;&#x8BF4;&#x662F;&#x544A;&#x8BC9;&#x8C03;&#x5EA6;&#x5668;&#x8BA9;&#x5B83;&#x53BB;&#x8C03;&#x5EA6;&#x5176;&#x4ED6;&#x53EF;&#x7528;&#x7A7A;&#x95F2;&#x7684; Go &#x534F;&#x7A0B;&#x3002;&#x8BA9;&#x6211;&#x4EEC;&#x8C03;&#x7528; <code>time.Sleep()</code> &#x51FD;&#x6570;&#x53BB;&#x5B9E;&#x73B0;&#x5B83;&#x5427;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-9ca32a567ee3de28eeb779298d39eafa_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/ujQKjpALlRJ" rel="nofollow noreferrer">https://play.golang.org/p/ujQKjpALlRJ</a></p><p>&#x5982;&#x4E0A;&#x56FE;&#x6240;&#x793A;&#xFF0C;&#x6211;&#x4EEC;&#x4FEE;&#x6539;&#x4E86;&#x7A0B;&#x5E8F;&#xFF0C;&#x7A0B;&#x5E8F;&#x5728; main &#x51FD;&#x6570;&#x7684;&#x6700;&#x540E;&#x4E00;&#x6761;&#x8BED;&#x53E5;&#x4E4B;&#x524D;&#x8C03;&#x7528;&#x4E86; <code>time.Sleep(10 * time.Millisecond)</code>&#xFF0C;&#x4F7F;&#x5F97; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x5728;&#x6267;&#x884C;&#x6700;&#x540E;&#x4E00;&#x6761;&#x6307;&#x4EE4;&#x4E4B;&#x524D;&#x8C03;&#x5EA6;&#x5668;&#x5C31;&#x5C06;&#x63A7;&#x5236;&#x6743;&#x8F6C;&#x79FB;&#x7ED9;&#x4E86; <code>printhello &#x534F;&#x7A0B;</code>&#x3002;&#x5728;&#x8FD9;&#x4E2A;&#x4F8B;&#x5B50;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x901A;&#x8FC7;&#x8C03;&#x7528; <code>time.Sleep(10 * time.Millisecond)</code> &#x5F3A;&#x884C;&#x8BA9; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x4F11;&#x7720; 10ms &#x5E76;&#x4E14;&#x5728;&#x5728;&#x8FD9;&#x4E2A; 10ms &#x5185;&#x4E0D;&#x4F1A;&#x518D;&#x88AB;&#x8C03;&#x5EA6;&#x5668;&#x91CD;&#x65B0;&#x8C03;&#x5EA6;&#x8FD0;&#x884C;&#x3002;</p><p>&#x4E00;&#x65E6; <code>printHello &#x534F;&#x7A0B;</code> &#x6267;&#x884C;&#xFF0C;&#x5B83;&#x5C31;&#x4F1A;&#x5411;&#x63A7;&#x5236;&#x53F0;&#x6253;&#x5370;&#x2018; Hello World &#xFF01;&#x2019;&#xFF0C;&#x7136;&#x540E;&#x8BE5; Go &#x534F;&#x7A0B;&#xFF08;<code>printHello &#x534F;&#x7A0B;</code>&#xFF09;&#x5C31;&#x4F1A;&#x968F;&#x4E4B;&#x7EC8;&#x6B62;&#xFF0C;&#x63A5;&#x4E0B;&#x6765; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x5C31;&#x4F1A;&#x88AB;&#x91CD;&#x65B0;&#x8C03;&#x5EA6;&#xFF08;&#x56E0;&#x4E3A; main Go &#x534F;&#x7A0B;&#x5DF2;&#x7ECF;&#x7761;&#x591F; 10ms &#x4E86;&#xFF09;&#xFF0C;&#x5E76;&#x6267;&#x884C;&#x6700;&#x540E;&#x4E00;&#x6761;&#x8BED;&#x53E5;&#x3002;&#x56E0;&#x6B64;&#xFF0C;&#x8FD0;&#x884C;&#x4E0A;&#x9762;&#x7684;&#x7A0B;&#x5E8F;&#x5C31;&#x4F1A;&#x5F97;&#x5230;&#x4EE5;&#x4E0B;&#x7684;&#x8F93;&#x51FA; :</p><pre><code class="language-text">main execution started
Hello World!
main execution stopped
</code></pre><p>&#x4E0B;&#x9762;&#x6211;&#x7A0D;&#x5FAE;&#x4FEE;&#x6539;&#x4E00;&#x4E0B;&#x4F8B;&#x5B50;&#xFF0C;&#x6211;&#x5728; <code>printHello</code> &#x51FD;&#x6570;&#x7684;&#x8F93;&#x51FA;&#x8BED;&#x53E5;&#x4E4B;&#x524D;&#x6DFB;&#x52A0;&#x4E86;&#x4E00;&#x6761; <code>time.Sleep(time.Millisecond)</code>&#x3002;&#x6211;&#x4EEC;&#x5DF2;&#x7ECF;&#x77E5;&#x9053;&#x4E86;&#x5982;&#x679C;&#x6211;&#x4EEC;&#x5728;&#x51FD;&#x6570;&#x4E2D;&#x8C03;&#x7528;&#x4E86;&#x4F11;&#x7720;&#xFF08;sleep&#xFF09;&#x51FD;&#x6570;&#xFF0C;&#x8FD9;&#x4E2A;&#x51FD;&#x6570;&#x5C31;&#x4F1A;&#x544A;&#x8BC9; Go &#x8C03;&#x5EA6;&#x5668;&#x53BB;&#x8C03;&#x5EA6;&#x5176;&#x4ED6;&#x53EF;&#x88AB;&#x8C03;&#x5EA6;&#x7684; Go &#x534F;&#x7A0B;&#x3002;&#x5728;&#x4E0A;&#x4E00;&#x8BFE;&#x4E2D;&#x63D0;&#x5230;&#xFF0C;&#x53EA;&#x6709;&#x975E;&#x4F11;&#x7720;&#xFF08;<code>non-sleeping</code>&#xFF09;&#x7684; Go &#x534F;&#x7A0B;&#x624D;&#x4F1A;&#x88AB;&#x8BA4;&#x4E3A;&#x662F;&#x53EF;&#x88AB;&#x8C03;&#x5EA6;&#x7684;&#xFF0C;&#x6240;&#x4EE5;&#x4E3B;&#x534F;&#x7A0B;&#x5728;&#x8FD9;&#x4F11;&#x7720;&#x7684; 10ms &#x5185;&#x662F;&#x4E0D;&#x4F1A;&#x88AB;&#x518D;&#x6B21;&#x8C03;&#x5EA6;&#x7684;&#x3002;&#x56E0;&#x6B64; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x5148;&#x6253;&#x5370;&#x51FA;&#x201C; main execution started &#x201D; &#x63A5;&#x7740;&#x5C31;&#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A; <strong>printHello</strong> &#x534F;&#x7A0B;&#xFF0C;<em>&#x9700;&#x8981;&#x6CE8;&#x610F;&#x6B64;&#x65F6;&#x7684; <code>&#x4E3B;&#x534F;&#x7A0B;</code> &#x8FD8;&#x662F;&#x975E;&#x4F11;&#x7720;&#x72B6;&#x6001;&#x7684;</em>&#xFF0C;&#x5728;&#x8FD9;&#x4E4B;&#x540E;&#x4E3B;&#x534F;&#x7A0B;&#x5C31;&#x8981;&#x8C03;&#x7528;&#x4F11;&#x7720;&#x51FD;&#x6570;&#x53BB;&#x7761; 10ms&#xFF0C;&#x5E76;&#x4E14;&#x628A;&#x8FD9;&#x4E2A;&#x63A7;&#x5236;&#x6743;&#x8BA9;&#x51FA;&#x6765;&#x7ED9;<strong>printHello</strong> &#x534F;&#x7A0B;&#x3002;<strong>printHello</strong> &#x534F;&#x7A0B;&#x4F1A;&#x5148;&#x4F11;&#x7720; 1ms &#x544A;&#x8BC9;&#x8C03;&#x5EA6;&#x5668;&#x770B;&#x770B;&#x6709;&#x6CA1;&#x6709;&#x5176;&#x4ED6;&#x53EF;&#x8C03;&#x5EA6;&#x7684; Go &#x534F;&#x7A0B;&#xFF0C;&#x5728;&#x8FD9;&#x4E2A;&#x4F8B;&#x5B50;&#x91CC;&#x663E;&#x7136;&#x6CA1;&#x6709;&#x5176;&#x4ED6;&#x53EF;&#x8C03;&#x5EA6;&#x7684; Go &#x534F;&#x7A0B;&#x4E86;&#xFF0C;&#x6240;&#x4EE5;&#x5728;<strong>printHello</strong>&#x534F;&#x7A0B;&#x7ED3;&#x675F;&#x4E86;&#x8FD9; 1ms &#x7684;&#x4F11;&#x7720;&#x6237;&#x5C31;&#x4F1A;&#x88AB;&#x8C03;&#x5EA6;&#x5668;&#x8C03;&#x5EA6;&#xFF0C;&#x63A5;&#x7740;&#x5C31;&#x8F93;&#x51FA;&#x4E86;&#x201C; Hello World &#x201D;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;&#x4E4B;&#x540E;&#x8FD9;&#x4E2A; Go &#x534F;&#x7A0B;&#x8FD0;&#x884C;&#x7ED3;&#x675F;&#x3002;&#x4E4B;&#x540E;&#xFF0C;&#x4E3B;&#x534F;&#x7A0B;&#x4F1A;&#x5728;&#x4E4B;&#x540E;&#x7684;&#x51E0;&#x6BEB;&#x79D2;&#x88AB;&#x5524;&#x9192;&#xFF0C;&#x7D27;&#x63A5;&#x7740;&#x5C31;&#x4F1A;&#x8F93;&#x51FA;&#x201C; main execution stopped &#x201D;&#x5E76;&#x4E14;&#x7ED3;&#x675F;&#x6574;&#x4E2A;&#x7A0B;&#x5E8F;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic1.zhimg.com/80/v2-a68881b2101b68dbc84c610746f14c64_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/rWvzS8UeqD6" rel="nofollow noreferrer">https://play.golang.org/p/rWvzS8UeqD6</a></p><p>&#x4E0A;&#x9762;&#x7684;&#x7A0B;&#x5E8F;&#x4F9D;&#x65E7;&#x548C;&#x4E4B;&#x524D;&#x7684;&#x4F8B;&#x5B50;&#x4E00;&#x6837;&#xFF0C;&#x8F93;&#x51FA;&#x4EE5;&#x4E0B;&#x76F8;&#x540C;&#x7684;&#x7ED3;&#x679C;&#xFF1A;</p><pre><code class="language-text">main execution started
Hello World!
main execution stopped
</code></pre><p>&#x8981;&#x662F;&#xFF0C;&#x6211;&#x628A;&#x8FD9;&#x4E2A;<strong>printHello</strong> &#x534F;&#x7A0B;&#x4E2D;&#x7684;&#x4F11;&#x7720; 1 &#x6BEB;&#x79D2;&#x6539;&#x6210;&#x4F11;&#x7720; 15 &#x6BEB;&#x79D2;&#xFF0C;&#x8FD9;&#x4E2A;&#x7ED3;&#x679C;&#x53C8;&#x662F;&#x5982;&#x4F55;&#x5462;&#xFF1F;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-d5e629e733101a1395d66f33fd2bf136_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/Pc2nP2BtRiP" rel="nofollow noreferrer">https://play.golang.org/p/Pc2nP2BtRiP</a></p><p>&#x5728;&#x8FD9;&#x4E2A;&#x4F8B;&#x5B50;&#x4E2D;&#xFF0C;&#x4E0E;&#x5176;&#x4ED6;&#x7684;&#x4F8B;&#x5B50;&#x6700;&#x5927;&#x7684;&#x533A;&#x522B;&#x5C31;&#x662F;<strong>printHello</strong> &#x534F;&#x7A0B;&#x6BD4;&#x4E3B;&#x534F;&#x7A0B;&#x7684;&#x4F11;&#x7720;&#x65F6;&#x95F4;&#x8FD8;&#x8981;&#x957F;&#xFF0C;&#x5F88;&#x660E;&#x663E;&#xFF0C;&#x4E3B;&#x534F;&#x7A0B;&#x8981;&#x6BD4; printHello &#x534F;&#x7A0B;&#x5524;&#x9192;&#x8981;&#x65E9;&#xFF0C;&#x8FD9;&#x6837;&#x7684;&#x7ED3;&#x679C;&#x5C31;&#x662F;&#x4E3B;&#x534F;&#x7A0B;&#x5373;&#x4F7F;&#x5524;&#x9192;&#x540E;&#x6267;&#x884C;&#x5B8C;&#x6240;&#x6709;&#x7684;&#x8BED;&#x53E5;&#xFF0C;printHello &#x534F;&#x7A0B;&#x8FD8;&#x662F;&#x5728;&#x4F11;&#x7720;&#x72B6;&#x6001;&#x3002;&#x4E4B;&#x524D;&#x63D0;&#x5230;&#x8FC7;&#xFF0C;&#x4E3B;&#x534F;&#x7A0B;&#x6BD4;&#x8F83;&#x7279;&#x6B8A;&#xFF0C;&#x5982;&#x679C;&#x4E3B;&#x534F;&#x7A0B;&#x6267;&#x884C;&#x7ED3;&#x675F;&#x540E;&#x6574;&#x4E2A;&#x7A0B;&#x5E8F;&#x5C31;&#x8981;&#x9000;&#x51FA;&#xFF0C;&#x6240;&#x4EE5; printHello &#x534F;&#x7A0B;&#x5F97;&#x4E0D;&#x5230;&#x673A;&#x4F1A;&#x53BB;&#x6267;&#x884C;&#x4E0B;&#x9762;&#x7684;&#x8F93;&#x51FA;&#x7684;&#x8BED;&#x53E5;&#x4E86;&#xFF0C;&#x6240;&#x4EE5;&#x4EE5;&#x4E0A;&#x7684;&#x7A0B;&#x5E8F;&#x7684;&#x6570;&#x636E;&#x7ED3;&#x679C;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">main execution started
main execution stopped
</code></pre><h2 id="%E4%BD%BF%E7%94%A8%E5%A4%9A-go-%E5%8D%8F%E7%A8%8B"><strong>&#x4F7F;&#x7528;&#x591A; Go &#x534F;&#x7A0B;</strong></h2><p>&#x5C31;&#x50CF;&#x4E4B;&#x524D;&#x6211;&#x6240;&#x63D0;&#x5230;&#x8FC7;&#x7684;&#xFF0C;&#x4F60;&#x53EF;&#x4EE5;&#x968F;&#x5FC3;&#x6240;&#x6B32;&#x5730;&#x521B;&#x5EFA;&#x591A;&#x4E2A; Go &#x534F;&#x7A0B;&#x3002;&#x4E0B;&#x9762;&#x8BA9;&#x6211;&#x4EEC;&#x5B9A;&#x4E49;&#x4E24;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x51FD;&#x6570;&#xFF0C;&#x4E00;&#x4E2A;&#x662F;&#x7528;&#x4E8E;&#x987A;&#x5E8F;&#x6253;&#x5370;&#x67D0;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#x4E2D;&#x7684;&#x6BCF;&#x4E2A;&#x5B57;&#x7B26;&#xFF0C;&#x53E6;&#x4E00;&#x4E2A;&#x662F;&#x987A;&#x5E8F;&#x6253;&#x5370;&#x51FA;&#x67D0;&#x4E2A;&#x6574;&#x6570;&#x5207;&#x7247;&#x4E2D;&#x7684;&#x6BCF;&#x4E2A;&#x6570;&#x5B57;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-08d66df77b0904a1e4a4ae8b1b9fe1a7_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/SJano_g1wTV" rel="nofollow noreferrer">https://play.golang.org/p/SJano_g1wTV</a></p><p>&#x5728;&#x4E0A;&#x56FE;&#x4E2D;&#x7684;&#x7A0B;&#x5E8F;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x8FDE;&#x7EED;&#x5730;&#x521B;&#x5EFA;&#x4E86;&#x4E24;&#x4E2A; Go &#x534F;&#x7A0B;&#xFF0C;&#x7A0B;&#x5E8F;&#x8F93;&#x51FA;&#x7684;&#x7ED3;&#x679C;&#x5982;&#x4E0B;&#xFF1A;</p><pre><code class="language-text">main execution started
H e l l o 1 2 3 4 5
main execution stopped
</code></pre><p>&#x4E0A;&#x9762;&#x7684;&#x7ED3;&#x679C;&#x8BC1;&#x5B9E;&#x4E86; Go &#x534F;&#x7A0B;&#x662F;&#x4EE5;&#x5408;&#x4F5C;&#x5F0F;&#x8C03;&#x5EA6;&#x6765;&#x8FD0;&#x4F5C;&#x7684;&#x3002;&#x4E0B;&#x9762;&#x6211;&#x4EEC;&#x5728;&#x6BCF;&#x4E2A;&#x51FD;&#x6570;&#x4E2D;&#x7684;&#x8F93;&#x51FA;&#x8BED;&#x53E5;&#x7684;&#x4E0B;&#x9762;&#x6DFB;&#x52A0;&#x4E00;&#x884C; <code>time.Sleep</code>&#xFF0C;&#x8BA9;&#x51FD;&#x6570;&#x5728;&#x8F93;&#x51FA;&#x6BCF;&#x4E2A;&#x5B57;&#x7B26;&#x6216;&#x6570;&#x5B57;&#x540E;&#x4F11;&#x606F;&#x4E00;&#x6BB5;&#x65F6;&#x95F4;&#xFF0C;&#x597D;&#x8BA9;&#x8C03;&#x5EA6;&#x5668;&#x8C03;&#x5EA6;&#x5176;&#x4ED6;&#x53EF;&#x7528;&#x7684; Go &#x534F;&#x7A0B;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic2.zhimg.com/80/v2-366b939559697be53cf73728486a9321_720w.jpg" class="kg-image" alt loading="lazy"></figure><p><a href="https://link.zhihu.com/?target=https%3A//play.golang.org/p/lrSIEdNxSaH" rel="nofollow noreferrer">https://play.golang.org/p/lrSIEdNxSaH</a></p><p>&#x5728;&#x4E0A;&#x9762;&#x7684;&#x7A0B;&#x5E8F;&#x4E2D;&#xFF0C;&#x6211;&#x53C8;&#x4FEE;&#x6539;&#x4E86;&#x4E00;&#x4E0B;&#x8F93;&#x51FA;&#x8BED;&#x53E5;&#x4F7F;&#x5F97;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x6BCF;&#x4E2A;&#x5B57;&#x7B26;&#x6216;&#x6570;&#x5B57;&#x7684;&#x8F93;&#x51FA;&#x65F6;&#x523B;&#x3002;&#x7406;&#x8BBA;&#x4E0A;&#x4E3B;&#x534F;&#x7A0B;&#x4F1A;&#x4F11;&#x7720; 200ms&#xFF0C;&#x56E0;&#x6B64;&#x5176;&#x4ED6; Go &#x534F;&#x7A0B;&#x8981;&#x8D76;&#x5728;&#x4E3B;&#x534F;&#x7A0B;&#x5524;&#x9192;&#x4E4B;&#x524D;&#x505A;&#x5B8C;&#x81EA;&#x5DF1;&#x7684;&#x5DE5;&#x4F5C;&#xFF0C;&#x56E0;&#x4E3A;&#x4E3B;&#x534F;&#x7A0B;&#x5524;&#x9192;&#x4E4B;&#x540E;&#x5C31;&#x4F1A;&#x5BFC;&#x81F4;&#x7A0B;&#x5E8F;&#x9000;&#x51FA;&#x3002;<code>getChars</code> &#x534F;&#x7A0B;&#x6BCF;&#x6253;&#x5370;&#x4E00;&#x4E2A;&#x5B57;&#x7B26;&#x5C31;&#x4F1A;&#x4F11;&#x7720; 10ms&#xFF0C;&#x4E4B;&#x540E;&#x63A7;&#x5236;&#x6743;&#x5C31;&#x4F1A;&#x4F20;&#x7ED9; <code>getDigits</code> &#x534F;&#x7A0B;&#xFF0C;<code>getDigits</code> &#x534F;&#x7A0B;&#x6BCF;&#x6253;&#x5370;&#x4E00;&#x4E2A;&#x6570;&#x5B57;&#x540E;&#x5C31;&#x4F11;&#x7720; 30ms&#xFF0C;&#x82E5; <code>getChars</code> &#x534F;&#x7A0B;&#x5524;&#x9192;&#xFF0C;&#x5219;&#x4F1A;&#x628A;&#x63A7;&#x5236;&#x6743;&#x4F20;&#x56DE; <code>getChars</code> &#x534F;&#x7A0B;&#xFF0C;&#x5982;&#x6B64;&#x5F80;&#x590D;&#x3002;&#x5728;&#x4EE3;&#x7801;&#x4E2D;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;<code>getChars</code> &#x534F;&#x7A0B;&#x4F1A;&#x5728;&#x5176;&#x4ED6;&#x534F;&#x7A0B;&#x4F11;&#x7720;&#x7684;&#x65F6;&#x5019;&#x591A;&#x6B21;&#x8FDB;&#x884C;&#x6253;&#x5370;&#x5B57;&#x7B26;&#x4EE5;&#x53CA;&#x4F11;&#x7720;&#x64CD;&#x4F5C;&#xFF0C;&#x6240;&#x4EE5;&#x6211;&#x4EEC;&#x9884;&#x8BA1;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x8F93;&#x51FA;&#x7684;&#x5B57;&#x7B26;&#x6BD4;&#x6570;&#x5B57;&#x66F4;&#x5177;&#x6709;&#x8FDE;&#x7EED;&#x6027;&#x3002;</p><p>&#x6211;&#x4EEC;&#x5728; Windows &#x4E0A;&#x8FD0;&#x884C;&#x4E0A;&#x9762;&#x7684;&#x7A0B;&#x5E8F;&#xFF0C;&#x5F97;&#x5230;&#x4E86;&#x4EE5;&#x4E0B;&#x7684;&#x7ED3;&#x679C;&#xFF1A;</p><pre><code class="language-text">main execution started at time 0s
H at time 1.0012ms                         &lt;-|
1 at time 1.0012ms                           | almost at the same time
e at time 11.0283ms                        &lt;-|
l at time 21.0289ms                          | ~10ms apart
l at time 31.0416ms
2 at time 31.0416ms
o at time 42.0336ms
3 at time 61.0461ms                        &lt;-|
4 at time 91.0647ms                          |
5 at time 121.0888ms                         | ~30ms apart
main execution stopped at time 200.3137ms    | exiting after 200ms
</code></pre><p>&#x901A;&#x8FC7;&#x4EE5;&#x4E0A;&#x8F93;&#x51FA;&#x7ED3;&#x679C;&#x53EF;&#x4EE5;&#x8BC1;&#x660E;&#x6211;&#x4EEC;&#x4E4B;&#x524D;&#x5BF9;&#x8F93;&#x51FA;&#x7684;&#x8BA8;&#x8BBA;&#x3002;&#x5BF9;&#x4E8E;&#x8FD9;&#x4E2A;&#x7ED3;&#x679C;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;&#x4E0B;&#x9762;&#x7684;&#x7684;&#x7A0B;&#x5E8F;&#x8FD0;&#x884C;&#x56FE;&#x6765;&#x89E3;&#x91CA;&#x3002;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#xFF0C;&#x6211;&#x4EEC;&#x5728;&#x56FE;&#x4E2D;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x8F93;&#x51FA;&#x8BED;&#x53E5;&#x5927;&#x7EA6;&#x4F1A;&#x82B1;&#x8D39; 1ms &#x7684; CPU &#x65F6;&#x95F4;&#xFF0C;&#x800C;&#x8FD9;&#x4E2A;&#x65F6;&#x95F4;&#x76F8;&#x5BF9;&#x4E8E; 200ms &#x6765;&#x8BF4;&#x662F;&#x53EF;&#x4EE5;&#x5FFD;&#x7565;&#x4E0D;&#x8BA1;&#x7684;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://pic4.zhimg.com/80/v2-fddc16e5abc471fd11e77acb832f5cc3_720w.jpg" class="kg-image" alt loading="lazy"></figure><p>&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x5DF2;&#x7ECF;&#x77E5;&#x9053;&#x4E86;&#x5982;&#x4F55;&#x53BB;&#x521B;&#x5EFA; Go &#x534F;&#x7A0B;&#x4EE5;&#x53CA;&#x53BB;&#x5982;&#x4F55;&#x53BB;&#x4F7F;&#x7528;&#x5B83;&#x3002;&#x4F46;&#x662F;&#x4F7F;&#x7528; <code>time.Sleep</code> &#x53EA;&#x662F;&#x4E00;&#x4E2A;&#x8BA9;&#x6211;&#x4EEC;&#x83B7;&#x53D6;&#x7406;&#x60F3;&#x7ED3;&#x679C;&#x7684;&#x4E00;&#x4E2A;&#x5C0F;&#x6280;&#x5DE7;&#x3002;&#x5728;&#x5B9E;&#x9645;&#x751F;&#x4EA7;&#x73AF;&#x5883;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x65E0;&#x6CD5;&#x77E5;&#x6653;&#x4E00;&#x4E2A; Go &#x534F;&#x7A0B;&#x5230;&#x5E95;&#x9700;&#x8981;&#x6267;&#x884C;&#x591A;&#x957F;&#x7684;&#x65F6;&#x95F4;&#xFF0C;&#x56E0;&#x800C;&#x5728; main &#x51FD;&#x6570;&#x91CC;&#x9762;&#x6DFB;&#x52A0;&#x4E00;&#x4E2A; <code>time.Sleep</code> &#x5E76;&#x4E0D;&#x662F;&#x4E00;&#x4E2A;&#x89E3;&#x51B3;&#x95EE;&#x9898;&#x7684;&#x65B9;&#x6CD5;&#x3002;&#x6211;&#x4EEC;&#x5E0C;&#x671B; Go &#x534F;&#x7A0B;&#x5728;&#x6267;&#x884C;&#x5B8C;&#x6BD5;&#x540E;&#x544A;&#x77E5;&#x4E3B;&#x534F;&#x7A0B;&#x8FD0;&#x884C;&#x7684;&#x7ED3;&#x679C;&#x3002;&#x5728;&#x76EE;&#x524D;&#x9636;&#x6BB5;&#xFF0C;&#x6211;&#x4EEC;&#x8FD8;&#x4E0D;&#x77E5;&#x9053;&#x5982;&#x4F55;&#x5411;&#x5176;&#x4ED6; Go &#x534F;&#x7A0B;&#x4F20;&#x9012;&#x4EE5;&#x53CA;&#x83B7;&#x53D6;&#x6570;&#x636E;&#xFF0C;&#x7B80;&#x800C;&#x8A00;&#x4E4B;&#xFF0C;&#x5C31;&#x662F;&#x4E0E;&#x5176;&#x4ED6; Go &#x534F;&#x7A0B;&#x8FDB;&#x884C;&#x901A;&#x4FE1;&#x3002;&#x8FD9;&#x5C31;&#x662F; channels &#x5F15;&#x5165;&#x7684;&#x539F;&#x56E0;&#x3002;&#x6211;&#x4EEC;&#x4F1A;&#x5728;&#x4E0B;&#x4E00;&#x6B21;&#x8BFE;&#x4E2D;&#x8BA8;&#x8BBA;&#x8FD9;&#x4E2A;&#x4E1C;&#x897F;&#x3002;</p><h2 id="%E5%8C%BF%E5%90%8D-go-%E5%8D%8F%E7%A8%8B"><strong>&#x533F;&#x540D; Go &#x534F;&#x7A0B;</strong></h2><p>&#x5982;&#x679C;&#x4E00;&#x4E2A;&#x533F;&#x540D;&#x51FD;&#x6570;&#x53EF;&#x4EE5;&#x9000;&#x51FA;&#xFF0C;&#x90A3;&#x4E48;&#x533F;&#x540D; Go &#x534F;&#x7A0B;&#x4E5F;&#x540C;&#x6837;&#x53EF;&#x4EE5;&#x9000;&#x51FA;&#x3002;&#x8BF7;&#x53C2;&#x7167;<strong><code><a href="https://link.zhihu.com/?target=https%3A//medium.com/rungo/the-anatomy-of-functions-in-go-de56c050fe11" rel="nofollow noreferrer">functions</a></code></strong> &#x8BFE;&#x7A0B;&#x4E2D;&#x7684; <code>&#x5373;&#x65F6;&#x8C03;&#x7528;&#x51FD;&#x6570;&#xFF08;Immedietly invoked function&#xFF09;</code> &#x6765;&#x7406;&#x89E3;&#x672C;&#x8282;&#x3002;&#x8BA9;&#x6211;&#x4EEC;&#x4FEE;&#x6539;&#x4E00;&#x4E0B;&#x4E4B;&#x524D; <code>printHello</code> &#x534F;&#x7A0B;&#x7684;&#x4F8B;&#x5B50;&#xFF1A;</p><figure class="kg-card kg-image-card"><img src="https://pic3.zhimg.com/80/v2-c9dfb83fa5304d6dc4e08e05bbd2d3fa_720w.jpg" class="kg-image" alt loading="lazy"></figure><p>&#x7ED3;&#x679C;&#x975E;&#x5E38;&#x660E;&#x663E;&#xFF0C;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;&#x5B9A;&#x4E49;&#x4E86;&#x533F;&#x540D;&#x51FD;&#x6570;&#xFF0C;&#x5E76;&#x5728;&#x540C;&#x4E00;&#x8BED;&#x53E5;&#x4E2D;&#x4F5C;&#x4E3A; Go &#x534F;&#x7A0B;&#x6267;&#x884C;&#x3002;</p><p><em>&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#xFF0C;&#x6240;&#x6709;&#x7684; Go &#x534F;&#x7A0B;&#x90FD;&#x662F;&#x533F;&#x540D;&#x7684;&#xFF0C;&#x56E0;&#x4E3A;&#x6211;&#x4EEC;&#x4ECE;<strong><code><a href="https://link.zhihu.com/?target=https%3A//medium.com/rungo/achieving-concurrency-in-go-3f84cbf870ca" rel="nofollow noreferrer">&#x5E76;&#x53D1;&#xFF08;concurrency</a></code></strong> &#x4E00;&#x8BFE;&#x4E2D;&#x5B66;&#x5230;&#xFF0C;go &#x534F;&#x7A0B;&#x662F;&#x4E0D;&#x5B58;&#x5728;&#x6807;&#x8BC6;&#x7B26;&#x7684;&#xFF0C;&#x5728;&#x8FD9;&#x91CC;&#x6240;&#x8C13;&#x7684;&#x533F;&#x540D; Go &#x534F;&#x7A0B;&#x53EA;&#x662F;&#x901A;&#x8FC7;&#x533F;&#x540D;&#x51FD;&#x6570;&#x6765;&#x521B;&#x5EFA;&#x7684; Go &#x534F;&#x7A0B;&#x7F62;&#x4E86;</em></p>]]></content:encoded></item><item><title><![CDATA[Go 中基于 IP 地址的 HTTP 请求限流]]></title><description><![CDATA[<p>&#x5982;&#x679C;&#x4F60;&#x5728;&#x8FD0;&#x884C; HTTP &#x670D;&#x52A1;&#x5E76;&#x4E14;&#x60F3;&#x5BF9; endpoints &#x8FDB;&#x884C;&#x9650;&#x901F;&#xFF0C;&#x4F60;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x7EF4;&#x62A4;&#x826F;&#x597D;&#x7684;&#x5DE5;&#x5177;&#xFF0C;&#x4F8B;&#x5982; <strong><a href="https://link.zhihu.com/?target=https%3A//github.com/didip/tollbooth" rel="nofollow noreferrer">github.com/didip/tollbooth</a></strong>&#x3002;&#x4F46;&#x662F;&#x5982;&#x679C;&#x4F60;&#x5728;&#x6784;&#x5EFA;&#x4E00;&#x4E9B;&#x975E;</p>]]></description><link>http://www.net-e.cn/go-zhong-ji-yu-ip-di-zhi-de-http-qing-qiu-xian-liu/</link><guid isPermaLink="false">61502870681cac0001a7ef38</guid><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Sun, 26 Sep 2021 08:05:23 GMT</pubDate><content:encoded><![CDATA[<p>&#x5982;&#x679C;&#x4F60;&#x5728;&#x8FD0;&#x884C; HTTP &#x670D;&#x52A1;&#x5E76;&#x4E14;&#x60F3;&#x5BF9; endpoints &#x8FDB;&#x884C;&#x9650;&#x901F;&#xFF0C;&#x4F60;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x7EF4;&#x62A4;&#x826F;&#x597D;&#x7684;&#x5DE5;&#x5177;&#xFF0C;&#x4F8B;&#x5982; <strong><a href="https://link.zhihu.com/?target=https%3A//github.com/didip/tollbooth" rel="nofollow noreferrer">github.com/didip/tollbooth</a></strong>&#x3002;&#x4F46;&#x662F;&#x5982;&#x679C;&#x4F60;&#x5728;&#x6784;&#x5EFA;&#x4E00;&#x4E9B;&#x975E;&#x5E38;&#x7B80;&#x5355;&#x7684;&#x4E1C;&#x897F;&#xFF0C;&#x81EA;&#x5DF1;&#x5B9E;&#x73B0;&#x5E76;&#x4E0D;&#x56F0;&#x96BE;&#x3002;</p><p>&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x5DF2;&#x7ECF;&#x5B58;&#x5728;&#x7684;&#x8BD5;&#x9A8C;&#x6027;&#x7684; Go &#x5305; <code>x/time/rate</code>&#x3002;</p><p>&#x5728;&#x672C;&#x6559;&#x7A0B;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x57FA;&#x4E8E;&#x7528;&#x6237; IP &#x5730;&#x5740;&#x8FDB;&#x884C;&#x901F;&#x7387;&#x9650;&#x5236;&#x7684;&#x7B80;&#x5355;&#x7684;&#x4E2D;&#x95F4;&#x4EF6;&#x3002;</p><h2 id="%E3%80%8C%E5%B9%B2%E5%87%80%E7%9A%84%E3%80%8Dhttp-%E6%9C%8D%E5%8A%A1"><strong>&#x300C;&#x5E72;&#x51C0;&#x7684;&#x300D;HTTP &#x670D;&#x52A1;</strong></h2><p>&#x8BA9;&#x6211;&#x4EEC;&#x4ECE;&#x6784;&#x5EFA;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684; HTTP &#x670D;&#x52A1;&#x5F00;&#x59CB;&#xFF0C;&#x8BE5;&#x670D;&#x52A1;&#x5177;&#x6709;&#x975E;&#x5E38;&#x7B80;&#x5355;&#x7684; endpiont&#x3002;&#x8FD9;&#x53EF;&#x80FD;&#x662F;&#x4E2A;&#x975E;&#x5E38;&#x300C;&#x91CD;&#x300D;&#x7684; endpoint&#xFF0C;&#x56E0;&#x6B64;&#x6211;&#x4EEC;&#x60F3;&#x5728;&#x8FD9;&#x91CC;&#x6DFB;&#x52A0;&#x901F;&#x7387;&#x9650;&#x5236;&#x3002;</p><pre><code class="language-text">package main

import (
    &quot;log&quot;
    &quot;net/http&quot;
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc(&quot;/&quot;, okHandler)

    if err := http.ListenAndServe(&quot;:8888&quot;, mux); err != nil {

    // log.Fatalf(&quot;unable to start server: %s&quot;, err.Error())
    }
}

func okHandler(w http.ResponseWriter, r *http.Request) {
    // Some very expensive database call
    w.Write([]byte(&quot;alles gut&quot;))
}
</code></pre><p>&#x5728; <code>main.go</code> &#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x542F;&#x52A8;&#x670D;&#x52A1;&#xFF0C;&#x8BE5;&#x670D;&#x52A1;&#x76D1;&#x542C; <code>:8888</code> &#x5E76;&#x62E5;&#x6709;&#x4E00;&#x4E2A; endpoint <code>/</code>&#x3002;</p><h3 id="httpgolangorgxtimerate"><a href="https://link.zhihu.com/?target=http%3A//golang.org/x/time/rate" rel="nofollow noreferrer">http://golang.org/x/time/rate</a></h3><p>&#x6211;&#x4EEC;&#x5C06;&#x4F7F;&#x7528; Go &#x4E2D; <code>x/time/rate</code> &#x5305;&#xFF0C;&#x8BE5;&#x5305;&#x63D0;&#x4F9B;&#x4E86;&#x4EE4;&#x724C;&#x6876;&#x9650;&#x901F;&#x7B97;&#x6CD5;&#x3002;<strong><a href="https://link.zhihu.com/?target=https%3A//godoc.org/golang.org/x/time/rate%23Limiter" rel="nofollow noreferrer">rate#Limiter</a></strong> &#x63A7;&#x5236;&#x4E8B;&#x4EF6;&#x53D1;&#x751F;&#x7684;&#x9891;&#x7387;&#x3002;&#x5B83;&#x5B9E;&#x73B0;&#x4E86;&#x4E00;&#x4E2A;&#x5927;&#x5C0F;&#x4E3A; <code>b</code> &#x7684;&#x300C;&#x4EE4;&#x724C;&#x6876;&#x300D;&#xFF0C;&#x521D;&#x59CB;&#x5316;&#x65F6;&#x662F;&#x6EE1;&#x7684;&#xFF0C;&#x5E76;&#x4E14;&#x4EE5;&#x6BCF;&#x79D2; <code>r</code> &#x4E2A;&#x4EE4;&#x724C;&#x7684;&#x901F;&#x7387;&#x91CD;&#x65B0;&#x586B;&#x5145;&#x3002;&#x975E;&#x6B63;&#x5F0F;&#x5730;&#xFF0C;&#x5728;&#x4EFB;&#x610F;&#x8DB3;&#x591F;&#x957F;&#x7684;&#x65F6;&#x95F4;&#x95F4;&#x9694;&#x4E2D;&#xFF0C;&#x9650;&#x901F;&#x5668;&#x5C06;&#x901F;&#x7387;&#x9650;&#x5236;&#x5728;&#x6BCF;&#x79D2; r &#x4E2A;&#x4EE4;&#x724C;&#xFF0C;&#x6700;&#x5927;&#x7A81;&#x53D1;&#x4E8B;&#x4EF6;&#x4E3A; b &#x4E2A;&#x3002;</p><p>&#x65E2;&#x7136;&#x6211;&#x4EEC;&#x60F3;&#x8981;&#x5B9E;&#x73B0;&#x57FA;&#x4E8E; IP &#x5730;&#x5740;&#x7684;&#x9650;&#x901F;&#x5668;&#xFF0C;&#x6211;&#x4EEC;&#x8FD8;&#x9700;&#x8981;&#x7EF4;&#x62A4;&#x4E00;&#x4E2A;&#x9650;&#x901F;&#x5668;&#x7684; map&#x3002;</p><pre><code class="language-text">package main

import (
    &quot;sync&quot;

    &quot;golang.org/x/time/rate&quot;
)

// IPRateLimiter .
type IPRateLimiter struct {
    ips map[string]*rate.Limiter
    mu  *sync.RWMutex
    r   rate.Limit
    b   int
}

// NewIPRateLimiter .
func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter {
    i := &amp;IPRateLimiter{
        ips: make(map[string]*rate.Limiter),
        mu:  &amp;sync.RWMutex{},
        r:   r,
        b:   b,
    }

    return i
}

// AddIP creates a new rate limiter and adds it to the ips map,
// using the IP address as the key
func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
    i.mu.Lock()
    defer i.mu.Unlock()

    limiter := rate.NewLimiter(i.r, i.b)

    i.ips[ip] = limiter

    return limiter
}

// GetLimiter returns the rate limiter for the provided IP address if it exists.
// Otherwise calls AddIP to add IP address to the map
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
    i.mu.Lock()
    limiter, exists := i.ips[ip]

    if !exists {
        i.mu.Unlock()
        return i.AddIP(ip)
    }

    i.mu.Unlock()

    return limiter
}
</code></pre><p><code>NewIPRateLimiter</code> &#x521B;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A; IP &#x9650;&#x901F;&#x5668;&#x7684;&#x5B9E;&#x4F8B;&#xFF0C;HTTP &#x670D;&#x52A1;&#x9700;&#x8981;&#x8C03;&#x7528;&#x8BE5;&#x5B9E;&#x4F8B;&#x7684; <code>GetLimiter</code> &#x65B9;&#x6CD5;&#x53BB;&#x83B7;&#x53D6;&#x7279;&#x5B9A; IP &#x7684;&#x9650;&#x901F;&#x5668;&#xFF08;&#x4ECE; map &#x4E2D;&#x83B7;&#x53D6;&#xFF0C;&#x6216;&#x8005;&#x751F;&#x6210;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#xFF09;&#x3002;</p><h2 id="%E4%B8%AD%E9%97%B4%E4%BB%B6"><strong>&#x4E2D;&#x95F4;&#x4EF6;</strong></h2><p>&#x8BA9;&#x6211;&#x4EEC;&#x5347;&#x7EA7;&#x6211;&#x4EEC;&#x7684; HTTP &#x670D;&#x52A1;&#xFF0C;&#x5C06;&#x4E2D;&#x95F4;&#x4EF6;&#x6DFB;&#x52A0;&#x5230;&#x6240;&#x6709;&#x7684; endpoints &#x4E2D;&#xFF0C;&#x56E0;&#x6B64;&#xFF0C;&#x5982;&#x679C;&#x67D0; IP &#x8FBE;&#x5230;&#x4E86;&#x9650;&#x5236;&#x901F;&#x7387;&#xFF0C;&#x670D;&#x52A1;&#x5C06;&#x4F1A;&#x8FD4;&#x56DE; 429 Too Many Requests&#xFF0C;&#x5426;&#x5219;&#x670D;&#x52A1;&#x5C06;&#x5904;&#x7406;&#x8BE5;&#x8BF7;&#x6C42;&#x3002;</p><p>&#x5728; <code>limitMiddleware</code> &#x51FD;&#x6570;&#x4E2D;&#xFF0C;&#x6BCF;&#x6B21;&#x4E2D;&#x95F4;&#x4EF6;&#x6536;&#x5230; HTTP &#x8BF7;&#x6C42;&#xFF0C;&#x6211;&#x4EEC;&#x90FD;&#x4F1A;&#x8C03;&#x7528;&#x5168;&#x5C40;&#x9650;&#x901F;&#x5668;&#x7684; <code>Allow()</code> &#x65B9;&#x6CD5;&#x3002;&#x5982;&#x679C;&#x4EE4;&#x724C;&#x6876;&#x4E2D;&#x6CA1;&#x6709;&#x5269;&#x4F59;&#x7684;&#x4EE4;&#x724C;&#xFF0C;<code>Allow()</code> &#x5C06;&#x8FD4;&#x56DE; false&#xFF0C;&#x6211;&#x4EEC;&#x8FD4;&#x56DE;&#x7ED9;&#x7528;&#x6237; 429 Too Many Requests &#x54CD;&#x5E94;&#x3002;&#x5426;&#x5219;&#xFF0C;&#x8C03;&#x7528; <code>Allow()</code> &#x5C06;&#x6D88;&#x8017;&#x6876;&#x4E2D;&#x7684;&#x4E00;&#x4E2A;&#x4EE4;&#x724C;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;&#x63A7;&#x5236;&#x6743;&#x4F20;&#x9012;&#x7ED9;&#x8C03;&#x7528;&#x94FE;&#x7684;&#x4E0B;&#x4E00;&#x4E2A;&#x5904;&#x7406;&#x5668;&#x3002;</p><pre><code class="language-text">package main

import (
    &quot;log&quot;
    &quot;net/http&quot;
)

var limiter = NewIPRateLimiter(1, 5)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc(&quot;/&quot;, okHandler)

    if err := http.ListenAndServe(&quot;:8888&quot;, limitMiddleware(mux)); err != nil {
        log.Fatalf(&quot;unable to start server: %s&quot;, err.Error())
    }
}

func limitMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        limiter := limiter.GetLimiter(r.RemoteAddr)
        if !limiter.Allow() {
            http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(w, r)
    })
}

func okHandler(w http.ResponseWriter, r *http.Request) {
    // Some very expensive database call
    w.Write([]byte(&quot;alles gut&quot;))
}
</code></pre><h2 id="%E6%9E%84%E5%BB%BA-%E8%BF%90%E8%A1%8C"><strong>&#x6784;&#x5EFA; &amp; &#x8FD0;&#x884C;</strong></h2><pre><code class="language-text">go get golang.org/x/time/rate
go build -o server .
./server
</code></pre><h2 id="%E6%B5%8B%E8%AF%95"><strong>&#x6D4B;&#x8BD5;</strong></h2><p>&#x6709;&#x4E00;&#x4E2A;&#x975E;&#x5E38;&#x68D2;&#x7684;&#x5DE5;&#x5177;&#x79F0;&#x4F5C; vegeta&#xFF0C;&#x6211;&#x559C;&#x6B22;&#x5728; HTTP &#x8D1F;&#x8F7D;&#x6D4B;&#x8BD5;&#x4E2D;&#x4F7F;&#x7528;&#xFF08;&#x5B83;&#x4E5F;&#x662F;&#x7528; Go &#x7F16;&#x5199;&#x7684;&#xFF09;</p><pre><code class="language-text">brew install vegeta
</code></pre><p>&#x6211;&#x4EEC;&#x9700;&#x8981;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x914D;&#x7F6E;&#x6587;&#x4EF6;&#xFF0C;&#x58F0;&#x660E;&#x6211;&#x4EEC;&#x60F3;&#x8981;&#x53D1;&#x9001;&#x7684;&#x8BF7;&#x6C42;&#x3002;</p><pre><code class="language-text">GET http://localhost:8888/</code></pre><p>&#x7136;&#x540E;&#xFF0C;&#x4EE5;&#x6BCF;&#x4E2A;&#x65F6;&#x95F4;&#x5355;&#x5143; 100 &#x4E2A;&#x8BF7;&#x6C42;&#x7684;&#x901F;&#x7387;&#x653B;&#x51FB; 10 &#x79D2;&#x3002;</p><pre><code class="language-text">vegeta attack -duration=10s -rate=100 -targets=vegeta.conf | vegeta report
</code></pre><p>&#x7ED3;&#x679C;&#xFF0C;&#x4F60;&#x5C06;&#x770B;&#x5230;&#x4E00;&#x4E9B;&#x8BF7;&#x6C42;&#x8FD4;&#x56DE; 200&#xFF0C;&#x4F46;&#x5927;&#x591A;&#x6570;&#x8FD4;&#x56DE; 429&#x3002;</p>]]></content:encoded></item><item><title><![CDATA[深入底层：Go语言从零构建区块链（二）：PoW工作证明机制]]></title><description><![CDATA[<p>Build Blockchain from Scratch with Golang</p><h2 id="directory">Directory</h2><p><a href="http://krad.top/blockchain/goblockchain02.html#dir0">Directory</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir1">&#x524D;&#x8A00;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir2">&#x9879;&#x76EE;&#x91CD;&#x6784;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir3">&#x5171;&#x8BC6;&#x673A;&#x5236;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir4">&#x6DFB;&#x52A0;Nonce</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir5">PoW&#x5B9E;&#x73B0;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir6">&#x8C03;&#x8BD5;&#x5E26;PoW&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir7">&#x603B;&#x7ED3;</a><br></p><h2 id="%E5%89%8D%E8%A8%80">&#x524D;&#x8A00;</h2><p>&#x5728;&#x4E0A;&#x4E00;&#x7AE0;&#x4E2D;&#x6211;&#x4EEC;&#x4E86;&#x89E3;&#x4E86;&#x533A;&#x5757;</p>]]></description><link>http://www.net-e.cn/shen-ru-di-ceng-goyu-yan-cong-ling-gou-jian-qu-kuai-lian-er-powgong-zuo-zheng-ming-ji-zhi/</link><guid isPermaLink="false">61502614681cac0001a7ef30</guid><dc:creator><![CDATA[Liang Wang]]></dc:creator><pubDate>Sun, 26 Sep 2021 07:50:04 GMT</pubDate><content:encoded><![CDATA[<p>Build Blockchain from Scratch with Golang</p><h2 id="directory">Directory</h2><p><a href="http://krad.top/blockchain/goblockchain02.html#dir0">Directory</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir1">&#x524D;&#x8A00;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir2">&#x9879;&#x76EE;&#x91CD;&#x6784;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir3">&#x5171;&#x8BC6;&#x673A;&#x5236;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir4">&#x6DFB;&#x52A0;Nonce</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir5">PoW&#x5B9E;&#x73B0;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir6">&#x8C03;&#x8BD5;&#x5E26;PoW&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;</a><br><a href="http://krad.top/blockchain/goblockchain02.html#dir7">&#x603B;&#x7ED3;</a><br></p><h2 id="%E5%89%8D%E8%A8%80">&#x524D;&#x8A00;</h2><p>&#x5728;&#x4E0A;&#x4E00;&#x7AE0;&#x4E2D;&#x6211;&#x4EEC;&#x4E86;&#x89E3;&#x4E86;&#x533A;&#x5757;&#x662F;&#x4EC0;&#x4E48;&#x4EE5;&#x53CA;&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;&#x4E4B;&#x95F4;&#x7684;&#x5173;&#x7CFB;&#x3002;&#x5728;&#x8FD9;&#x4E00;&#x7AE0;&#x4E2D;&#x6211;&#x4EEC;&#x5C06;&#x62D3;&#x5BBD;&#x533A;&#x5757;&#x7684;&#x5934;&#x90E8;&#x4FE1;&#x606F;&#xFF0C;&#x5E76;&#x8BB2;&#x89E3;&#x533A;&#x5757;&#x5982;&#x4F55;&#x5408;&#x6CD5;&#x7684;&#x88AB;&#x6DFB;&#x52A0;&#x8FDB;&#x533A;&#x5757;&#x94FE;&#x4E2D;&#x3002;</p><h2 id="%E9%A1%B9%E7%9B%AE%E9%87%8D%E6%9E%84">&#x9879;&#x76EE;&#x91CD;&#x6784;</h2><p>&#x5728;&#x4E0A;&#x4E00;&#x7AE0;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x6240;&#x6709;&#x7684;&#x4EE3;&#x7801;&#x90FD;&#x5199;&#x5728;&#x4E86;main.go&#x4E2D;&#xFF0C;&#x8FD9;&#x663E;&#x7136;&#x4E0D;&#x5229;&#x4E8E;&#x6211;&#x4EEC;&#x7EE7;&#x7EED;&#x6784;&#x5EFA;&#x9879;&#x76EE;&#x3002;&#x6211;&#x4EEC;&#x5E0C;&#x671B;main.go&#x53EA;&#x7528;&#x4E8E;&#x6700;&#x540E;&#x542F;&#x52A8;&#x6211;&#x4EEC;&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#xFF0C;&#x4E3A;&#x6B64;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x5C06;&#x8BBE;&#x8BA1;&#x7684;&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;&#x79FB;&#x690D;&#x5176;&#x5B83;&#x6587;&#x4EF6;&#x5939;&#x4E2D;&#xFF0C;&#x8FD9;&#x4E5F;&#x4F1A;&#x5E2E;&#x4F60;go&#x8BED;&#x8A00;&#x7684;&#x4EE3;&#x7801;&#x7BA1;&#x7406;&#x673A;&#x5236;&#x3002;</p><p>&#x9996;&#x5148;&#x6211;&#x4EEC;&#x5728;goblockchain&#x6587;&#x4EF6;&#x5939;&#x4E0B;&#x5EFA;&#x7ACB;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x6587;&#x4EF6;&#x5939;blockchain&#xFF0C;&#x5728;blockchain&#x4E0B;&#x5206;&#x522B;&#x521B;&#x5EFA;block.go,blockchain.go&#xFF0C;&#x4E4B;&#x540E;&#x6211;&#x4EEC;&#x4F1A;&#x5C06;&#x76F8;&#x5173;&#x7ED3;&#x6784;&#x4F53;&#x4E0E;&#x51FD;&#x6570;&#x653E;&#x5165;&#x5176;&#x4E2D;&#x3002;&#x521B;&#x5EFA;utils&#x6587;&#x4EF6;&#x5939;&#xFF0C;&#x5728;&#x5176;&#x4E0B;&#x521B;&#x5EFA;util.go&#x7528;&#x4EE5;&#x5B58;&#x653E;&#x4E00;&#x4E9B;&#x9F99;&#x5957;&#x51FD;&#x6570;&#x3002;&#x521B;&#x5EFA;constcoe&#x6587;&#x4EF6;&#x5939;&#x5728;&#x5176;&#x4E0B;&#x521B;&#x5EFA;constcoe.go&#x7528;&#x4E8E;&#x50A8;&#x5B58;&#x4E00;&#x4E9B;&#x5168;&#x5C40;&#x5E38;&#x91CF;&#x3002;</p><figure class="kg-card kg-image-card"><img src="http://krad.top/img/goblockchain2/pic1.png" class="kg-image" alt="pic1" loading="lazy"></figure><p>&#x6253;&#x5F00;utils.go&#xFF0C;&#x5F15;&#x5165;&#x4EE5;&#x4E0B;&#x5305;&#x3002;</p><pre><code class="language-go">//util.go

package utils

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;log&quot;
)</code></pre><p>&#x7136;&#x540E;&#x6784;&#x5EFA;&#x4E00;&#x4E2A;&#x7B80;&#x5355;&#x7684;&#x9519;&#x8BEF;&#x5904;&#x7406;&#x51FD;&#x6570;&#x3002;</p><pre><code class="language-go">//util.go

func Handle(err error) {
	if err != nil {
		log.Panic(err)
	}
}</code></pre><p>&#x7136;&#x540E;&#x5C06;&#x6211;&#x4EEC;&#x4E4B;&#x524D;&#x5199;&#x7684;int64&#x8F6C;&#x5B57;&#x8282;&#x4E32;&#x51FD;&#x6570;&#x79FB;&#x52A8;&#x8FC7;&#x6765;&#x3002;</p><pre><code class="language-go">//util.go

func ToHexInt(num int64) []byte {
	buff := new(bytes.Buffer)
	err := binary.Write(buff, binary.BigEndian, num)
	Handle(err)
	return buff.Bytes()
}</code></pre><p>&#x7136;&#x540E;&#x6211;&#x4EEC;&#x8F6C;&#x81F3;constcoe.go,&#x8BBE;&#x7F6E;&#x4E00;&#x4E2A;&#x540E;&#x9762;&#x4F1A;&#x7528;&#x5230;&#x7684;&#x5168;&#x5C40;&#x5E38;&#x91CF;&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x5B9E;&#x73B0;PoW&#x65F6;&#x7684;&#x96BE;&#x5EA6;&#xFF08;&#x540E;&#x9762;&#x4F1A;&#x8BE6;&#x7EC6;&#x8BB2;&#xFF09;&#x3002;</p><pre><code class="language-go">//constcoe.go

package constcoe

const (
	Difficulty = 12
)</code></pre><p>&#x6253;&#x5F00;block.go&#xFF0C;&#x5C06;&#x4E4B;&#x524D;&#x5199;&#x7684;&#x7ED3;&#x6784;&#x4F53;&#x4E0E;&#x51FD;&#x6570;&#x653E;&#x5165;&#x3002;</p><pre><code class="language-go">//block.go

package blockchain

import (
	&quot;bytes&quot;
	&quot;crypto/sha256&quot;
	&quot;goblockchain/utils&quot;
	&quot;time&quot;
)

type Block struct {
	Timestamp int64
	Hash      []byte
	PrevHash  []byte
	Data      []byte
}

func (b *Block) SetHash() {
	information := bytes.Join([][]byte{utils.ToHexInt(b.Timestamp), b.PrevHash, b.Data}, []byte{})
	hash := sha256.Sum256(information)
	b.Hash = hash[:]
}

func CreateBlock(prevhash, data []byte) *Block {
	block := Block{time.Now().Unix(), []byte{}, prevhash, data}
	block.SetHash()
	return &amp;block
}

func GenesisBlock() *Block {
	genesisWords := &quot;Hello, blockchain!&quot;
	return CreateBlock([]byte{}, []byte(genesisWords))
}</code></pre><p>&#x6253;&#x5F00;blockchain.go&#xFF0C;&#x5C06;&#x7ED3;&#x6784;&#x4F53;&#x4E0E;&#x51FD;&#x6570;&#x653E;&#x5165;&#x3002;</p><pre><code class="language-go">//blockchain.go

package blockchain

type BlockChain struct {
	Blocks []*Block
}

func (bc *BlockChain) AddBlock(data string) {
	newBlock := CreateBlock(bc.Blocks[len(bc.Blocks)-1].Hash, []byte(data))
	bc.Blocks = append(bc.Blocks, newBlock)
}

func CreateBlockChain() *BlockChain {
	blockchain := BlockChain{}
	blockchain.Blocks = append(blockchain.Blocks, GenesisBlock())
	return &amp;blockchain
}</code></pre><p>&#x56DE;&#x5230;main.go&#xFF0C;&#x53EA;&#x9700;&#x8981;&#x8C03;&#x7528;&#x6211;&#x4EEC;&#x5199;&#x7684;blockchain&#x5305;&#xFF0C;&#x5C31;&#x53EF;&#x4EE5;&#x542F;&#x52A8;&#x4E4B;&#x524D;&#x5199;&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#x4E86;&#x3002;</p><pre><code class="language-go">//main.go

package main

import (
	&quot;fmt&quot;
	&quot;goblockchain/blockchain&quot;
	&quot;time&quot;
)

func main() {
	blockchain := blockchain.CreateBlockChain()
	time.Sleep(time.Second)
	blockchain.AddBlock(&quot;After genesis, I have something to say.&quot;)
	time.Sleep(time.Second)
	blockchain.AddBlock(&quot;Leo Cao is awesome!&quot;)
	time.Sleep(time.Second)
	blockchain.AddBlock(&quot;I can&apos;t wait to follow his github!&quot;)
	time.Sleep(time.Second)

	for _, block := range blockchain.Blocks {
		fmt.Printf(&quot;Timestamp: %d\n&quot;, block.Timestamp)
		fmt.Printf(&quot;hash: %x\n&quot;, block.Hash)
		fmt.Printf(&quot;Previous hash: %x\n&quot;, block.PrevHash)
		fmt.Printf(&quot;data: %s\n&quot;, block.Data)

	}

}</code></pre><p>&#x6CE8;&#x610F;&#x6B64;&#x65F6;&#x8C03;&#x7528;&#x51FD;&#x6570;CreateBlockChain&#x9700;&#x8981;&#x5728;&#x524D;&#x9762;&#x52A0;blockchain&#x7684;&#x524D;&#x7F00;&#x3002;</p><h2 id="%E5%85%B1%E8%AF%86%E6%9C%BA%E5%88%B6">&#x5171;&#x8BC6;&#x673A;&#x5236;</h2><p>&#x6211;&#x4EEC;&#x5E38;&#x8BF4;&#x533A;&#x5757;&#x94FE;&#x662F;&#x4E00;&#x4E2A;&#x5206;&#x5E03;&#x5F0F;&#x7CFB;&#x7EDF;&#xFF0C;&#x7CFB;&#x7EDF;&#x4E2D;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x90FD;&#x6709;&#x673A;&#x4F1A;&#x50A8;&#x5B58;&#x6570;&#x636E;&#x4FE1;&#x606F;&#x6784;&#x9020;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x7136;&#x540E;&#x8FFD;&#x52A0;&#x5230;&#x533A;&#x5757;&#x94FE;&#x5C3E;&#x90E8;&#x3002;&#x8FD9;&#x91CC;&#x5C31;&#x5B58;&#x5728;&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#xFF0C;&#x90A3;&#x5C31;&#x662F;&#x5F53;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#x4E2D;&#x6709;&#x591A;&#x4E2A;&#x8282;&#x70B9;&#x90FD;&#x60F3;&#x5C06;&#x81EA;&#x5DF1;&#x7684;&#x533A;&#x5757;&#x8FFD;&#x52A0;&#x5230;&#x533A;&#x5757;&#x94FE;&#x662F;&#x6211;&#x4EEC;&#x8BE5;&#x600E;&#x4E48;&#x529E;&#xFF1F;&#x6211;&#x4EEC;&#x5C06;&#x8FD9;&#x4E9B;&#x7B49;&#x5F85;&#x6DFB;&#x52A0;&#x7684;&#x533A;&#x5757;&#x7EDF;&#x79F0;&#x4E3A;&#x5019;&#x9009;&#x533A;&#x5757;&#xFF0C;&#x663E;&#x7136;&#x6211;&#x4EEC;&#x4E0D;&#x80FD;&#x5BF9;&#x5019;&#x9009;&#x533A;&#x5757;&#x5168;&#x76D8;&#x7167;&#x6536;&#xFF0C;&#x5426;&#x5219;&#x533A;&#x5757;&#x94FE;&#x5C31;&#x4E0D;&#x518D;&#x662F;&#x4E00;&#x6761;&#x94FE;&#x800C;&#x662F;&#x4E0D;&#x540C;&#x5206;&#x53C9;&#x6210;&#x533A;&#x5757;&#x6811;&#x3002;&#x90A3;&#x4E48;&#x6211;&#x4EEC;&#x5982;&#x4F55;&#x786E;&#x5B9A;&#x4E00;&#x79CD;&#x65B9;&#x6CD5;&#x6765;&#x4ECE;&#x5019;&#x9009;&#x533A;&#x5757;&#x4E2D;&#x9009;&#x62E9;&#x4E00;&#x4E2A;&#x52A0;&#x5165;&#x5230;&#x533A;&#x5757;&#x94FE;&#x4E2D;&#x4E86;&#xFF1F;&#x8FD9;&#x91CC;&#x5C31;&#x9700;&#x8981;&#x7528;&#x5230;&#x533A;&#x5757;&#x94FE;&#x7684;&#x5171;&#x8BC6;&#x673A;&#x5236;&#xFF0C;&#x540E;&#x6587;&#x5C06;&#x4EE5;&#x6BD4;&#x7279;&#x5E01;&#x4F7F;&#x7528;&#x7684;&#x6700;&#x7ECF;&#x5178;PoW&#x5171;&#x8BC6;&#x673A;&#x5236;&#x8FDB;&#x884C;&#x8BB2;&#x89E3;&#x3002;</p><p>&#x5171;&#x8BC6;&#x673A;&#x5236;&#x8BF4;&#x7684;&#x901A;&#x4FD7;&#x660E;&#x767D;&#x4E00;&#x70B9;&#x5C31;&#x662F;&#x8981;&#x5728;&#x76F8;&#x5BF9;&#x516C;&#x5E73;&#x7684;&#x6761;&#x4EF6;&#x4E0B;&#x8BA9;&#x60F3;&#x8981;&#x6DFB;&#x52A0;&#x533A;&#x5757;&#x8FDB;&#x533A;&#x5757;&#x94FE;&#x7684;&#x8282;&#x70B9;&#x5185;&#x5377;&#xFF0C;&#x901A;&#x8FC7;&#x7ADE;&#x4E89;&#x9009;&#x62E9;&#x51FA;&#x4E00;&#x4E2A;&#x5927;&#x5BB6;&#x516C;&#x8BA4;&#x7684;&#x8282;&#x70B9;&#x6DFB;&#x52A0;&#x5B83;&#x7684;&#x533A;&#x5757;&#x8FDB;&#x5165;&#x533A;&#x5757;&#x94FE;&#x3002;&#x6574;&#x4E2A;&#x5171;&#x8BC6;&#x673A;&#x5236;&#x88AB;&#x5206;&#x4E3A;&#x4E24;&#x90E8;&#x5206;&#xFF0C;&#x9996;&#x5148;&#x662F;&#x7ADE;&#x4E89;&#xFF0C;&#x7136;&#x540E;&#x662F;&#x5171;&#x8BC6;&#x3002;&#x4E2D;&#x672C;&#x806A;&#x5728;&#x6BD4;&#x7279;&#x5E01;&#x4E2D;&#x8BBE;&#x8BA1;&#x4E86;&#x5982;&#x4E0B;&#x7684;&#x4E00;&#x4E2A;Game&#x6765;&#x5B9E;&#x73B0;&#x7ADE;&#x4E89;&#xFF1A;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x53BB;&#x5BFB;&#x627E;&#x4E00;&#x4E2A;&#x968F;&#x673A;&#x503C;&#xFF08;&#x4E5F;&#x5C31;&#x662F;nonce&#xFF09;&#xFF0C;&#x5C06;&#x8FD9;&#x4E2A;&#x968F;&#x673A;&#x503C;&#x4F5C;&#x4E3A;&#x5019;&#x9009;&#x533A;&#x5757;&#x7684;&#x5934;&#x90E8;&#x4FE1;&#x606F;&#x5C5E;&#x6027;&#x4E4B;&#x4E00;&#xFF0C;&#x8981;&#x6C42;&#x5019;&#x9009;&#x533A;&#x5757;&#x5BF9;&#x81EA;&#x8EAB;&#x4FE1;&#x606F;&#xFF08;&#x6CE8;&#x610F;&#x8FD9;&#x91CC;&#x662F;&#x5305;&#x542B;&#x4E86;nonce&#x7684;&#xFF09;&#x8FDB;&#x884C;&#x54C8;&#x5E0C;&#x540E;&#x8868;&#x793A;&#x4E3A;&#x6570;&#x503C;&#x8981;&#x5C0F;&#x4E8E;&#x4E00;&#x4E2A;&#x96BE;&#x5EA6;&#x76EE;&#x6807;&#x503C;&#xFF08;&#x4E5F;&#x5C31;&#x662F;Target&#xFF09;&#xFF0C;&#x6700;&#x5148;&#x5BFB;&#x627E;&#x5230;nonce&#x7684;&#x8282;&#x70B9;&#x5373;&#x4E3A;&#x5377;&#x738B;&#xFF0C;&#x53EF;&#x4EE5;&#x5C06;&#x81EA;&#x5DF1;&#x7684;&#x5019;&#x9009;&#x533A;&#x5757;&#x53D1;&#x5E03;&#x5E76;&#x6DFB;&#x52A0;&#x5230;&#x533A;&#x5757;&#x94FE;&#x5C3E;&#x90E8;&#x3002;&#x8FD9;&#x4E2A;Game&#x8BBE;&#x8BA1;&#x7684;&#x975E;&#x5E38;&#x5DE7;&#x5999;&#xFF0C;&#x9996;&#x5148;&#x6BCF;&#x4E2A;&#x8282;&#x70B9;&#x8981;&#x5BFB;&#x627E;&#x5230;&#x7684;nonce&#x53EA;&#x5BF9;&#x81EA;&#x5DF1;&#x5019;&#x9009;&#x533A;&#x5757;&#x6709;&#x6548;&#xFF0C;&#x9632;&#x6B62;&#x4E86;&#x5176;&#x5B83;&#x8282;&#x70B9;&#x540C;&#x5B66;&#x6284;&#x7B54;&#x6848;&#xFF1B;&#x5176;&#x6B21;&#xFF0C;nonce&#x7684;&#x5BFB;&#x627E;&#x662F;&#x5B8C;&#x5168;&#x968F;&#x673A;&#x7684;&#x6CA1;&#x6709;&#x6280;&#x5DE7;&#xFF0C;&#x5BFB;&#x627E;&#x5230;nonce&#x7684;&#x65F6;&#x95F4;&#x4E0E;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#x4E0E;&#x8282;&#x70B9;&#x672C;&#x8EAB;&#x8BA1;&#x7B97;&#x6027;&#x80FD;&#x6709;&#x5173;&#xFF0C;&#x4F46;&#x4E0D;&#x59A8;&#x788D;&#x6027;&#x80FD;&#x8F83;&#x5DEE;&#x7684;&#x8282;&#x70B9;&#x4E5F;&#x6709;&#x673A;&#x4F1A;&#x83B7;&#x80DC;&#xFF1B;&#x6700;&#x540E;&#x5BFB;&#x627E;nonce&#x53EF;&#x80FD;&#x8017;&#x8D39;&#x5927;&#x91CF;&#x65F6;&#x95F4;&#x4E0E;&#x8D44;&#x6E90;&#xFF0C;&#x4F46;&#x662F;&#x9A8C;&#x8BC1;&#x5377;&#x738B;&#x662F;&#x5426;&#x771F;&#x7684;&#x627E;&#x5230;&#x4E86;nonce&#x5374;&#x975E;&#x5E38;&#x5374;&#x80FD;&#x591F;&#x5F88;&#x5FEB;&#x5B8C;&#x6210;&#x5E76;&#x51E0;&#x4E4E;&#x4E0D;&#x9700;&#x8981;&#x8017;&#x8D39;&#x8D44;&#x6E90;&#xFF0C;&#x8FD9;&#x4E2A;&#x5BFB;&#x627E;&#x5230;&#x7684;nonce&#x53EF;&#x4EE5;&#x8BF4;&#x5C31;&#x662F;&#x5377;&#x738B;&#x771F;&#x7684;&#x662F;&#x5377;&#x738B;&#x7684;&#x8BC1;&#x636E;&#x3002;&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x5C31;&#x6765;&#x4E00;&#x6B65;&#x4E00;&#x6B65;&#x5B9E;&#x73B0;&#x8FD9;&#x4E2A;Game&#x3002;</p><h2 id="%E6%B7%BB%E5%8A%A0nonce">&#x6DFB;&#x52A0;Nonce</h2><p>&#x5982;&#x524D;&#x6587;&#x6240;&#x8BF4;&#xFF0C;&#x6211;&#x4EEC;&#x8981;&#x5148;&#x589E;&#x52A0;&#x4E00;&#x4E9B;&#x533A;&#x5757;&#x7684;&#x5934;&#x90E8;&#x4FE1;&#x606F;&#x3002;</p><pre><code class="language-go">//block.go

import (
	&quot;bytes&quot;
	&quot;crypto/sha256&quot;
	&quot;goblockchain/utils&quot;
	&quot;time&quot;
)

type Block struct {
	Timestamp int64
	Hash      []byte
	PrevHash  []byte
	Target    []byte //This line is new
	Nonce     int64  //This line is new
	Data      []byte
}</code></pre><p>Nonce&#x5C31;&#x662F;&#x8282;&#x70B9;&#x5BFB;&#x627E;&#x5230;&#x7684;&#x4F5C;&#x4E3A;&#x5377;&#x738B;&#x7684;&#x8BC1;&#x636E;&#x3002;Target&#x5C31;&#x662F;&#x6211;&#x4EEC;&#x524D;&#x6587;&#x8BF4;&#x5230;&#x7684;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#xFF0C;&#x5C06;&#x5B83;&#x4FDD;&#x5B58;&#x5230;&#x533A;&#x5757;&#x4E2D;&#x4FBF;&#x4E8E;&#x5176;&#x4ED6;&#x8282;&#x70B9;&#x5FEB;&#x901F;&#x9A8C;&#x8BC1;Nonce&#x662F;&#x5426;&#x6B63;&#x786E;&#x3002;</p><p>&#x8FD9;&#x6837;&#x4E00;&#x6765;&#x4E4B;&#x524D;&#x521B;&#x5EFA;&#x7684;&#x51E0;&#x4E2A;&#x51FD;&#x6570;&#x4F1A;&#x62A5;&#x9519;&#xFF0C;&#x6211;&#x4EEC;&#x5148;&#x6682;&#x65F6;&#x4E0D;&#x7406;&#x4F1A;&#x3002;</p><h2 id="pow%E5%AE%9E%E7%8E%B0">PoW&#x5B9E;&#x73B0;</h2><p>&#x5728;blockchain&#x6587;&#x4EF6;&#x5939;&#x4E0B;&#x521B;&#x5EFA;proofofwork.go&#xFF0C;&#x6211;&#x4EEC;&#x6765;&#x5B9E;&#x73B0;&#x4E4B;&#x524D;&#x8BF4;&#x5230;&#x7684;Game&#x3002;&#x9996;&#x5148;&#x5F15;&#x5165;&#x4EE5;&#x4E0B;&#x5305;&#x3002;</p><pre><code class="language-go">//proofofwork.go

package blockchain

import (
	&quot;bytes&quot;
	&quot;crypto/sha256&quot;
	&quot;goblockchain/constcoe&quot;
	&quot;goblockchain/utils&quot;
	&quot;math&quot;
	&quot;math/big&quot;
)</code></pre><p>&#x6211;&#x4EEC;&#x73B0;&#x5728;&#x6765;&#x6784;&#x5EFA;&#x4E00;&#x4E2A;&#x53EF;&#x4EE5;&#x8FD4;&#x56DE;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#x7684;&#x51FD;&#x6570;&#x3002;&#x6211;&#x4EEC;&#x8FD9;&#x91CC;&#x4F7F;&#x7528;&#x7684;&#x4E4B;&#x524D;&#x8BBE;&#x5B9A;&#x7684;&#x4E00;&#x4E2A;&#x5E38;&#x91CF;Difficulty&#x6765;&#x6784;&#x9020;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#xFF0C;&#x4F46;&#x662F;&#x5728;&#x5B9E;&#x9645;&#x7684;&#x533A;&#x5757;&#x94FE;&#x4E2D;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#x4F1A;&#x6839;&#x636E;&#x7F51;&#x7EDC;&#x60C5;&#x51B5;&#x5B9A;&#x65F6;&#x8FDB;&#x884C;&#x8C03;&#x6574;&#xFF0C;&#x4E14;&#x80FD;&#x591F;&#x4FDD;&#x8BC1;&#x5404;&#x8282;&#x70B9;&#x5728;&#x540C;&#x4E00;&#x65F6;&#x95F4;&#x5728;&#x540C;&#x4E00;&#x96BE;&#x5EA6;&#x4E0B;&#x8FDB;&#x884C;&#x7ADE;&#x4E89;&#xFF0C;&#x6545;&#x8FD9;&#x91CC;&#x7684;GetTarget&#x53EF;&#x4EE5;&#x7406;&#x89E3;&#x4E3A;&#x9884;&#x7559;API&#xFF0C;&#x671F;&#x5F85;&#x4E00;&#x4E0B;&#x4E4B;&#x540E;&#x7684;&#x5206;&#x5E03;&#x5F0F;&#x7F51;&#x7EDC;&#x5B9E;&#x73B0;&#x3002;</p><pre><code class="language-go">//proofofwork.go

func (b *Block) GetTarget() []byte {
	target := big.NewInt(1)
	target.Lsh(target, uint(256-constcoe.Difficulty))
	return target.Bytes()
}</code></pre><p>Lsh&#x51FD;&#x6570;&#x5C31;&#x662F;&#x5411;&#x5DE6;&#x79FB;&#x4F4D;&#xFF0C;&#x79FB;&#x7684;&#x8D8A;&#x591A;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#x8D8A;&#x5927;&#xFF0C;&#x54C8;&#x5E0C;&#x53D6;&#x503C;&#x843D;&#x5728;&#x7684;&#x7A7A;&#x95F4;&#x5C31;&#x66F4;&#x591A;&#x5C31;&#x8D8A;&#x5BB9;&#x6613;&#x627E;&#x5230;&#x7B26;&#x5408;&#x6761;&#x4EF6;&#x7684;nonce&#x3002;</p><p>&#x6BCF;&#x6B21;&#x6211;&#x4EEC;&#x8F93;&#x5165;&#x4E00;&#x4E2A;nonce&#x5BF9;&#x5E94;&#x7684;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#x90FD;&#x4F1A;&#x6539;&#x53D8;&#xFF0C;&#x5982;&#x4E0B;&#x3002;</p><pre><code class="language-go">//proofofwork.go

func (b *Block) GetBase4Nonce(nonce int64) []byte {
	data := bytes.Join([][]byte{
		utils.ToHexInt(b.Timestamp),
		b.PrevHash,
		utils.ToHexInt(int64(nonce)),
		b.Target,
		b.Data,
	},
		[]byte{},
	)
	return data
}</code></pre><p>&#x73B0;&#x5728;&#x5BF9;&#x4E8E;&#x4EFB;&#x610F;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#xFF0C;&#x6211;&#x4EEC;&#x90FD;&#x80FD;&#x53BB;&#x5BFB;&#x627E;&#x4E00;&#x4E2A;&#x5408;&#x9002;&#x7684;nonce&#x4E86;&#x3002;</p><pre><code class="language-go">//proofofwork.go

func (b *Block) FindNonce() int64 {
	var intHash big.Int
	var intTarget big.Int
	var hash [32]byte
	var nonce int64
	nonce = 0
	intTarget.SetBytes(b.Target)

	for nonce &lt; math.MaxInt64 {
		data := b.GetBase4Nonce(nonce)
		hash = sha256.Sum256(data)
		intHash.SetBytes(hash[:])
		if intHash.Cmp(&amp;intTarget) == -1 {
			break
		} else {
			nonce++
		}
	}
	return nonce
}</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#xFF0C;&#x795E;&#x79D8;&#x7684;nonce&#x4E0D;&#x8FC7;&#x662F;&#x4ECE;0&#x5F00;&#x59CB;&#x53D6;&#x7684;&#x6574;&#x6570;&#x800C;&#x5DF2;&#xFF0C;&#x968F;&#x7740;&#x4E0D;&#x65AD;&#x5C1D;&#x8BD5;&#xFF0C;&#x6BCF;&#x6B21;&#x5931;&#x8D25;nonce&#x5C31;&#x52A0;1&#x76F4;&#x5230;&#x7531;&#x5F53;&#x524D;nonce&#x5F97;&#x5230;&#x7684;&#x533A;&#x5757;&#x54C8;&#x5E0C;&#x8F6C;&#x5316;&#x4E3A;&#x6570;&#x503C;&#x5C0F;&#x4E8E;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#x4E3A;&#x6B62;&#x3002;</p><p>&#x6211;&#x4EEC;&#x518D;&#x6765;&#x5B9E;&#x73B0;&#x4E00;&#x4E2A;&#x5FEB;&#x901F;&#x9A8C;&#x8BC1;&#x5377;&#x738B;&#x662F;&#x5377;&#x738B;&#x7684;&#x51FD;&#x6570;&#x3002;</p><pre><code class="language-go">//proofofwork.go

func (b *Block) ValidatePoW() bool {
	var intHash big.Int
	var intTarget big.Int
	var hash [32]byte
	intTarget.SetBytes(b.Target)
	data := b.GetBase4Nonce(b.Nonce)
	hash = sha256.Sum256(data)
	intHash.SetBytes(hash[:])
	if intHash.Cmp(&amp;intTarget) == -1 {
		return true
	}
	return false
}</code></pre><p>&#x597D;&#x4E86;&#xFF0C;PoW&#x6211;&#x4EEC;&#x5DF2;&#x7ECF;&#x5B9E;&#x73B0;&#x4E86;&#x3002;&#x56DE;&#x5230;block.go&#xFF0C;&#x8C03;&#x6574;&#x4EE5;&#x4E0B;&#x51FD;&#x6570;&#x3002;</p><pre><code class="language-go">//block.go

func (b *Block) SetHash() {
	information := bytes.Join([][]byte{utils.ToHexInt(b.Timestamp), b.PrevHash, b.Target, utils.ToHexInt(b.Nonce), b.Data}, []byte{})
	hash := sha256.Sum256(information)
	b.Hash = hash[:]
}

func CreateBlock(prevhash, data []byte) *Block {
	block := Block{time.Now().Unix(), []byte{}, prevhash, []byte{}, 0, data}
	block.Target = block.GetTarget()
	block.Nonce = block.FindNonce()
	block.SetHash()
	return &amp;block
}</code></pre><h2 id="%E8%B0%83%E8%AF%95%E5%B8%A6pow%E7%9A%84%E5%8C%BA%E5%9D%97%E9%93%BE%E7%B3%BB%E7%BB%9F">&#x8C03;&#x8BD5;&#x5E26;PoW&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;</h2><p>&#x73B0;&#x5728;&#x6253;&#x5F00;main.go&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x7F16;&#x5199;&#x7A0B;&#x5E8F;&#x542F;&#x52A8;&#x6211;&#x4EEC;&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#x4E86;&#x3002;</p><pre><code class="language-go">//main.go

package main

import (
	&quot;fmt&quot;
	&quot;goblockchain/blockchain&quot;
	&quot;time&quot;
)

func main() {
	chain := blockchain.CreateBlockChain()
	time.Sleep(time.Second)
	chain.AddBlock(&quot;After genesis, I have something to say.&quot;)
	time.Sleep(time.Second)
	chain.AddBlock(&quot;Leo Cao is awesome!&quot;)
	time.Sleep(time.Second)
	chain.AddBlock(&quot;I can&apos;t wait to follow his github!&quot;)
	time.Sleep(time.Second)

	for _, block := range chain.Blocks {
		fmt.Printf(&quot;Timestamp: %d\n&quot;, block.Timestamp)
		fmt.Printf(&quot;hash: %x\n&quot;, block.Hash)
		fmt.Printf(&quot;Previous hash: %x\n&quot;, block.PrevHash)
		fmt.Printf(&quot;nonce: %d\n&quot;, block.Nonce)
		fmt.Printf(&quot;data: %s\n&quot;, block.Data)
		fmt.Println(&quot;Proof of Work validation:&quot;, block.ValidatePoW())
	}
}</code></pre><p>&#x8001;&#x6837;&#x5B50;&#x5728;terminal&#x4E2D;&#x6572;&#x4E0B;go run main.go&#xFF0C;&#x5F97;&#x5230;&#x5982;&#x4E0B;&#x7ED3;&#x679C;&#x3002;</p><pre><code>D:\learngo\goblockchain&gt;go run main.go
Timestamp: 1632558933
hash: 5ee3e13ce051362c7fa4a5c0dcf4883fec97affb66521d02dcd1bfc5ac14c142
Previous hash:
nonce: 1623
data: Hello, blockchain!
Proof of Work validation: true
Timestamp: 1632558934
hash: 611739fb51de47b7bb472444517a4a9c7d590f9f17fc54ef13fe79ddebefa0e2
Previous hash: 5ee3e13ce051362c7fa4a5c0dcf4883fec97affb66521d02dcd1bfc5ac14c142
nonce: 3369
data: After genesis, I have something to say.
Proof of Work validation: true
Timestamp: 1632558935
hash: eca9fe17530d867ee8212084eae6d54581d152fd01f0c0c64f2143adbbf6a9cb
Previous hash: 611739fb51de47b7bb472444517a4a9c7d590f9f17fc54ef13fe79ddebefa0e2
nonce: 4541
data: Leo Cao is awesome!
Proof of Work validation: true
Timestamp: 1632558936
hash: edaff517ca77b1f6705227b1bf40f311aeb0207014581318f2c98a0fe3842723
Previous hash: eca9fe17530d867ee8212084eae6d54581d152fd01f0c0c64f2143adbbf6a9cb
nonce: 1325
data: I can&apos;t wait to follow his github!
Proof of Work validation: true
</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x6211;&#x4EEC;&#x7684;PoW&#x9A8C;&#x8BC1;&#x8FD0;&#x884C;&#x6B63;&#x5E38;&#x3002;&#x4F60;&#x53EF;&#x4EE5;&#x5C1D;&#x8BD5;&#x5C06;&#x5168;&#x5C40;&#x53D8;&#x91CF;Difficulty&#x6539;&#x5927;&#x6765;&#x589E;&#x52A0;&#x96BE;&#x5EA6;&#x503C;&#xFF0C;&#x7136;&#x540E;&#x89C2;&#x5BDF;&#x4E00;&#x4E0B;&#x5404;&#x4E2A;&#x533A;&#x5757;&#x7684;timestamp&#x53D8;&#x5316;&#x3002;</p><h2 id="%E6%80%BB%E7%BB%93">&#x603B;&#x7ED3;</h2><p>&#x672C;&#x7AE0;&#x8BB2;&#x89E3;&#x4E86;PoW&#x5171;&#x8BC6;&#x673A;&#x5236;&#xFF0C;&#x9700;&#x8981;&#x91CD;&#x70B9;&#x7406;&#x89E3;nonce&#x4E0E;&#x76EE;&#x6807;&#x96BE;&#x5EA6;&#x503C;&#xFF0C;&#x4EE5;&#x53CA;&#x5377;&#x738B;&#x3002;&#x5728;&#x4E00;&#x7AE0;&#x4E2D;&#x6211;&#x4EEC;&#x5C06;&#x4F1A;&#x8BB2;&#x89E3;&#x533A;&#x5757;&#x4E2D;&#x7684;&#x6570;&#x636E;&#x4FE1;&#x606F;&#x5B58;&#x50A8;&#x65B9;&#x5F0F;&#xFF0C;&#x6D89;&#x53CA;UTXO&#x6A21;&#x578B;&#x3002;</p>]]></content:encoded></item><item><title><![CDATA[深入底层：Go语言从零构建区块链（一）: Hello, Blockchain]]></title><description><![CDATA[<p>Build Blockchain from Scratch with Golang</p><h2 id="directory">Directory</h2><p><a href="http://krad.top/blockchain/goblockchain01.html#dir0">Directory</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir1">&#x524D;&#x8A00;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir2">&#x521B;&#x5EFA;&#x9879;&#x76EE;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir3">&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir4">&#x54C8;&#x5E0C;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir5">&#x533A;&#x5757;&#x521B;&#x5EFA;&#x4E0E;&#x521B;&#x59CB;&#x533A;&#x5757;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir6">&#x8FD0;&#x884C;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir7">&#x603B;&#x7ED3;</a><br></p><h2 id="%E5%89%8D%E8%A8%80">&#x524D;&#x8A00;</h2><p>&#x6709;&#x65F6;&#x89C9;&#x5F97;&#x524D;&#x8A00;&#x4EC0;&#x4E48;</p>]]></description><link>http://www.net-e.cn/shen-ru-di-ceng-goyu-yan-cong-ling-gou-jian-qu-kuai-lian-yi-hello-blockchain/</link><guid isPermaLink="false">61502593681cac0001a7ef29</guid><dc:creator><![CDATA[Liang Wang]]></dc:creator><pubDate>Sun, 26 Sep 2021 07:49:03 GMT</pubDate><content:encoded><![CDATA[<p>Build Blockchain from Scratch with Golang</p><h2 id="directory">Directory</h2><p><a href="http://krad.top/blockchain/goblockchain01.html#dir0">Directory</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir1">&#x524D;&#x8A00;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir2">&#x521B;&#x5EFA;&#x9879;&#x76EE;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir3">&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir4">&#x54C8;&#x5E0C;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir5">&#x533A;&#x5757;&#x521B;&#x5EFA;&#x4E0E;&#x521B;&#x59CB;&#x533A;&#x5757;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir6">&#x8FD0;&#x884C;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;</a><br><a href="http://krad.top/blockchain/goblockchain01.html#dir7">&#x603B;&#x7ED3;</a><br></p><h2 id="%E5%89%8D%E8%A8%80">&#x524D;&#x8A00;</h2><p>&#x6709;&#x65F6;&#x89C9;&#x5F97;&#x524D;&#x8A00;&#x4EC0;&#x4E48;&#x7684;&#x53EF;&#x4EE5;&#x7701;&#x7565;&#xFF0C;&#x4F46;&#x4F5C;&#x4E3A;&#x4E00;&#x4E2A;&#x6559;&#x7A0B;&#x8FD8;&#x662F;&#x5E94;&#x8BE5;&#x5728;&#x6700;&#x5F00;&#x59CB;&#x7684;&#x65F6;&#x5019;&#x8BF4;&#x4E24;&#x53E5;&#x3002;</p><p>&#x8FD9;&#x4E2A;&#x7CFB;&#x5217;&#x7684;&#x6559;&#x7A0B;&#x76EE;&#x7684;&#x662F;&#x4F7F;&#x7528;Golang&#x7531;&#x6D45;&#x5165;&#x6DF1;&#x5730;&#x8FD8;&#x539F;PoW&#x5171;&#x8BC6;&#x673A;&#x5236;&#x6700;&#x57FA;&#x7840;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#xFF08;&#x53C2;&#x7167;&#x6BD4;&#x7279;&#x5E01;&#xFF09;&#xFF0C;&#x9002;&#x5408;&#x60F3;&#x8981;&#x5FEB;&#x901F;&#x5165;&#x95E8;&#x533A;&#x5757;&#x94FE;&#x6838;&#x5FC3;&#x6280;&#x672F;&#x7684;&#x8BFB;&#x8005;&#xFF0C;&#x5F53;&#x7136;&#x4E5F;&#x9002;&#x5408;&#x521A;&#x5B66;&#x5B8C;Go&#x57FA;&#x7840;&#x8BED;&#x6CD5;&#x5E0C;&#x671B;&#x7EC3;&#x624B;&#x7684;&#x8BFB;&#x8005;&#x3002;&#x76F8;&#x8F83;&#x4E8E;&#x7F51;&#x7EDC;&#x4E0A;&#x5176;&#x5B83;Go&#x8BED;&#x8A00;&#x5B9E;&#x73B0;&#x533A;&#x5757;&#x94FE;&#x7684;&#x6559;&#x7A0B;&#xFF0C;&#x672C;&#x7CFB;&#x5217;&#x6559;&#x7A0B;&#x4EE5;&#x6700;&#x7EC8;&#x5EFA;&#x7ACB;&#x4E00;&#x4E2A;&#x53EF;&#x4EE5;&#x5206;&#x5E03;&#x5F0F;&#x8FD0;&#x884C;&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#x4E3A;&#x76EE;&#x6807;&#xFF0C;&#x4F7F;&#x7528;&#x65B0;&#x7248;&#x672C;&#x7684;Golang&#xFF08;v1.17&#xFF09;&#x53CA;&#x76F8;&#x5173;&#x5305;&#xFF0C;&#x5728;&#x8FD8;&#x539F;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#x4F1A;&#x5C3D;&#x91CF;&#x8BF4;&#x660E;&#x4E00;&#x4E9B;&#x5E38;&#x89C4;&#x6559;&#x7A0B;&#x5FFD;&#x89C6;&#x7684;&#x7EC6;&#x8282;&#xFF0C;&#x7ED9;&#x51FA;&#x6240;&#x6709;&#x7684;&#x4EE3;&#x7801;&#x3002;</p><p>&#x5927;&#x90E8;&#x5206;&#x4EBA;&#x5BF9;&#x4E8E;&#x533A;&#x5757;&#x94FE;&#x6280;&#x672F;&#x7684;&#x5B66;&#x4E60;&#x5E38;&#x5E38;&#x505C;&#x7559;&#x5728;&#x8868;&#x8C61;&#xFF0C;&#x4E86;&#x89E3;&#x4E86;UTXO&#x6A21;&#x578B;&#xFF0C;&#x5171;&#x8BC6;&#x673A;&#x5236;&#xFF0C;P2P&#x7F51;&#x7EDC;&#x540E;&#xFF0C;&#x603B;&#x662F;&#x8FEB;&#x4E0D;&#x53CA;&#x5F85;&#x5730;&#x5C31;&#x60F3;&#x7528;&#x533A;&#x5757;&#x94FE;&#x5F80;&#x6240;&#x6709;&#x6D89;&#x53CA;&#x9690;&#x79C1;&#x4E0E;&#x5B89;&#x5168;&#x7684;&#x95EE;&#x9898;&#x91CC;&#x5957;&#x3002;&#x6211;&#x59CB;&#x7EC8;&#x6301;&#x6709;&#x7684;&#x89C2;&#x70B9;&#x662F;&#xFF0C;&#x53EF;&#x4EE5;&#x5141;&#x8BB8;&#x533A;&#x5757;&#x94FE;&#x5728;&#x5404;&#x79CD;&#x5E94;&#x7528;&#x573A;&#x666F;&#x4E2D;&#x8BD5;&#x9519;&#xFF0C;&#x4F46;&#x4E0D;&#x5E94;&#x8BE5;&#x8FC7;&#x4E8E;&#x63A8;&#x5D07;&#x533A;&#x5757;&#x94FE;&#xFF0C;&#x5B83;&#x4E0D;&#x662F;&#x4E07;&#x80FD;&#x7684;&#xFF0C;&#x8981;&#x5B66;&#x4E60;&#x533A;&#x5757;&#x94FE;&#x5C31;&#x5E94;&#x8BE5;&#x4E86;&#x89E3;&#x5176;&#x672C;&#x8D28;&#xFF0C;&#x4ECE;&#x4E8B;&#x7269;&#x7684;&#x4E24;&#x9762;&#x6027;&#x53BB;&#x7814;&#x7A76;&#x5B83;&#x3002;&#x4E3E;&#x4E2A;&#x4F8B;&#x5B50;&#xFF0C;&#x5982;&#x679C;&#x6211;&#x4EEC;&#x628A;&#x533A;&#x5757;&#x94FE;&#x5F53;&#x4F5C;&#x4E00;&#x4E2A;&#x5206;&#x5E03;&#x5F0F;&#x7684;&#x6570;&#x636E;&#x5E93;&#x770B;&#x5F85;&#xFF0C;&#x90A3;&#x4E48;&#x5B83;&#x7684;&#x6027;&#x80FD;&#x65E0;&#x7591;&#x662F;&#x62C9;&#x8DE8;&#x7684;&#xFF0C;&#x4F46;&#x662F;&#x5982;&#x679C;&#x5145;&#x5206;&#x7406;&#x89E3;&#x533A;&#x5757;&#x94FE;&#x7684;&#x672C;&#x8D28;&#xFF0C;&#x5C31;&#x80FD;&#x591F;&#x660E;&#x767D;&#x6BD4;&#x7279;&#x5E01;&#x4E3A;&#x4EC0;&#x4E48;&#x4EC5;&#x4EC5;&#x7528;&#x4E00;&#x6BB5;&#x4EE3;&#x7801;&#x5C31;&#x80FD;&#x591F;&#x5728;&#x5168;&#x7403;&#x6CA1;&#x6709;&#x7B2C;&#x4E09;&#x65B9;&#x673A;&#x6784;&#x7684;&#x53C2;&#x4E0E;&#x4E0B;&#x5B9E;&#x73B0;&#x8D44;&#x4EA7;&#x4FE1;&#x606F;&#x7684;&#x957F;&#x4E45;&#x4FDD;&#x5B58;&#xFF0C;&#x7A33;&#x5B9A;&#x8FD0;&#x884C;&#x8D85;&#x8FC7;&#x4E94;&#x5E74;&#xFF0C;&#x611F;&#x53F9;&#x5176;&#x7CBE;&#x5999;&#x4E4B;&#x5904;&#x3002;</p><p>&#x5982;&#x679C;&#x60F3;&#x8981;&#x4E86;&#x89E3;&#x533A;&#x5757;&#x94FE;&#x6280;&#x672F;&#x7684;&#x672C;&#x8D28;&#xFF0C;&#x4E86;&#x89E3;&#x533A;&#x5757;&#x94FE;&#x6280;&#x672F;&#x7684;&#x4F18;&#x7F3A;&#x70B9;&#x4EE5;&#x53CA;&#x53EF;&#x80FD;&#x7684;&#x7814;&#x7A76;&#x65B9;&#x5411;&#xFF0C;&#x6700;&#x76F4;&#x63A5;&#x7684;&#x529E;&#x6CD5;&#x65E0;&#x7591;&#x662F;&#x9605;&#x8BFB;&#x6BD4;&#x7279;&#x5E01;&#x6E90;&#x7801;&#x3002;&#x4F46;&#x662F;&#x6BD4;&#x7279;&#x5E01;&#x6E90;&#x7801;&#x4F7F;&#x7528;C&#x8FDB;&#x884C;&#x7F16;&#x5199;&#xFF0C;&#x4EBA;&#x4EEC;&#x5E38;&#x5E38;&#x4E0D;&#x77E5;&#x9053;&#x4ECE;&#x54EA;&#x91CC;&#x5F00;&#x59CB;&#x8FDB;&#x884C;&#x5B66;&#x4E60;&#x7406;&#x89E3;&#xFF0C;&#x5728;&#x8017;&#x8D39;&#x5927;&#x91CF;&#x65F6;&#x95F4;&#x4E0E;&#x7CBE;&#x529B;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#xFF0C;&#x6E10;&#x6E10;&#x6D88;&#x78E8;&#x5B66;&#x4E60;&#x8005;&#x5BF9;&#x533A;&#x5757;&#x94FE;&#x7684;&#x5174;&#x8DA3;&#x3002;&#x672C;&#x4EBA;&#x5728;&#x5B66;&#x4E60;&#x533A;&#x5757;&#x94FE;&#x7684;&#x8FC7;&#x7A0B;&#x4E2D;&#x53D1;&#x73B0;&#xFF0C;&#x901A;&#x8FC7;&#x7406;&#x89E3;&#x533A;&#x5757;&#x94FE;&#x539F;&#x7406;&#x4E00;&#x6B65;&#x4E00;&#x6B65;&#x6784;&#x5EFA;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#x6BD4;&#x76F4;&#x63A5;&#x9605;&#x8BFB;&#x6BD4;&#x7279;&#x5E01;&#x6E90;&#x7801;&#x8981;&#x6709;&#x4E50;&#x8DA3;&#x7684;&#x591A;&#xFF0C;&#x5B66;&#x4E60;&#x901F;&#x5EA6;&#x4E5F;&#x66F4;&#x5FEB;&#xFF0C;&#x800C;&#x4E14;&#x6700;&#x7EC8;&#x90FD;&#x80FD;&#x8FBE;&#x5230;&#x540C;&#x6837;&#x7684;&#x76EE;&#x7684;&#xFF0C;&#x5C31;&#x50CF;B&#x6811;&#x7684;&#x5EFA;&#x7ACB;&#x5F80;&#x5F80;&#x6BD4;B&#x6811;&#x7684;&#x67E5;&#x627E;&#x5BB9;&#x6613;&#x5B66;&#x4E60;&#x7406;&#x89E3;&#x4E00;&#x6837;&#x3002;</p><p>&#x4E3A;&#x4E86;&#x8FBE;&#x5230;&#x4F7F;&#x8BFB;&#x8005;&#x5FEB;&#x901F;&#x5165;&#x95E8;&#x5E76;&#x7406;&#x89E3;&#x533A;&#x5757;&#x94FE;&#x6838;&#x5FC3;&#x6280;&#x672F;&#x7684;&#x76EE;&#x7684;&#xFF0C;&#x672C;&#x6559;&#x7A0B;&#x4E0D;&#x592A;&#x6CE8;&#x91CD;&#x5BF9;Go&#x8BED;&#x8A00;&#x76F8;&#x5173;&#x95EE;&#x9898;&#x7684;&#x8BB2;&#x89E3;&#xFF0C;&#x5173;&#x6CE8;&#x7684;&#x662F;&#x4EE3;&#x7801;&#x80CC;&#x540E;&#x7684;&#x533A;&#x5757;&#x94FE;&#x539F;&#x7406;&#x4E0E;&#x5B9E;&#x73B0;&#x7EC6;&#x8282;&#x3002;&#x8BFB;&#x8005;&#x9700;&#x8981;&#x505A;&#x7684;&#x53EA;&#x662F;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x7A7A;&#x9879;&#x76EE;&#xFF0C;&#x4ECE;&#x96F6;&#x5F00;&#x59CB;&#x8DDF;&#x968F;&#x672C;&#x6559;&#x7A0B;&#x6572;&#x4E0B;&#x4E00;&#x884C;&#x53C8;&#x4E00;&#x884C;&#x7684;&#x4EE3;&#x7801;&#x3002;&#x5BF9;&#x8BFB;&#x8005;&#x6765;&#x8BF4;&#xFF0C;&#x91CD;&#x8981;&#x7684;&#x4E0D;&#x662F;&#x5BF9;&#x6211;&#x6240;&#x5199;&#x7684;&#x4EE3;&#x7801;&#x8FDB;&#x884C;&#x6539;&#x52A8;&#xFF0C;&#x800C;&#x662F;&#x7406;&#x89E3;&#x6BCF;&#x4E00;&#x884C;&#x4EE3;&#x7801;&#x7684;&#x610F;&#x4E49;&#x3002;</p><p><em>&#x7531;&#x4E8E;&#x672C;&#x4EBA;Go&#x8BED;&#x8A00;&#x4E5F;&#x8FD8;&#x5904;&#x4E8E;&#x5B66;&#x4E60;&#x9636;&#x6BB5;&#xFF0C;&#x6545;&#x4E00;&#x4E9B;&#x90E8;&#x5206;&#x4EE3;&#x7801;&#x53EF;&#x80FD;&#x8F83;&#x4E3A;&#x5197;&#x4F59;&#x3002;&#x533A;&#x5757;&#x94FE;&#x5B9E;&#x73B0;&#x7EC6;&#x8282;&#x6709;&#x8BEF;&#x7684;&#x5730;&#x65B9;&#x4E5F;&#x968F;&#x65F6;&#x6B22;&#x8FCE;&#x8BA8;&#x8BBA;&#x6307;&#x6B63;&#x3002;</em></p><p><strong>&#x5B8C;&#x6574;&#x7684;&#x9879;&#x76EE;&#x5730;&#x5740;&#xFF1A;<a href="https://github.com/leo201313/Blockchain_with_Go">https://github.com/leo201313/Blockchain_with_Go</a></strong></p><h2 id="%E5%88%9B%E5%BB%BA%E9%A1%B9%E7%9B%AE">&#x521B;&#x5EFA;&#x9879;&#x76EE;</h2><p>&#x9996;&#x5148;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x9879;&#x76EE;&#x3002;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;&#x5939;&#x547D;&#x540D;&#x4E3A;goblockchain&#xFF08;&#x5F53;&#x7136;&#x4F60;&#x4E5F;&#x53EF;&#x4EE5;&#x53D6;&#x4E00;&#x4E2A;&#x9738;&#x6C14;&#x7684;&#x540D;&#x5B57;&#xFF0C;&#x6BD4;&#x5982;lighteningchain,goXchain&#x7B49;&#x7B49;&#xFF09;&#xFF0C;&#x7136;&#x540E;&#x4F7F;&#x7528;VS&#xFF08;Visual Studio Code&#xFF0C;&#x63A8;&#x8350;&#x4F7F;&#x7528;VS&#x4F5C;&#x4E3A;IDE&#xFF09;&#x6253;&#x5F00;&#x6587;&#x4EF6;&#x5939;&#xFF0C;&#x5982;&#x4E0B;&#x56FE;</p><figure class="kg-card kg-image-card"><img src="http://krad.top/img/goblockchain1/pic1.png" class="kg-image" alt="pic1" loading="lazy"></figure><p>&#x6B64;&#x65F6;&#x6587;&#x4EF6;&#x4E2D;&#x4EC0;&#x4E48;&#x90FD;&#x6CA1;&#x6709;&#xFF0C;&#x6211;&#x4EEC;&#x4F7F;&#x7528;go mod&#x6765;&#x521D;&#x59CB;&#x5316;&#x9879;&#x76EE;&#xFF0C;&#x70B9;&#x51FB;VS&#x5DE6;&#x4E0B;&#x65B9;&#x7684;&#x5C0F;&#x4E09;&#x89D2;&#xFF0C;&#x5728;terminal&#x4E2D;&#x8F93;&#x5165;go mod init goblockchain.</p><figure class="kg-card kg-image-card"><img src="http://krad.top/img/goblockchain1/pic2.jpg" class="kg-image" alt="pic1" loading="lazy"></figure><p>&#x6B64;&#x65F6;&#x6587;&#x4EF6;&#x5939;&#x4E2D;&#x5C06;&#x4F1A;&#x591A;&#x51FA;&#x4E00;&#x4E2A;go.mod&#x6587;&#x4EF6;&#xFF0C;&#x8BC1;&#x660E;&#x9879;&#x76EE;&#x5DF2;&#x7ECF;&#x521D;&#x59CB;&#x5316;&#x6210;&#x529F;&#x3002;&#x5728;goblockchain&#x6587;&#x4EF6;&#x5939;&#x4E0B;&#x521B;&#x5EFA;main.go&#x6587;&#x4EF6;&#x3002;</p><figure class="kg-card kg-image-card"><img src="http://krad.top/img/goblockchain1/pic3.png" class="kg-image" alt="pic1" loading="lazy"></figure><h2 id="%E5%8C%BA%E5%9D%97%E4%B8%8E%E5%8C%BA%E5%9D%97%E9%93%BE">&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;</h2><p>&#x533A;&#x5757;&#x94FE;&#x4EE5;&#x533A;&#x5757;&#xFF08;block&#xFF09;&#x7684;&#x5F62;&#x5F0F;&#x50A8;&#x5B58;&#x6570;&#x636E;&#x4FE1;&#x606F;&#xFF0C;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x8BB0;&#x5F55;&#x4E86;&#x4E00;&#x6BB5;&#x65F6;&#x95F4;&#x5185;&#x7CFB;&#x7EDF;&#x6216;&#x7F51;&#x7EDC;&#x4E2D;&#x4EA7;&#x751F;&#x7684;&#x91CD;&#x8981;&#x6570;&#x636E;&#x4FE1;&#x606F;&#xFF0C;&#x533A;&#x5757;&#x901A;&#x8FC7;&#x5F15;&#x7528;&#x4E0A;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x7684;hash&#x503C;&#x6765;&#x8FDE;&#x63A5;&#x4E0A;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x8FD9;&#x6837;&#x533A;&#x5757;&#x5C31;&#x6309;&#x65F6;&#x95F4;&#x987A;&#x5E8F;&#x6392;&#x5217;&#x5F62;&#x6210;&#x4E86;&#x4E00;&#x6761;&#x94FE;&#x3002;&#x6BCF;&#x4E2A;&#x533A;&#x5757;&#x5E94;&#x8BE5;&#x5305;&#x542B;&#x5934;&#x90E8;&#xFF08;head&#xFF09;&#x4FE1;&#x606F;&#x7528;&#x4E8E;&#x603B;&#x7ED3;&#x6027;&#x7684;&#x63CF;&#x8FF0;&#x8FD9;&#x4E2A;&#x533A;&#x5757;&#xFF0C;&#x7136;&#x540E;&#x5728;&#x533A;&#x5757;&#x7684;&#x6570;&#x636E;&#x5B58;&#x653E;&#x533A;&#xFF08;body&#xFF09;&#x4E2D;&#x5B58;&#x653E;&#x8981;&#x4FDD;&#x5B58;&#x7684;&#x91CD;&#x8981;&#x6570;&#x636E;&#x3002;&#x9996;&#x5148;&#x6211;&#x4EEC;&#x9700;&#x8981;&#x521D;&#x59CB;&#x5316;main.go&#xFF0C;&#x5E76;&#x5BFC;&#x5165;&#x4E00;&#x4E9B;&#x57FA;&#x672C;&#x7684;&#x5305;&#x3002;</p><pre><code class="language-go">//main.go

package main

import (
	&quot;bytes&quot;
	&quot;crypto/sha256&quot;
	&quot;encoding/binary&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;time&quot;
)

func main {
	
}</code></pre><p>&#x7136;&#x540E;&#x5B9A;&#x4E49;&#x533A;&#x5757;&#x7684;&#x7ED3;&#x6784;&#x4F53;&#x3002;</p><pre><code class="language-go">//main.go

type Block struct{
	Timestamp int64
	Hash []byte
	PrevHash []byte
	Data []byte
}</code></pre><p>&#x6211;&#x4EEC;&#x5B9A;&#x4E49;&#x7684;&#x533A;&#x5757;&#x4E2D;&#x6709;&#x65F6;&#x95F4;&#x6233;&#xFF0C;&#x672C;&#x8EAB;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#xFF0C;&#x6307;&#x5411;&#x4E0A;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x8FD9;&#x4E09;&#x4E2A;&#x5C5E;&#x6027;&#x6784;&#x6210;&#x5934;&#x90E8;&#x4FE1;&#x606F;&#xFF0C;&#x800C;&#x533A;&#x5757;&#x4E2D;&#x7684;&#x6570;&#x636E;&#x4EE5;Data&#x5C5E;&#x6027;&#x8868;&#x793A;&#x3002;&#x5728;&#x83B7;&#x5F97;&#x4E86;&#x533A;&#x5757;&#x540E;&#xFF0C;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x5B9A;&#x4E49;&#x533A;&#x5757;&#x94FE;&#x3002;</p><pre><code class="language-go">//main.go

type BlockChain struct{
	Blocks []*Block
}</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x6211;&#x4EEC;&#x8FD9;&#x91CC;&#x7684;&#x533A;&#x5757;&#x94FE;&#x5C31;&#x662F;&#x533A;&#x5757;&#x7684;&#x4E00;&#x4E2A;&#x96C6;&#x5408;&#x3002;&#x597D;&#x4E86;&#xFF0C;&#x73B0;&#x5728;&#x4F60;&#x5DF2;&#x7ECF;&#x638C;&#x63E1;&#x4E86;&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;&#x4E86;&#xFF0C;&#x73B0;&#x5728;&#x5C31;&#x53EF;&#x4EE5;&#x53BB;&#x642D;&#x5EFA;&#x81EA;&#x5DF1;&#x7684;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;&#x4E86;&#x3002;</p><h2 id="%E5%93%88%E5%B8%8C">&#x54C8;&#x5E0C;</h2><p>QVQ&#xFF0C;&#x597D;&#x5427;&#xFF0C;&#x6211;&#x4EEC;&#x73B0;&#x5728;&#x6765;&#x7ED9;&#x6211;&#x4EEC;&#x7684;&#x533A;&#x5757;&#x589E;&#x52A0;&#x70B9;&#x7EC6;&#x8282;&#xFF0C;&#x6765;&#x770B;&#x770B;&#x5B83;&#x4EEC;&#x662F;&#x600E;&#x4E48;&#x8FDE;&#x63A5;&#x8D77;&#x6765;&#x7684;&#x3002;&#x5BF9;&#x4E8E;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x800C;&#x8A00;&#xFF0C;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;&#x54C8;&#x5E0C;&#x7B97;&#x6CD5;&#x6982;&#x62EC;&#x5176;&#x6240;&#x5305;&#x542B;&#x7684;&#x6240;&#x6709;&#x4FE1;&#x606F;&#xFF0C;&#x54C8;&#x5E0C;&#x503C;&#x5C31;&#x76F8;&#x5F53;&#x4E8E;&#x533A;&#x5757;&#x7684;ID&#x503C;&#xFF0C;&#x540C;&#x65F6;&#x4E5F;&#x53EF;&#x4EE5;&#x7528;&#x6765;&#x68C0;&#x67E5;&#x533A;&#x5757;&#x6240;&#x5305;&#x542B;&#x4FE1;&#x606F;&#x7684;&#x5B8C;&#x6574;&#x6027;&#x3002;&#x54C8;&#x5E0C;&#x51FD;&#x6570;&#x6784;&#x9020;&#x5982;&#x4E0B;&#x3002;</p><pre><code class="language-go">//main.go

func (b *Block) SetHash() {
	information := bytes.Join([][]bytes{ToHexInt(b.Timestamp),b.PrevHash,b.Data},[]byte{})
	hash := sha256.Sum256(information)
	b.Hash = hash[:]
}

func ToHexInt(num int64) []byte {
	buff := new(bytes.Buffer)
	err := binary.Write(buff, binary.BigEndian, num)
	if err != nil {
		log.Panic(err)
	}
	return buff.Bytes()
}</code></pre><p>information&#x53D8;&#x91CF;&#x662F;&#x5C06;&#x533A;&#x5757;&#x7684;&#x5404;&#x9879;&#x5C5E;&#x6027;&#x4E32;&#x8054;&#x4E4B;&#x540E;&#x7684;&#x5B57;&#x8282;&#x4E32;&#x3002;&#x8FD9;&#x91CC;&#x63D0;&#x9192;&#x4E00;&#x4E0B;bytes.Join&#x53EF;&#x4EE5;&#x5C06;&#x591A;&#x4E2A;&#x5B57;&#x8282;&#x4E32;&#x8FDE;&#x63A5;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x53C2;&#x6570;&#x662F;&#x5C06;&#x5B57;&#x8282;&#x4E32;&#x8FDE;&#x63A5;&#x65F6;&#x7684;&#x5206;&#x9694;&#x7B26;&#xFF0C;&#x8FD9;&#x91CC;&#x8BBE;&#x7F6E;&#x4E3A;[]byte{}&#x5373;&#x4E3A;&#x7A7A;&#xFF0C;ToHexInt&#x5C06;int64&#x8F6C;&#x6362;&#x4E3A;&#x5B57;&#x8282;&#x4E32;&#x7C7B;&#x578B;&#x3002;&#x7136;&#x540E;&#x6211;&#x4EEC;&#x5BF9;information&#x505A;&#x54C8;&#x5E0C;&#x5C31;&#x53EF;&#x4EE5;&#x5F97;&#x5230;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#x4E86;&#x3002;</p><h2 id="%E5%8C%BA%E5%9D%97%E5%88%9B%E5%BB%BA%E4%B8%8E%E5%88%9B%E5%A7%8B%E5%8C%BA%E5%9D%97">&#x533A;&#x5757;&#x521B;&#x5EFA;&#x4E0E;&#x521B;&#x59CB;&#x533A;&#x5757;</h2><p>&#x65E2;&#x7136;&#x6211;&#x4EEC;&#x53EF;&#x4EE5;&#x83B7;&#x5F97;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#x4E86;&#xFF0C;&#x6211;&#x4EEC;&#x5C31;&#x80FD;&#x591F;&#x521B;&#x5EFA;&#x533A;&#x5757;&#x4E86;&#x3002;</p><pre><code class="language-go">//main.go

func CreateBlock(prevhash, data []byte) *Block {
	block := Block{time.Now().Unix(), []byte{}, prevhash, data}
	block.SetHash()
	return &amp;block
}</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x5728;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x65F6;&#x4E00;&#x5B9A;&#x8981;&#x5F15;&#x7528;&#x524D;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#xFF0C;&#x8FD9;&#x91CC;&#x4F1A;&#x6709;&#x4E00;&#x4E2A;&#x95EE;&#x9898;&#xFF0C;&#x90A3;&#x5C31;&#x662F;&#x533A;&#x5757;&#x94FE;&#x4E2D;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x600E;&#x4E48;&#x521B;&#x5EFA;&#xFF1F;&#x5176;&#x5B9E;&#xFF0C;&#x5728;&#x533A;&#x5757;&#x94FE;&#x4E2D;&#x6709;&#x4E00;&#x4E2A;&#x521B;&#x4E16;&#x533A;&#x5757;&#xFF0C;&#x968F;&#x7740;&#x533A;&#x5757;&#x94FE;&#x7684;&#x521B;&#x5EFA;&#x800C;&#x6DFB;&#x52A0;&#xFF0C;&#x5B83;&#x6307;&#x5411;&#x7684;&#x4E0A;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#x4E3A;&#x7A7A;&#x3002;</p><pre><code class="language-go">//main.go

func GenesisBlock() *Block {
	genesisWords := &quot;Hello, blockchain!&quot;
	return CreateBlock([]byte{}, []byte(genesisWords))
}</code></pre><p>&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x6211;&#x4EEC;&#x5728;&#x521B;&#x59CB;&#x533A;&#x5757;&#x4E2D;&#x5B58;&#x653E;&#x4E86; <em>Hello, blockchain!</em> &#x8FD9;&#x6BB5;&#x4FE1;&#x606F;&#x3002;&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x6765;&#x6784;&#x5EFA;&#x51FD;&#x6570;&#xFF0C;&#x4F7F;&#x5F97;&#x533A;&#x5757;&#x94FE;&#x53EF;&#x4EE5;&#x6839;&#x636E;&#x5176;&#x5B83;&#x4FE1;&#x606F;&#x521B;&#x5EFA;&#x533A;&#x5757;&#x8FDB;&#x884C;&#x50A8;&#x5B58;&#x3002;</p><pre><code class="language-go"> //main.go

func (bc *BlockChain) AddBlock(data string) {
	newBlock := CreateBlock(bc.Blocks[len(bc.Blocks)-1].Hash, []byte(data))
	bc.Blocks = append(bc.Blocks, newBlock)
}</code></pre><p>&#x6700;&#x540E;&#x6211;&#x4EEC;&#x6784;&#x5EFA;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x94FE;&#x521D;&#x59CB;&#x5316;&#x51FD;&#x6570;&#xFF0C;&#x4F7F;&#x5176;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;&#x5305;&#x542B;&#x521B;&#x59CB;&#x533A;&#x5757;&#x7684;&#x533A;&#x5757;&#x94FE;&#x3002;</p><pre><code class="language-go">//main.go

func CreateBlockChain() *BlockChain {
	blockchain := BlockChain{}
	blockchain.Blocks = append(blockchain.Blocks, GenesisBlock())
	return &amp;blockchain
}</code></pre><h2 id="%E8%BF%90%E8%A1%8C%E5%8C%BA%E5%9D%97%E9%93%BE%E7%B3%BB%E7%BB%9F">&#x8FD0;&#x884C;&#x533A;&#x5757;&#x94FE;&#x7CFB;&#x7EDF;</h2><p>&#x73B0;&#x5728;&#x6211;&#x4EEC;&#x5DF2;&#x7ECF;&#x62E5;&#x6709;&#x4E86;&#x6240;&#x6709;&#x521B;&#x5EFA;&#x533A;&#x5757;&#x94FE;&#x9700;&#x8981;&#x7684;&#x51FD;&#x6570;&#x4E86;&#xFF0C;&#x6765;&#x770B;&#x770B;&#x6211;&#x4EEC;&#x7684;&#x533A;&#x5757;&#x94FE;&#x662F;&#x600E;&#x4E48;&#x8FD0;&#x4F5C;&#x7684;&#x3002;</p><pre><code class="language-go">//main.go

func main() {
	blockchain := CreateBlockChain()
	time.Sleep(time.Second)
	blockchain.AddBlock(&quot;After genesis, I have something to say.&quot;)
	time.Sleep(time.Second)
	blockchain.AddBlock(&quot;Leo Cao is awesome!&quot;)
	time.Sleep(time.Second)
	blockchain.AddBlock(&quot;I can&apos;t wait to follow his github!&quot;)
	time.Sleep(time.Second)

	for _, block := range blockchain.Blocks {
		fmt.Printf(&quot;Timestamp: %d\n&quot;, block.Timestamp)
		fmt.Printf(&quot;hash: %x\n&quot;, block.Hash)
		fmt.Printf(&quot;Previous hash: %x\n&quot;, block.PrevHash)
		fmt.Printf(&quot;data: %s\n&quot;, block.Data)

	}

}</code></pre><p>&#x5728;terminal&#x4E2D;&#x8F93;&#x5165;go run main.go&#xFF0C;&#x8F93;&#x51FA;&#x5982;&#x4E0B;&#x3002;</p><pre><code>D:\learngo\goblockchain&gt;go run main.go
Timestamp: 1632471455
hash: 289c596026a32c6ac5702fd2d3c96104d6b7178de49beb70a71c100ee839ac26
Previous hash:
data: Hello, blockchain!
Timestamp: 1632471456
hash: a29d04ef59529bb50b1526393203ebf7cc60d8f0ddfbb09900475c9dcf180d3b
Previous hash: 289c596026a32c6ac5702fd2d3c96104d6b7178de49beb70a71c100ee839ac26
data: After genesis, I have something to say.
Timestamp: 1632471457
hash: 69eb263ab680cc0d45530c5ba0db1514255c891e084c3f04bfb416f0f1b06a59
Previous hash: a29d04ef59529bb50b1526393203ebf7cc60d8f0ddfbb09900475c9dcf180d3b
data: Leo Cao is awesome!
Timestamp: 1632471458
hash: 453ff251f95183c92ace277dec4181d5c71582129dc31cce3ceb37c7b1377efc
Previous hash: 69eb263ab680cc0d45530c5ba0db1514255c891e084c3f04bfb416f0f1b06a59
data: I can&apos;t wait to follow his github!
</code></pre><p>&#x4F60;&#x9700;&#x8981;&#x6CE8;&#x610F;&#x7684;&#x662F;&#x521B;&#x59CB;&#x533A;&#x5757;&#x6CA1;&#x6709;Previous Hash&#xFF0C;&#x540C;&#x65F6;&#x540E;&#x9762;&#x7684;&#x6BCF;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x90FD;&#x4FDD;&#x7559;&#x4E86;&#x524D;&#x4E00;&#x4E2A;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#x3002;</p><h2 id="%E6%80%BB%E7%BB%93">&#x603B;&#x7ED3;</h2><p>&#x5728;&#x672C;&#x7AE0;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x6784;&#x5EFA;&#x4E86;&#x4E00;&#x4E2A;&#x6700;&#x7B80;&#x5355;&#x7684;&#x533A;&#x5757;&#x94FE;&#x6A21;&#x578B;&#x3002;&#x672C;&#x7AE0;&#x9700;&#x8981;&#x91CD;&#x70B9;&#x7406;&#x89E3;&#x533A;&#x5757;&#x4E0E;&#x533A;&#x5757;&#x94FE;&#x7684;&#x5173;&#x7CFB;&#xFF0C;&#x533A;&#x5757;&#x7684;&#x54C8;&#x5E0C;&#x503C;&#x7684;&#x610F;&#x4E49;&#xFF0C;&#x4EE5;&#x53CA;&#x521B;&#x4E16;&#x533A;&#x5757;&#x7684;&#x6784;&#x5EFA;&#x3002;&#x5728;&#x4E0B;&#x4E00;&#x7AE0;&#x4E2D;&#xFF0C;&#x6211;&#x4EEC;&#x5C06;&#x8BB2;&#x89E3;PoW(Proof of Work)&#x5171;&#x8BC6;&#x673A;&#x5236;&#xFF0C;&#x5E76;&#x589E;&#x52A0;&#x4E00;&#x4E9B;&#x533A;&#x5757;&#x7ED3;&#x6784;&#x4F53;&#x7684;&#x5934;&#x90E8;&#x4FE1;&#x606F;&#x3002;</p>]]></content:encoded></item><item><title><![CDATA[2025微博V影响力大会]]></title><description><![CDATA[<p>10&#x6708;19&#x65E5;&#xFF0C;&#x4E3A;&#x671F;&#x4E24;&#x5929;&#x7684;2025&#x5FAE;&#x535A;V&#x5F71;&#x54CD;&#x529B;&#x5927;&#x4F1A;&#x5728;&#x5317;&#x4EAC;&#xB7;&#x5FAE;&#x535A;IN&#x8DE8;&#x6B21;&#x5143;&#x5F15;&#x529B;&#x573A;&#x5706;&#x6EE1;&#x843D;&#x5E55;&#x3002;&#x4F5C;&#x4E3A;&#x5FAE;&#x535A;&#x7684;&#x5E74;&#x5EA6;&#x91CD;&#x78C5;&#x5E73;&#x53F0;&#x7EA7;&#x6D3B;</p>]]></description><link>http://www.net-e.cn/welcome/</link><guid isPermaLink="false">611b1b26681cac0001a7edcc</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:59 GMT</pubDate><content:encoded><![CDATA[<p>10&#x6708;19&#x65E5;&#xFF0C;&#x4E3A;&#x671F;&#x4E24;&#x5929;&#x7684;2025&#x5FAE;&#x535A;V&#x5F71;&#x54CD;&#x529B;&#x5927;&#x4F1A;&#x5728;&#x5317;&#x4EAC;&#xB7;&#x5FAE;&#x535A;IN&#x8DE8;&#x6B21;&#x5143;&#x5F15;&#x529B;&#x573A;&#x5706;&#x6EE1;&#x843D;&#x5E55;&#x3002;&#x4F5C;&#x4E3A;&#x5FAE;&#x535A;&#x7684;&#x5E74;&#x5EA6;&#x91CD;&#x78C5;&#x5E73;&#x53F0;&#x7EA7;&#x6D3B;&#x52A8;&#xFF0C;&#x672C;&#x5C4A;&#x5927;&#x4F1A;&#x4EE5;&#x201C;&#x5C3D;&#x5174;&#x5206;&#x4EAB;&#xFF0C;&#x81EA;&#x6210;&#x5F71;&#x54CD;&#x201D;&#x4E3A;&#x4E3B;&#x9898;&#xFF0C;&#x6C47;&#x805A;&#x4E86;&#x5404;&#x9886;&#x57DF;&#x5934;&#x90E8;&#x521B;&#x4F5C;&#x8005;&#x3001;&#x884C;&#x4E1A;&#x5927;&#x5496;&#x53CA;&#x54C1;&#x724C;&#x4EE3;&#x8868;&#xFF0C;&#x6D3B;&#x52A8;&#x73B0;&#x573A;&#x4E0D;&#x4EC5;&#x63ED;&#x6653;&#x4E86;&#x5907;&#x53D7;&#x77A9;&#x76EE;&#x7684;&#x4E5D;&#x5927;&#x5E74;&#x5EA6;&#x8363;&#x8A89;&#xFF0C;&#x66F4;&#x901A;&#x8FC7;&#x5E73;&#x53F0;&#x653F;&#x7B56;&#x5BA3;&#x8BB2;&#x4E0E;&#x535A;&#x4E3B;&#x5206;&#x4EAB;&#x8F93;&#x51FA;&#x4E86;&#x6EE1;&#x6EE1;&#x7684;&#x884C;&#x4E1A;&#x5E72;&#x8D27;&#x3002;&#x800C;&#x8FDE;&#x7EED;&#x4E24;&#x65E5;&#x5F00;&#x653E;&#x7684;&#x6D6A;&#x6D6A;&#x53CB;&#x4EBA;&#x90E8;&#x843D;&#xFF0C;&#x51ED;&#x501F;&#x4E30;&#x5BCC;&#x7684;&#x4E92;&#x52A8;&#x73A9;&#x6CD5;&#x4E0E;&#x96F6;&#x8DDD;&#x79BB;&#x7684;&#x7C89;&#x4E1D;&#x89C1;&#x9762;&#x4F1A;&#xFF0C;&#x5C06;&#x73B0;&#x573A;&#x6C14;&#x6C1B;&#x4E0D;&#x65AD;&#x63A8;&#x5411;&#x9AD8;&#x6F6E;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2025%2F1020%2F2b3b72e7j00t4eokh01bkd000za00nig.jpg&amp;thumbnail=660x2147483647&amp;quality=80&amp;type=jpg" class="kg-image" alt="2025&#x5FAE;&#x535A;V&#x5F71;&#x54CD;&#x529B;&#x5927;&#x4F1A;&#x5706;&#x6EE1;&#x843D;&#x5E55;&#xFF0C;&#x8D4B;&#x80FD;&#x521B;&#x4F5C;&#x8005;&#x751F;&#x6001;&#x65B0;&#x672A;&#x6765;" loading="lazy"></figure><p>&#x5317;&#x4EAC;&#x7F51;&#x7535;&#x521B;&#x65B0;&#x79D1;&#x6280;&#x6709;&#x9650;&#x516C;&#x53F8;&#xFF0C;&#x4E3A;&#x6B64;&#x6B21;&#x6D3B;&#x52A8;&#x5168;&#x7A0B;&#x63D0;&#x4F9B;&#x5BA4;&#x5185;&#xFF0C;&#x6237;&#x5916;&#xFF0C;&#x6709;&#x7EBF;&#x548C;&#x65E0;&#x7EBF;&#x7F51;&#x7EDC;&#x5168;&#x8986;&#x76D6;&#xFF0C;&#x4FDD;&#x8BC1;&#x6D3B;&#x52A8;&#x7684;&#x987A;&#x5229;&#x8FDB;&#x884C;&#x3002;</p>]]></content:encoded></item><item><title><![CDATA[美团主办的第八届餐饮产业大会]]></title><description><![CDATA[<p>10&#x6708;16&#x65E5;&#xFF0C;&#x7531;&#x7F8E;&#x56E2;&#x4E3B;&#x529E;&#x7684;&#x7B2C;&#x516B;&#x5C4A;&#x9910;&#x996E;&#x4EA7;&#x4E1A;&#x5927;&#x4F1A;&#x5728;&#x5317;&#x4EAC;&#x56FD;&#x8D38;&#x4E09;&#x671F;&#x5927;&#x9152;&#x5E97;&#x4E3E;&#x529E;&#xFF0C;&#x4E0A;&#x5343;&#x4F4D;&#x9910;&#x996E;&#x5546;&#x5BB6;&#x8D1F;&#x8D23;&#x4EBA;&#x9F50;&#x805A;&#xFF0C;&#x5171;&#x63A2;&#x884C;&#x4E1A;</p>]]></description><link>http://www.net-e.cn/design/</link><guid isPermaLink="false">611b1b26681cac0001a7edca</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:58 GMT</pubDate><content:encoded><![CDATA[<p>10&#x6708;16&#x65E5;&#xFF0C;&#x7531;&#x7F8E;&#x56E2;&#x4E3B;&#x529E;&#x7684;&#x7B2C;&#x516B;&#x5C4A;&#x9910;&#x996E;&#x4EA7;&#x4E1A;&#x5927;&#x4F1A;&#x5728;&#x5317;&#x4EAC;&#x56FD;&#x8D38;&#x4E09;&#x671F;&#x5927;&#x9152;&#x5E97;&#x4E3E;&#x529E;&#xFF0C;&#x4E0A;&#x5343;&#x4F4D;&#x9910;&#x996E;&#x5546;&#x5BB6;&#x8D1F;&#x8D23;&#x4EBA;&#x9F50;&#x805A;&#xFF0C;&#x5171;&#x63A2;&#x884C;&#x4E1A;&#x957F;&#x6548;&#x7ECF;&#x8425;&#x65B0;&#x601D;&#x8DEF;&#x3002;</p><figure class="kg-card kg-image-card"><img src="https://www.xinhuanet.com/tech/20251017/5ed14f2b22104f36989425c7f9611dbe/202510175ed14f2b22104f36989425c7f9611dbe_202510174be61c864740431f92ec88fb9d0eec16.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://www.xinhuanet.com/tech/20251017/5ed14f2b22104f36989425c7f9611dbe/202510175ed14f2b22104f36989425c7f9611dbe_20251017283ee314f0cd4d2e8928132e0e55ef81.png" class="kg-image" alt loading="lazy"></figure><p>&#x5317;&#x4EAC;&#x7F51;&#x7535;&#x521B;&#x65B0;&#x79D1;&#x6280;&#x6709;&#x9650;&#x516C;&#x53F8;&#xFF0C;&#x4E3A;&#x6B64;&#x6B21;&#x6D3B;&#x52A8;&#x5168;&#x7A0B;&#x63D0;&#x4F9B;&#x5BA4;&#x5185;&#xFF0C;&#x6237;&#x5916;&#xFF0C;&#x6709;&#x7EBF;&#x548C;&#x65E0;&#x7EBF;&#x7F51;&#x7EDC;&#x5168;&#x8986;&#x76D6;&#xFF0C;&#x4FDD;&#x8BC1;&#x6D3B;&#x52A8;&#x7684;&#x987A;&#x5229;&#x8FDB;&#x884C;&#x3002;<br><br></p>]]></content:encoded></item><item><title><![CDATA[微软创想未来峰会]]></title><description><![CDATA[<p>&#x5FAE;&#x8F6F;&#x521B;&#x60F3;&#x672A;&#x6765;&#x5CF0;&#x4F1A;&#xFF0C;&#x5728;&#x4E2D;&#x5173;&#x6751;&#x56FD;&#x9645;&#x521B;&#x65B0;&#x4E2D;&#x5FC3; |2025 &#x5E74; 4 &#x6708; 23 &#x65E5;&#x987A;&#x5229;&#x4E3E;&#x529E;&#xFF0C;&#x5317;&#x4EAC;&#x7F51;&#x7535;&#x521B;&#x65B0;&#x79D1;&#x6280;&#x6709;&#x9650;&#x516C;&#x53F8;&#xFF0C;&#x4E3A;&#x6B64;&#x6B21;&#x6D3B;&#x52A8;&#x5168;&#x7A0B;</p>]]></description><link>http://www.net-e.cn/write/</link><guid isPermaLink="false">611b1b26681cac0001a7edc8</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:57 GMT</pubDate><content:encoded><![CDATA[<p>&#x5FAE;&#x8F6F;&#x521B;&#x60F3;&#x672A;&#x6765;&#x5CF0;&#x4F1A;&#xFF0C;&#x5728;&#x4E2D;&#x5173;&#x6751;&#x56FD;&#x9645;&#x521B;&#x65B0;&#x4E2D;&#x5FC3; |2025 &#x5E74; 4 &#x6708; 23 &#x65E5;&#x987A;&#x5229;&#x4E3E;&#x529E;&#xFF0C;&#x5317;&#x4EAC;&#x7F51;&#x7535;&#x521B;&#x65B0;&#x79D1;&#x6280;&#x6709;&#x9650;&#x516C;&#x53F8;&#xFF0C;&#x4E3A;&#x6B64;&#x6B21;&#x6D3B;&#x52A8;&#x5168;&#x7A0B;&#x63D0;&#x4F9B;&#x5BA4;&#x5185;&#xFF0C;&#x6237;&#x5916;&#xFF0C;&#x6709;&#x7EBF;&#x548C;&#x65E0;&#x7EBF;&#x7F51;&#x7EDC;&#x5168;&#x8986;&#x76D6;&#x3002;&#x503C;&#x5F97;&#x4E00;&#x63D0;&#x7684;&#x662F;&#xFF0C;&#x4E3A;&#x4E09;&#x4E2A;&#x9AD8;&#x5BC6;&#x5EA6;&#x7684;&#x52A8;&#x624B;&#x5B9E;&#x9A8C;&#x5BA4;&#xFF0C;&#x63D0;&#x4F9B;&#x4E86;&#x5168;&#x8986;&#x76D6;&#xFF0C;&#x9AD8;&#x5BC6;&#x5EA6;&#xFF0C;&#x9AD8;&#x7F51;&#x901F;&#x7684;Wi-Fi6&#x7F51;&#x7EDC;&#x4FDD;&#x969C;&#x3002;</p><figure class="kg-card kg-image-card"><img src="http://www.net-e.cn/content/images/2025/10/image.png" class="kg-image" alt loading="lazy" width="2000" height="1500" srcset="http://www.net-e.cn/content/images/size/w600/2025/10/image.png 600w, http://www.net-e.cn/content/images/size/w1000/2025/10/image.png 1000w, http://www.net-e.cn/content/images/size/w1600/2025/10/image.png 1600w, http://www.net-e.cn/content/images/size/w2400/2025/10/image.png 2400w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[Building your audience with subscriber signups]]></title><description><![CDATA[How Ghost allows you to turn anonymous readers into an audience of active subscribers, so you know what's working and what isn't.]]></description><link>http://www.net-e.cn/portal/</link><guid isPermaLink="false">611b1b26681cac0001a7edc6</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:56 GMT</pubDate><media:content url="https://static.ghost.org/v4.0.0/images/creating-a-custom-theme.png" medium="image"/><content:encoded><![CDATA[<img src="https://static.ghost.org/v4.0.0/images/creating-a-custom-theme.png" alt="Building your audience with subscriber signups"><p>What sets Ghost apart from other products is that you can publish content and grow your audience using the same platform. Rather than just endlessly posting and hoping someone is listening, you can track real signups against your work and have them subscribe to be notified of future posts. The feature that makes all this possible is called <em>Portal</em>.</p><p>Portal is an embedded interface for your audience to sign up to your site. It works on every Ghost site, with every theme, and for any type of publisher. </p><p>You can customize the design, content and settings of Portal to suit your site, whether you just want people to sign up to your newsletter &#x2014; or you&apos;re running a full premium publication with user sign-ins and private content.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://static.ghost.org/v4.0.0/images/portalsettings.png" class="kg-image" alt="Building your audience with subscriber signups" loading="lazy" width="2924" height="1810"></figure><p>Once people sign up to your site, they&apos;ll receive an email confirmation with a link to click. The link acts as an automatic sign-in, so subscribers will be automatically signed-in to your site when they click on it. There are a couple of interesting angles to this:</p><p>Because subscribers are automatically able to sign in and out of your site as registered members: You can (optionally) restrict access to posts and pages depending on whether people are signed-in or not. So if you want to publish some posts for free, but keep some really great stuff for members-only, this can be a great draw to encourage people to sign up!</p><p>Ghost members sign in using email authentication links, so there are no passwords for people to set or forget. You can turn any list of email subscribers into a database of registered members who can sign in to your site. Like magic.</p><p>Portal makes all of this possible, and it appears by default as a floating button in the bottom-right corner of your site. When people are logged out, clicking it will open a sign-up/sign-in window. When members are logged in, clicking the Portal button will open the account menu where they can edit their name, email, and subscription settings.</p><p>The floating Portal button is completely optional. If you prefer, you can add manual links to your content, navigation, or theme to trigger it instead.</p><p>Like this! <a href="#/portal">Sign up here</a></p><hr><p>As you start to grow your registered audience, you&apos;ll be able to get a sense of who you&apos;re publishing <em>for</em> and where those people are coming <em>from</em>. Best of all: You&apos;ll have a straightforward, reliable way to connect with people who enjoy your work.</p><p>Social networks go in and out of fashion all the time. Email addresses are timeless.</p><p>Growing your audience is valuable no matter what type of site you run, but if your content <em>is</em> your business, then you might also be interested in <a href="http://www.net-e.cn/sell/">setting up premium subscriptions</a>.</p>]]></content:encoded></item><item><title><![CDATA[Selling premium memberships with recurring revenue]]></title><description><![CDATA[<p>For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business.</p><p>Connect your <a href="https://stripe.com">Stripe</a> account to Ghost, and you&apos;ll be able to quickly and easily create monthly and yearly premium</p>]]></description><link>http://www.net-e.cn/sell/</link><guid isPermaLink="false">611b1b26681cac0001a7edc4</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:55 GMT</pubDate><media:content url="https://static.ghost.org/v4.0.0/images/organizing-your-content.png" medium="image"/><content:encoded><![CDATA[<img src="https://static.ghost.org/v4.0.0/images/organizing-your-content.png" alt="Selling premium memberships with recurring revenue"><p>For creators and aspiring entrepreneurs looking to generate a sustainable recurring revenue stream from their creative work, Ghost has built-in payments allowing you to create a subscription commerce business.</p><p>Connect your <a href="https://stripe.com">Stripe</a> account to Ghost, and you&apos;ll be able to quickly and easily create monthly and yearly premium plans for members to subscribe to, as well as complimentary plans for friends and family.</p><p>Ghost takes <strong>0% payment fees</strong>, so everything you make is yours to keep!</p><p>Using subscriptions, you can build an independent media business like <a href="https://stratechery.com">Stratechery</a>, <a href="https://www.theinformation.com">The Information</a>, or <a href="https://thebrowser.com">The Browser</a>.</p><p>The creator economy is just getting started, and Ghost allows you to build something based on technology that you own and control.</p><figure class="kg-card kg-image-card kg-card-hascaption"><a href="https://thebrowser.com"><img src="https://static.ghost.org/v4.0.0/images/thebrowser.jpg" class="kg-image" alt="Selling premium memberships with recurring revenue" loading="lazy" width="1600" height="2000"></a><figcaption>The Browser has over 10,000 paying subscribers</figcaption></figure><p>Most successful subscription businesses publish a mix of free and paid posts to attract a new audience, and upsell the most loyal members to a premium offering. You can also mix different access levels within the same post, showing a free preview to logged out members and then, right when you&apos;re ready for a cliffhanger, that&apos;s a good time to...</p>]]></content:encoded></item><item><title><![CDATA[How to grow your business around an audience]]></title><description><![CDATA[A guide to collaborating with other staff users to publish, and some resources to help you with the next steps of growing your business]]></description><link>http://www.net-e.cn/grow/</link><guid isPermaLink="false">611b1b26681cac0001a7edc2</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:54 GMT</pubDate><media:content url="https://static.ghost.org/v4.0.0/images/admin-settings.png" medium="image"/><content:encoded><![CDATA[<img src="https://static.ghost.org/v4.0.0/images/admin-settings.png" alt="How to grow your business around an audience"><p>As you grow, you&apos;ll probably want to start inviting team members and collaborators to your site. Ghost has a number of different user roles for your team:</p><p><strong>Contributors</strong><br>This is the base user level in Ghost. Contributors can create and edit their own draft posts, but they are unable to edit drafts of others or publish posts. Contributors are <strong>untrusted</strong> users with the most basic access to your publication.</p><p><strong>Authors</strong><br>Authors are the 2nd user level in Ghost. Authors can write, edit and publish their own posts. Authors are <strong>trusted</strong> users. If you don&apos;t trust users to be allowed to publish their own posts, they should be set as Contributors.</p><p><strong>Editors</strong><br>Editors are the 3rd user level in Ghost. Editors can do everything that an Author can do, but they can also edit and publish the posts of others - as well as their own. Editors can also invite new Contributors &amp; Authors to the site.</p><p><strong>Administrators</strong><br>The top user level in Ghost is Administrator. Again, administrators can do everything that Authors and Editors can do, but they can also edit all site settings and data, not just content. Additionally, administrators have full access to invite, manage or remove any other user of the site.<br><br><strong>The Owner</strong><br>There is only ever one owner of a Ghost site. The owner is a special user which has all the same permissions as an Administrator, but with two exceptions: The Owner can never be deleted. And in some circumstances the owner will have access to additional special settings if applicable. For example: billing details, if using <a href="https://ghost.org/pricing/"><strong>Ghost(Pro)</strong></a>.</p><blockquote><em>Ask all of your users to fill out their user profiles, including bio and social links. These will populate rich structured data for posts and generally create more opportunities for themes to fully populate their design.</em></blockquote><hr><p>If you&apos;re looking for insights, tips and reference materials to expand your content business, here&apos;s 5 top resources to get you started:</p><ul><li><a href="https://ghost.org/blog/how-to-create-a-newsletter/"><strong>How to create a premium newsletter (+ some case studies)</strong></a><strong> </strong> <br>Learn how others run successful paid email newsletter products</li><li><strong><a href="https://ghost.org/blog/membership-sites/">The ultimate guide to membership websites for creators</a></strong><br>Tips to help you build, launch and grow your new membership business</li><li><strong><a href="https://newsletterguide.org/">The Newsletter Guide</a></strong><br>A 201 guide for taking your newsletters to the next level</li><li><a href="https://ghost.org/blog/find-your-niche-creator-economy/"><strong>The proven way to find your niche, explained</strong></a><br>Find the overlap and find a monetizable niche that gets noticed</li><li><strong><a href="https://ghost.org/blog/newsletter-referral-programs/">Should you launch a referral program? </a></strong><br>Strategies for building a sustainable referral growth machine</li></ul>]]></content:encoded></item><item><title><![CDATA[Setting up apps and custom integrations]]></title><description><![CDATA[Work with all your favorite apps and tools or create your own custom integrations using the Ghost API.]]></description><link>http://www.net-e.cn/integrations/</link><guid isPermaLink="false">611b1b25681cac0001a7edc0</guid><category><![CDATA[Getting Started]]></category><dc:creator><![CDATA[Ghost]]></dc:creator><pubDate>Tue, 17 Aug 2021 02:12:53 GMT</pubDate><media:content url="https://static.ghost.org/v4.0.0/images/app-integrations.png" medium="image"/><content:encoded><![CDATA[<img src="https://static.ghost.org/v4.0.0/images/app-integrations.png" alt="Setting up apps and custom integrations"><p>It&apos;s possible to extend your Ghost site and connect it with hundreds of the most popular apps and tools using integrations. </p><p>Whether you need to automatically publish new posts on social media, connect your favorite analytics tool, sync your community or embed forms into your content &#x2014; our <a href="https://ghost.org/integrations/">integrations library</a> has got it all covered with hundreds of integration tutorials.</p><p>Many integrations are as simple as inserting an embed by pasting a link, or copying a snippet of code directly from an app and pasting it into Ghost. Our integration tutorials are used by creators of all kinds to get apps and integrations up and running in no time &#x2014; no technical knowledge required.</p><figure class="kg-card kg-image-card kg-width-full"><img src="https://static.ghost.org/v4.0.0/images/integrations-icons.png" class="kg-image" alt="Setting up apps and custom integrations" loading="lazy"></figure><h2 id="zapier">Zapier</h2><p>Zapier is a no-code tool that allows you to build powerful automations, and our official integration allows you to connect your Ghost site to more than 1,000 external services.</p><blockquote><strong>Example</strong>: When someone new subscribes to a newsletter on a Ghost site (Trigger) then the contact information is automatically pushed into MailChimp (Action).</blockquote><p><strong>Here&apos;s a few of the most popular automation templates:</strong> </p><!--kg-card-begin: markdown--><script src="https://zapier.com/apps/embed/widget.js?services=Ghost,-shortcm,-hubspot,-sendpulse,-noticeable,-aweber,-icontact,-facebook-pages,-github,-medium,-slack,-mailchimp,-activecampaign,-twitter,-discourse&amp;container,-convertkit,-drip,-airtable=true&amp;limit=5"></script>
<!--kg-card-end: markdown--><h2 id="custom-integrations">Custom integrations</h2><p>For more advanced automation, it&apos;s possible to create custom Ghost integrations with dedicated API keys from the Integrations page within Ghost Admin. </p><figure class="kg-card kg-image-card"><img src="https://static.ghost.org/v4.0.0/images/iawriter-integration.png" class="kg-image" alt="Setting up apps and custom integrations" loading="lazy" width="2244" height="936"></figure><p>These custom integrations allow you to use the Ghost API without needing to write code, and create powerful workflows such as sending content from your favorite desktop editor into Ghost as a new draft.</p>]]></content:encoded></item></channel></rss>