diff --git a/2017/09/01/TODO/index.html b/2017/09/01/TODO/index.html
deleted file mode 100644
index 1d8f5df..0000000
--- a/2017/09/01/TODO/index.html
+++ /dev/null
@@ -1,273 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>TODO | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Log Rotator Linearizability Chord Broker Heap Load Balancing xargs Bluetooth Countmin sketch Monte Carlo search tree Blob Video Streamer Paxos Daemon Channels of Channels Benchmark Markov Chain pprof">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="TODO">
-<meta property="og:url" content="https://oceanoverflow.github.io/2017/09/01/TODO/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Log Rotator Linearizability Chord Broker Heap Load Balancing xargs Bluetooth Countmin sketch Monte Carlo search tree Blob Video Streamer Paxos Daemon Channels of Channels Benchmark Markov Chain pprof">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-07-05T13:28:01.025Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="TODO">
-<meta name="twitter:description" content="Log Rotator Linearizability Chord Broker Heap Load Balancing xargs Bluetooth Countmin sketch Monte Carlo search tree Blob Video Streamer Paxos Daemon Channels of Channels Benchmark Markov Chain pprof">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TODO"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      TODO
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2017-09-01T13:20:48.000Z" itemprop="datePublished">
-        Sep 1, 2017
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <ul>
-<li>Log Rotator</li>
-<li>Linearizability</li>
-<li>Chord</li>
-<li>Broker</li>
-<li>Heap Load Balancing</li>
-<li>xargs</li>
-<li>Bluetooth</li>
-<li>Countmin sketch</li>
-<li>Monte Carlo search tree</li>
-<li>Blob</li>
-<li>Video Streamer</li>
-<li>Paxos</li>
-<li>Daemon</li>
-<li>Channels of Channels</li>
-<li>Benchmark</li>
-<li>Markov Chain</li>
-<li>pprof</li>
-<li>HyperLogLog</li>
-<li>Adapter</li>
-<li>Reflect</li>
-<li>FUSE</li>
-<li>Memory Allocation</li>
-<li>Garbage Collection</li>
-<li>Docker Network</li>
-<li>A * Search Algorithm</li>
-<li>B-Tree</li>
-<li>BitTorrent</li>
-</ul>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2017/09/02/LinuxManiac/index.html b/2017/09/02/LinuxManiac/index.html
deleted file mode 100644
index ecf19c0..0000000
--- a/2017/09/02/LinuxManiac/index.html
+++ /dev/null
@@ -1,246 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Linux Maniac | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Terminal keyboard shorcut: ctrl+a beginning of the shellctrl+e end of the shellalt+b backward one wordalt-f dorward one wordctrl+r reverse search ( ctrl+r again)ctrl+l clearctrl+g back to work">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Linux Maniac">
-<meta property="og:url" content="https://oceanoverflow.github.io/2017/09/02/LinuxManiac/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Terminal keyboard shorcut: ctrl+a beginning of the shellctrl+e end of the shellalt+b backward one wordalt-f dorward one wordctrl+r reverse search ( ctrl+r again)ctrl+l clearctrl+g back to work">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-07-05T13:27:28.241Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Linux Maniac">
-<meta name="twitter:description" content="Terminal keyboard shorcut: ctrl+a beginning of the shellctrl+e end of the shellalt+b backward one wordalt-f dorward one wordctrl+r reverse search ( ctrl+r again)ctrl+l clearctrl+g back to work">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-LinuxManiac"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Linux Maniac
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2017-09-02T13:24:46.000Z" itemprop="datePublished">
-        Sep 2, 2017
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>Terminal keyboard shorcut:</p>
-<p><code>ctrl+a</code> beginning of the shell<br><code>ctrl+e</code> end of the shell<br><code>alt+b</code> backward one word<br><code>alt-f</code> dorward one word<br><code>ctrl+r</code> reverse search ( <code>ctrl+r</code> again)<br><code>ctrl+l</code> clear<br><code>ctrl+g</code> back to work</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2017/12/07/openssl/index.html b/2017/12/07/openssl/index.html
deleted file mode 100644
index 034b02f..0000000
--- a/2017/12/07/openssl/index.html
+++ /dev/null
@@ -1,260 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>openssl | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="下面我们来看一下如何使用 openssl 这个命令行工具产生公钥/私钥密钥对，并且使用私钥对文件进行签名和使用公钥进行验证。 生成公钥/私钥密钥对$ ssh-keygen -t ecdsa -C &amp;quot;foo@bar.cn&amp;quot; 如果想要使用其他签名方式如 RSA 进行签名，可以将上述命令中的ecdsa 替换成 rsa 。使用上述命令默认在 .ssh/ 目录下生成两个文件。  ~/.s">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="openssl">
-<meta property="og:url" content="https://oceanoverflow.github.io/2017/12/07/openssl/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="下面我们来看一下如何使用 openssl 这个命令行工具产生公钥/私钥密钥对，并且使用私钥对文件进行签名和使用公钥进行验证。 生成公钥/私钥密钥对$ ssh-keygen -t ecdsa -C &amp;quot;foo@bar.cn&amp;quot; 如果想要使用其他签名方式如 RSA 进行签名，可以将上述命令中的ecdsa 替换成 rsa 。使用上述命令默认在 .ssh/ 目录下生成两个文件。  ~/.s">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:12.710Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="openssl">
-<meta name="twitter:description" content="下面我们来看一下如何使用 openssl 这个命令行工具产生公钥/私钥密钥对，并且使用私钥对文件进行签名和使用公钥进行验证。 生成公钥/私钥密钥对$ ssh-keygen -t ecdsa -C &amp;quot;foo@bar.cn&amp;quot; 如果想要使用其他签名方式如 RSA 进行签名，可以将上述命令中的ecdsa 替换成 rsa 。使用上述命令默认在 .ssh/ 目录下生成两个文件。  ~/.s">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-openssl"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      openssl
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2017-12-07T05:17:05.000Z" itemprop="datePublished">
-        Dec 7, 2017
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>下面我们来看一下如何使用 <code>openssl</code> 这个命令行工具产生公钥/私钥密钥对，并且使用私钥对文件进行签名和使用公钥进行验证。</p>
-<h2 id="生成公钥-私钥密钥对"><a href="#生成公钥-私钥密钥对" class="headerlink" title="生成公钥/私钥密钥对"></a>生成公钥/私钥密钥对</h2><p><code>$ ssh-keygen -t ecdsa -C &quot;foo@bar.cn&quot;</code></p>
-<p>如果想要使用其他签名方式如 <code>RSA</code> 进行签名，可以将上述命令中的<code>ecdsa</code> 替换成 <code>rsa</code> 。使用上述命令默认在 <code>.ssh/</code> 目录下生成两个文件。</p>
-<ul>
-<li><p>~/.ssh/id_ecdsa：这是你的私钥，私钥信息不能被泄露，如果别人拿到了你的私钥，别人就可以伪装成你。</p>
-</li>
-<li><p>~/.ssh/id_ecdsa.pub：这是你的公钥，公钥可以被大众知晓，你可以将公钥发布在网站上，便于其他人使用公钥对文件进行验证操作，一般来说私钥默认为 <code>chmod 600</code> ，而公钥默认为 <code>chmod 644</code> 。</p>
-</li>
-</ul>
-<h2 id="生成PKCS8版本的公钥"><a href="#生成PKCS8版本的公钥" class="headerlink" title="生成PKCS8版本的公钥"></a>生成PKCS8版本的公钥</h2><p>一般用 <code>openssl</code> 工具生成的公钥（ <code>id_ecdsa.pub</code> ）的格式并不是非常友好，如果你想要将你的公钥颁布在你的网站上以便于他人进行验证的话，可以使用另一种格式的公钥，使用以下命令生成 <code>PKCS8</code> 版本。</p>
-<p><code>$ ssh-keygen -e -f ~/.ssh/id_ecdsa.pub -m PKCS8 &gt; ~/.ssh/id_ecdsa.pub.pkcs8</code></p>
-<h2 id="使用私钥对文件进行签名"><a href="#使用私钥对文件进行签名" class="headerlink" title="使用私钥对文件进行签名"></a>使用私钥对文件进行签名</h2><p>如果你有一个需要被签名的文件为 <code>foo.txt</code> ，可以使用以下命令对文件进行签名。</p>
-<p><code>$ openssl dgst -sha256 -sign ~/.ssh/id_ecdsa foo.txt &gt; foo.txt.sig</code></p>
-<p><code>-sha256</code> 代表你使用 <code>sha256</code> 来生成信息摘要，生成的签名保存在 <code>foo.txt.sig</code> 中，可以使用 <code>hexdump</code> 来查看签名的内容。</p>
-<h2 id="使用公钥对文件签名进行验证"><a href="#使用公钥对文件签名进行验证" class="headerlink" title="使用公钥对文件签名进行验证"></a>使用公钥对文件签名进行验证</h2><p>在使用公钥对文件进行验证之前，你需要有 <code>pkcs8</code> 格式的公钥，及需要被验证的文件（ <code>foo.txt</code> ）及该文件的签名（ <code>foo.txt.sig</code> ），还需要指定与签名时相同的哈希算法（ <code>sha256</code> ）来对文件进行验证。</p>
-<p><code>$ openssl dgst -sha256 -verify ~/.ssh/id_ecdsa.pub.pkcs8 -signature foo.txt.sign foo.txt</code></p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/02/05/CryptoBasic/index.html b/2018/02/05/CryptoBasic/index.html
deleted file mode 100644
index a43ad7d..0000000
--- a/2018/02/05/CryptoBasic/index.html
+++ /dev/null
@@ -1,296 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Cryptography Basics | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="安全基础当在互联网上交换数据时，被传输的数据会经过各种各样的设备和网络后才能到达目的地，正是因为如此，安全技术在互联网时代才显得如此重要。在数据在网络上传输的过程中，存在着4个比较显著的问题。  当A想要向B发送消息时，可能存在第三方X来截获消息的内容，这种问题称为“interception”。 即使A本来要将消息发送给B，也存在X伪装成B来接收消息的可能性；同样的，也存在B相信接收到的消息来自于">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Cryptography Basics">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/02/05/CryptoBasic/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="安全基础当在互联网上交换数据时，被传输的数据会经过各种各样的设备和网络后才能到达目的地，正是因为如此，安全技术在互联网时代才显得如此重要。在数据在网络上传输的过程中，存在着4个比较显著的问题。  当A想要向B发送消息时，可能存在第三方X来截获消息的内容，这种问题称为“interception”。 即使A本来要将消息发送给B，也存在X伪装成B来接收消息的可能性；同样的，也存在B相信接收到的消息来自于">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:44:45.318Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Cryptography Basics">
-<meta name="twitter:description" content="安全基础当在互联网上交换数据时，被传输的数据会经过各种各样的设备和网络后才能到达目的地，正是因为如此，安全技术在互联网时代才显得如此重要。在数据在网络上传输的过程中，存在着4个比较显著的问题。  当A想要向B发送消息时，可能存在第三方X来截获消息的内容，这种问题称为“interception”。 即使A本来要将消息发送给B，也存在X伪装成B来接收消息的可能性；同样的，也存在B相信接收到的消息来自于">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-CryptoBasic"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Cryptography Basics
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-02-05T14:39:55.000Z" itemprop="datePublished">
-        Feb 5, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <h2 id="安全基础"><a href="#安全基础" class="headerlink" title="安全基础"></a>安全基础</h2><p>当在互联网上交换数据时，被传输的数据会经过各种各样的设备和网络后才能到达目的地，正是因为如此，安全技术在互联网时代才显得如此重要。在数据在网络上传输的过程中，存在着4个比较显著的问题。</p>
-<ol>
-<li>当A想要向B发送消息时，可能存在第三方X来截获消息的内容，这种问题称为“interception”。</li>
-<li>即使A本来要将消息发送给B，也存在X伪装成B来接收消息的可能性；同样的，也存在B相信接收到的消息来自于A，但实际上是X伪装成A来发送这条消息，这种问题被称为“spoofing”。</li>
-<li>假设A向B发送的消息已经完成了，也存在在消息的发送过程中，X篡改消息的内容的可能性，这种问题被称为“falsification”。除了有意的消息篡改以外，也存在消息在发送的过程中因为传输设备出现异常而出错的可能性。</li>
-<li>最后一个问题，就是假设B已经正确地接受到了A发送的消息，但是发送方A出于自己的私心考虑，否认了这条消息是由他自己发出的，当出现这种情况时，互联网将无法成为商业交易或商业合同签署合格的媒介，这种问题被称为“repudiation”。</li>
-</ol>
-<p>当然上述4个问题并不仅限于人与人的信息交换之间，同时也存在我们日常上网的过程中。下面我们来简单的介绍一下解决上述问题的安全技术。<br>为了解决第一个问题中出现的消息被截获的问题，我们可以使用“加密”技术，解决第二个问题的方法可以是“消息验证码”或者“数字签名”技术。类似的，第三个问题同样也可以使用“消息验证码”或“数字签名”技术。还有“数字签名”技术还可以用于解决第四个问题—“repudiation”。</p>
-<p>其实数字签名本身也存在问题，就是它本身自己无法验证签名使用的公钥的拥有者的真实性，所以就出现了“数字证书”来解决数字签名本身的问题。</p>
-<h2 id="加密基础"><a href="#加密基础" class="headerlink" title="加密基础"></a>加密基础</h2><p>为什么在现代的互联网世界中我们需要加密技术呢？例如A需要向B发送消息，在消息到达B之前会经过各式各样的设备和网络，所以有很大的可能性消息会被恶意的第三方所截获，因此出于这种原因，在发送消息之前将消息加密就显得非常有必要了。</p>
-<p>被加密的数据被称为“秘文”，消息将会以秘文的形式发送给B，B收到A发送过来的秘文后，将其解密后就可以获得原来的消息。将加密的数据还原成数据的原始状态的过程被称为“解密”。当你将数据以加密的形式发送出去时，就可以不必当心恶意的第三方截获到你的数据了，正因为如此，加密技术在现代社会中才显得如此重要。下面，我们来仔细地了解一下在加密过程中涉及到的操作。</p>
-<p>我们知道，在计算机中，无论数据的类型是什么，计算机都将他们视为一系列二进制数据，也就是一长串的0和1。所以，尽管存在各种各样的数据格式，例如文本文件，音乐和影像，在计算机中，所有的数据都是以二进制数据进行管理的。同样，在加密的过程中，我们也可以以计算机管理数据那样的方式来思考我们的数据，数据就是一系列有意义的数字，虽然秘文同样也是一串数字，但是由于它们的随机性，计算机并不能正确地解释它们，加密就是通过计算，来将原来对于计算机来说有特定含义的数据转换成计算机无法解释的数据的一个过程。</p>
-<p>在加密的过程中，存在一个用于执行计算的一个“密钥”。这个密钥同样也是由数字组成。换一句话说，通过密钥来进行数值计算，加密可以将原本可读的数据转化为不可读的数据。反过来，解密就是通过密钥来进行数值计算，将不可读的数据转化为可读数据的一个过程。我们来通过一个“异或”理解加密和解密的过程，XOR(异或)的结果是根据真值表决定的，我们有：</p>
-<p>0 XOR 0 = 0 ；1 XOR 1 = 0；0 XOR 1 = 1；1 XOR 0 = 1</p>
-<p>异或操作的一个特点就是 A XOR B = C，B XOR C = A，这意味着如果C是A和B异或的结果，那么你就可以通过C与A和B中任意一个值进行异或操作来获得另外一个数字。将这个知识点用于加密和解密的过程中，我们可以将私钥和数据进行异或操作得到秘文，同理地，将生成的秘文与私钥再进行一次异或操作，我们就可以还原得到原来的明文。从上述过程中我们可以看出，相同的私钥被用于异或加密或解密数据的过程中。</p>
-<h2 id="哈希函数"><a href="#哈希函数" class="headerlink" title="哈希函数"></a>哈希函数</h2><p>一个“哈希函数”可以将不同长度的数据映射为定长的一个值，我们可以形象地将哈希函数理解为榨汁机，我们将我们的原始材料（我们的数据）放进榨汁机（哈希函数）得到我们的饮料（哈希值），与榨汁机类似，我们可以将原材料转化为我们的饮料，但是反过来饮料并不能通过一定的操作转化为我们的原材料。类比我们的哈希函数，我们可以将原始数据通过哈希操作转化为哈希值，但是我们不可以使用哈希值得到我们的原始数据，也就是说，哈希是一个不可逆的过程。哈希值其实就是一个数值，但是我们常常使用十六进制来表示。</p>
-<p>现在我们仔细地阐述一下哈希函数拥有的特点，第一点就是通过哈希函数得到的输出长度都是固定的，长度固定是针对特定的哈希函数而言的，例如SHA-1哈希函数得到的哈希值的长度都是20字节，这就意味着，即使你的输入数据非常大，但是通过SHA-1哈希之后，你得到的输出都是固定的20字节，类似的，不管你的输入数据有多小，你得到的输出依旧是20字节。哈希函数的第二个特点就是在哈希函数相同的情况下，相同的输入永远得到的是相同的输出。第三个特点也是非常重要的一个特点，就是你输入两个非常类似的数据，即使两个数据只相差1bit，得到的输出相差也会非常大。哈希值不会因为你的输入数据类似而得到相似的输出。第四个特点就是可能会存在输入的数据完全不同，依旧得到两个完全相同的哈希值，虽然这种概率非常小，这种情况被称为“哈希碰撞“。第五个特点就是哈希函数的单向性或者说是不可逆性，你几乎不可能通过哈希值得到原始数据，这也是哈希与加密之间一个非常重要的区别。哈希的最后一个特点就是计算哈希的过程可以非常简单。</p>
-<p>我们可以使用MD4，MD5，SHA-0，SHA-1，SHA-2之类的哈希函数，但是在现实生活中，我们最常使用的就是SHA-2。</p>
-<h2 id="共享密钥加密"><a href="#共享密钥加密" class="headerlink" title="共享密钥加密"></a>共享密钥加密</h2><p>共享密钥加密在加密和解密的过程中使用相同的私钥。假设A想要通过互联网将一段消息发送给B，在发送给B的过程中消息经过了很多不同的网络和设备。但是，如果A直接将消息以明文的形式发给B，则恶意第三方就非常容易截获该消息。正是因为这样，所以在传输消息的过程中通常需要经过加密处理。利用私钥，将明文加密为密文再进行发送。B利用相同的私钥将接收到的密文解密得到原文。所以，经过加密处理后，即使恶意第三方截取了消息，在不知道密钥的情况下，他也很难知道原文是什么。</p>
-<p>利用相同密钥进行加密和解密是共享密钥加密的一个特点，常见的共享密钥加密方法有凯撒加密，AES，DES，OTP等等，其中AES被使用的最为广泛。当然，共享密钥加密本身存在着一个致命的缺陷，假设B收到了A发送的密文，而且在发送的过程中，密文也可能被恶意第三方X所截获，现在存在的问题是，由于A和B可能从来没有直接接触过，B可能实现并不知道A用于加密的密钥，所以在这种情况下，A就需要某种机制把密钥传输给B，就像A向B传输密文一样，A同样需要在互联网上向B传输密钥，B利用接收到的来自A的密钥就可以对密文进行解密。然而，既然是在互联网上传播，恶意第三方X同样有机会截获到密钥，这样一来，X就可以用截获到的密钥对密文进行解密。</p>
-<p>在上述过程中 ，我们可以清楚地看到密钥本身传输存在问题，所以，组织A可以会想再通过对密钥本身进行加密后再传输，对于计算机来说，一个密钥仅仅是一段数据，所以我们可以使用新的密钥对老的密钥进行加密生成密文，再对密文进行传输，但是我们现在又需要一个机制来传输新的密钥，这样以来就会陷入一个循环，总结一下，共享密钥加密系统缺乏一个安全传输密钥的机制，这个问题被称为“密钥分发问题”。解决“密钥分发问题”有两种方法：</p>
-<ol>
-<li>使用如Diffie-Hellman 密钥交换这样的交换协议</li>
-<li>使用公钥加密算法</li>
-</ol>
-<h2 id="公钥加密"><a href="#公钥加密" class="headerlink" title="公钥加密"></a>公钥加密</h2><p>公钥加密与共享密钥加密最大的区别在与公钥加密在加密和解密时候使用的是不同的密钥，用于加密的密钥被称为“公钥”（public key），用于解密的密钥被称为“私钥”（private key），除了使用不同的密钥之外，公钥加密在加密和解密时比共享密钥加密需要花费的时间更长。常用的公钥加密有RSA加密和ECC加密（椭圆曲线加密）。<br>下面我们来了解一下在公钥加密的情况下数据是如何在双方之间交换的。</p>
-<p>假设A想要给B发送一段消息，首先，接受者B会生成一对密钥，分别是一个公钥和一个私钥，公钥部分将由B发送给A，A使用从B发送过来的公钥将消息加密，并将加密后的密文发送给B。B利用只有自己拥有的私钥将从A发送过来的密文进行解密，从而得到原始可读的消息，由于只有公钥和秘文在网上传输，而且只通过公钥并不能解密秘文，所以即使恶意的第三方截获了这两个信息，他也并不能解密获得原始消息。所以，公钥加密很好地解决了共享加密中私钥分发的问题。</p>
-<p>使用公钥加密的另一个好处就是在一个不确定人数的组织中交换数据非常方便，举一个例子，假设B已经事先准备好一对密钥，即一个公钥和与公钥相对应的私钥。因为公布自己的公钥并不会有什么影响，所以，B将自己的公钥公布在互联网上，另一方面，由于私钥是绝对不能让他人知晓的，所以私钥需要牢牢地守护。</p>
-<p>现在有多个个体需要向B发送数据，首先这些个体需要获取事先由B分享的公钥，然后利用公钥将需要发送的数据进行加密，最后将加密后的数据发送给B，B利用自己的私钥分别将收到的密文解密获得原来的数据，所以，在存在多个个体时，我们并不用准备多个公钥，还有一点就是，由于只有消息的接收者才具有用于解密的私钥，所以公钥加密的安全性非常之高。</p>
-<p>然而在存在着诸多优点的同时，公钥加密也存在着两个严重的问题。公钥加密存在的第一个问题就是公钥加密所需要花费的时间相对比较长，正是因为这样，公钥加密并不适用于来回交换大量的数据，为了解决这一点，出现了“混合加密”这样的解决方案。</p>
-<p>公钥加密的第二个问题在于公钥本身的可靠性。当B生成公钥和私钥时，为了方便起见，将B生成的公钥记为PB，将私钥记为SB，假设存在着恶意的第三方X，想要截获A发向B的数据，同时也生成了一对公私钥，分别记为PX和SX，当B向A发送自己的公钥PB时，X隐蔽地将B的公钥PB替换为自己的公钥PX，并将PX发送给A。由于通过公钥并不能发现公钥的产生者是谁，A并不能发现B的公钥有没有被第三方调包。接着A将自己的数据用公钥PX进行加密，当A将加密后的消息发送给B时，X截获了秘文，由于该秘文是用X的公钥PX加密的，X可以用自己的私钥SX来对秘文进行解密，这样以来，X成功截获了本来该发送给B的消息，接着，X将消息是用B的公钥PB加密后发送给B，由于过程中产生的密文是用B的公钥加密的，所以B可以利用自己的私钥SB对密文进行解密。正是因为B可以正确地对消息进行解密，A和B都无法知道其实消息已经被第三方截获过了。</p>
-<p>上述的通过替换公钥来截获消息的攻击方式被称为“中间人攻击”。这种问题的关键就在于A无法验证自己获取的公钥到底是来自B还是来自恶意的第三方X。为了解决“中间人攻击问题”，我们可以使用数字证书来解决这一问题。</p>
-<h2 id="混合加密"><a href="#混合加密" class="headerlink" title="混合加密"></a>混合加密</h2><p>如果使用共享密钥加密，我们会遇到“密钥分发问题”——如何安全地分发密钥，另一方面，如果使用公钥加密，漫长地加密解密问题又降低了信息传输的效率，混合加密的出现就整合了两者共同的优点，规避了两者的缺点。混合加密利用共享密钥加密加解密的高效性，而使用公钥加密来保障共享密钥的安全性。</p>
-<p>假设A要向B发送消息，可以利用共享加密方法进行高效地加密操作，因为用于加密的密钥也同样被用于解密，所以A需要把密钥安全地发送给B。其实密钥也是数据的一种形式，通过公钥加密，我们可以安全地将密钥发送给B。接收者B自己生成一对密钥，即一个公钥和一个私钥，B将公钥发送给A，A利用B的公钥对对称密钥进行对称加密处理，加密后的密钥然后再发送给B，B利用自己的私钥对加密后的密钥进行解密处理，这样以来，A就利用公钥加密将密钥安全地发送给B，现在剩下唯一要做的就是将经过对称密钥加密后的密文发送给B，由于共享密钥加密加密解密速度快，B就可以准确快速地接收到原始数据。</p>
-<p>上述过程我们可以清楚地看到混合加密整合了公钥加密的高安全性和共享密钥加密的快速加解密特点，混合加密已经被应用到SSL中，用于互联网上安全地交换数据。</p>
-<h2 id="消息验证码"><a href="#消息验证码" class="headerlink" title="消息验证码"></a>消息验证码</h2><p>消息验证码实现了两个功能，anthentication和falsification detection。首先，我们来认识一下为什么消息验证码有存在的必要。假设A需要从B那里购置一件商品，A向B发送自己要购买的商品编号“xyz”，然后A将该商品编号加密，假设加密使用了共享密钥进行加密，A先使用某种安全的方法将共享密钥加密方法使用的密钥传递给B，这种密钥交换方法可以是公钥加密或者Diffie-Hellman密钥交换手段。A使用共享密钥对需要发送的消息进行加密，这里的消息就是我们需要发送的商品编号，加密后得到的密文被发送给B，B得到密文后使用共享密钥进行解密后得到明文即A发送的商品编号，这个传输过程看起来好像并没有什么问题，但是现实生活中可能发生这样的事情，当A向B发送经过加密后的密文时，恶意第三方X将密文在传输过程中进行篡改，当B收到被篡改后的密文然后解密后，得到的商品编号却变成了“123”，而B并不知道商品编号已经被篡改过了，B将商品“123”而不是“xyz”发送给A。</p>
-<p>因为加密无非就是对原有数据进行数值计算，所以，解密的过程也可以在被篡改过的数据上进行，但是如果原消息是一个比较长的消息，而经过篡改后的密文解密后变成了一些没有实际意义的消息，那么消息的接收方可能会察觉到消息已经被篡改过了，但是是一些人类无法直接识别的消息例如上述的商品编号，那么就很难察觉出消息是否被篡改过了。所以，为了检测消息是否已经被恶意第三方篡改过，除了加密之外再增加一些手段就变得非常有必要了。</p>
-<p>消息验证码就是为了检测消息有无被篡改而出现的一种解决方案。下面我们来仔细看一看消息验证码是如何工作的。当A将加密后的密文发送给B之前，A同时生成一个用于消息验证码的密钥，然后A将该密钥以安全的方法发送给B，然后A利用该密钥和密文以特定算法生成一个值，这个由密钥和密文组合生成的值就被称为“消息验证码”，通常被简写为“MAC”，MAC值可以简单的理解为密钥和密文组合起来的哈希值，我们可以使用各种各样的方法来生成MAC值，例如HMAC，OMAC，CMAC等等，现实生活中HMAC被使用的最为广泛，生成MAC值以后，A连同密文和MAC值一同发送给B，B接收到以后，需要根据MAC值检测密文有无被第三方篡改，B和A一样，根据密文和密钥来重新生成MAC值，这样以来，根据A发送过来的MAC和B自己重新生成的MAC进行比较，如果两者相同则说明密文并没有被他人篡改，B剩下仅仅需要将密文解密得到原文。</p>
-<p>那么如果在A将密文发送给B的过程中，恶意第三方X将密文篡改的情况下会怎么样呢，假设在A将密文和MAC值发送给B的过程中，X篡改了密文，然而B收到以后重新计算MAC值，B会发现自己计算的MAC值和A发送的MAC值并不相同，这样以来，B就可以判断密文，MAC值或者两者都已经被篡改过了，在这种情况下，B可以选择将密文抛弃然后再重新请求A再次发送相同的密文。</p>
-<p>是否存在X将密文和MAC值同时改变从而让B重新计算出来的MAC值和被传输的MAC值一致的可能呢？由于X不知道用于生成MAC值的密钥，所以即使X能篡改传输中的消息，X也无法做到让两者的MAC值一致，所以B在重新计算MAC值时发现与被篡改后消息一起携带的MAC值不一样时，B就可以清楚地知道该消息已经被别人做过手脚了。</p>
-<p>经过上面的解释，我们可以清楚地看到使用消息验证码，或者MAC可以避免消息在传输的过程中被他人篡改，然而，消息验证码同时也存在着一些缺陷。由于A和B共享一对用于加密明文的密钥和用于生成MAC值的密钥，如果A可以加密消息和生成MAC值的话，那么B也可以还原这样的操作，B同样也可以加密消息和生成MAC值，换一句话说，你并不能区分原文是由A还是B生成的，那么假设A是恶意的，在A将消息发送给B后，A可以声称该消息是由B伪造生成的，这样A就否认了该消息是由他自己发送的，为了防止这种否认现象的出现，我们需要采取另外一种技术，也就是下面会讲的”数字签名“技术。</p>
-<h2 id="数字签名"><a href="#数字签名" class="headerlink" title="数字签名"></a>数字签名</h2><p>数字签名可以保证消息的不可否认性。数字签名除了完成了消息验证码实现了的authentication和falsification检测的功能之外，还实现了让消息的真实发送者无法否认这条消息是由他发送出的功能，这就是不可否认性。在仔细了解数字签名的工作原理之前，我们先回顾一下消息验证码。使用消息验证码的系统中，为了验证消息的发送者是真实的密钥拥有者，会将MAC值附着到要发送的消息上，为了方便起见，这里的消息以明文形式传输，A先以某种安全的方法将用于生成MAC的密钥发送给B，然后再将明文和MAC值发送给B，B根据收到的明文和密钥重新生成MAC值，然后再确认两者的MAC值是否相同，如果确认成功，那么就说明A是真实的发送者并且发送的明文没有经过他人篡改，然而由于消息验证码采用的是共享的密钥，依旧存在拥有该密码的组织伪装成为消息发送者的可能性，比如说，当A把一条消息发送给B之后，B却声称自己才是这条消息的创建者。还有一点就是，由于采用的是共享密钥来生成MAC值，那么当A与除了B之外的其他个体进行消息交流时，则需要生成一个新的密钥。</p>
-<p>为了解决消息验证码内在的问题，我们引入数字签名技术，数字签名技术不采用MAC，而是采用只有消息的真实发送者才能产生的数据为基础的技术，而这产生的数据就被称为“数字签名”。例如A要发送一段消息“abc”，A会生成一段只能由A生成的签名，所以，当A发送的带有原消息和签名的数据被接收方接收到时，接收方就可以保证发送方一定是A。消息的接收方B，可以判断数字签名来自发送者A，但是他们自己并不能生成这些数字签名。与消息验证码相对比，由于数字签名并没有使用共享密钥，所以A可以向不同的组织或个体发送相同的数字签名。</p>
-<p>我们知道用于生成MAC值的密钥是两方共享的，而当生成数字签名时，我们使用了和公钥加密系统类似的一个过程。我们在这里简单地回顾一下公钥加密的过程，首先如果A有消息要发送给B，接收方B会事先生成一对密钥，分别是公钥P和私钥S，B将公钥P传递给A，A使用B的公钥去加密自己的数据，然后再将加密后的密文发送给B，B利用只有自己才拥有的私钥S对密文进行解密，整个过程结束。所以在公钥加密中公钥被用于加密而私钥被用于解密，正是因为如此，任何人都可以使用公钥进行加密，但因为只有B才拥有私钥，故只有B才能进行解密。</p>
-<p>但如果我们将公钥加密的操作反向进行会怎么样呢，将私钥用于加密，而将公钥用于解密，在这种情况下，假设只有A才有私钥，只有他们才能加密数据，而加密生成的数据可以被任何持有对应公钥的人进行解密，但这样的加密手段没有任何意义，但是如果换一种角度去看的话，我们就可以理解为密文的生成者必定是持有私钥的A而不会是其他个体。<br>下面我们来仔细了解一下数字签名的整个流程。首先A准备需要发送的数据，以及一对公私钥，注意到由消息的发送者准备公私钥是与公钥加密不同的地方之一，在公钥加密中公私钥是由消息的接收方所准备的。A将自己的公钥发送给B，然后A利用自己的私钥对消息进行签名，签名结果就被用来当作数字签名，A将消息和数字签名一同发送给B，B利用A的公钥对数字签名进行验证，如果验证的消息与收到的消息一致，那么整个交换的过程就结束了。</p>
-<p>用A的私钥生成的数字签名，可以用A的公钥进行验证，但是该签名却只能由A生成，所以我们就可以确认A才是消息的发送者并且发送的消息没有被别人篡改过，而且，由于A的签名不能有除了A以外的组织例如B生成，因为B只有公钥，所以数字签名同时也实现了不可否认性这一功能。</p>
-<p>然而，和公钥加密类似，加密和解密与签名和验证都需要花费很多的时间，所以，我们不直接对消息进行签名，为了减少计算所需要的时间，我们首先生成消息对应的哈希值，然后对哈希值进行签名操作再得到数字签名，然后将原消息和利用哈希值得到的数字签名发送给B，同样的，B利用收到的消息计算哈希值，并利用公钥对收到的数字签名进行解密操作得到另一个哈希值，如果这两个哈希值相同，那么说明整个过程没有出错，利用数字签名进行交换的过程也算结束了。</p>
-<p>数字签名技术提供了authentication，falsification detection和repudiation prevention功能，但是它本身依旧存在着一个问题，消息和数字签名的接收方B，会无条件地认为A一定是消息和数字签名的发送方，但是事实上，很可能存在恶意第三方X伪装成A进行数据交换，存在这个问题的根本原因就在于数字签名和公钥加密都使用了一个公钥和一个私钥，我们并不能确定这个公钥到底属于谁，因为公钥中并没有包含它的归属方的信息，所以B使用的公钥很可能并不来自A，而是来自恶意第三方X的公钥，这个问题我们可以用“数字证书”这一技术来解决。</p>
-<h2 id="数字证书"><a href="#数字证书" class="headerlink" title="数字证书"></a>数字证书</h2><p>公钥加密体系和数字签名存在的共同的问题就是无法确定公钥的归属者，所以，当A需要将自己的公钥发送给B时，恶意第三方X可以在不让A和B发现的情况下将A的公钥替换为自己的公钥。数字证书就是为了解决无法确定公钥归属者这一问题而出现的解决方案。下面我们来了解一下数字证书是如何工作的，假设组织A拥有一对公私钥，分别记为PA和SA，并且决定将PA发送给组织B。组织A需要向CA(certification authority)发起请求，让CA颁布一个证明公钥PA属于组织A的证书。那什么是CA呢，CA就是用于管理数字证书的一个组织，一般来说，任何人都可以称为CA，但是最好还是相信由政府或者大型公司这个信用度高的组织担任的CA。同样的，每个CA自身也拥有一对公私钥，组织A向CA提供自己的个人信息，例如公钥PA，电子邮箱等等。当CA收到由组织A提供的信息时，CA利用自己私钥对组织A提供的数据进行签名，得到数字签名，然后生成的数字签名和A提供的消息一起生成一个文件来发送给A，这个文件就变成了A的数字证书。</p>
-<p>从现在开始，A就不向B直接发送自己的公钥PA了，取而代之的，A向B发送来自CA生成的数字证书，在那之后，B向CA索取它的公钥，并利用CA的公钥验证A发送的数字证书的真实性。数字证书中的数字签名仅仅可以用产生该数字证书的CA的公钥来验证，换句话说，如果验证不出问题，那就可以说明该数字证书确实是由该CA颁布的，然后就可以提取出数字证书中A的公钥PA了，经过这个过程，组织A向组织B传输公钥的过程就算完成了。</p>
-<p>让我们看看这种公钥传递方式是否存在问题，假设一个冒充A的恶意第三方X试图传递自己的公钥。但是，B没有理由相信一个没有作为数字证书发送的公钥。那么当X冒充A在认证机构注册公钥时会发生什么？在这种情况下，X无法访问A的电子邮件账户，因此X无法获得发行证书。X只能创建使用X的电子邮件地址的证书。因此，他们无法获得属于A的证书。通过使用数字证书系统，可以验证公钥的所有者。早些时候我们说B收到了证书颁发机构的公钥，但是现在存在一个问题，B收到的公钥（PC）是否真的是由认证机构创建的？因为没有办法确认是谁自己创建了公钥，它可能是由X伪装为认证机构创建的。换句话说，我们在公钥加密中发现的同样的问题也出现在这里。实际上，认证机构的这个公钥（PC）也作为数字证书被交付，并且“签名”认证机构的数字证书的一方是更高等级的认证机构。认证机构形成了一个树形结构，高级权威机构为较低级别的机构创建数字签名。</p>
-<p>为了了解这个认证机构的树状结构是如何运作的，比方说，我们有一个社会广泛信任的认证机构Y，即使新公司G想要作为认证机构开始服务，它在社会上也是没有信誉的。因此，G公司需要拥有Y公司颁发的数字证书。当然，Y公司会检查以确保G公司能够充分履行认证机构的职责。在这之后，G公司就可以宣称自己是一家赢得Y公司信任的公司。通过这样做，更大的组织可以确保小型组织的信任，形成有组织的树状结构。那么，谁在认证机构树的顶部？最高级别的证书颁发机构被称为“根证书颁发机构（root CA）”，并且自己证明其自身的有效性。另外，如果根证书颁发机构本身不是一个值得信赖的组织，它颁发的证书也不会被使用。因此，其中现在相当一部分CA是已经具有社会公信力的组织，如大公司和政府机构。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/22/heap/index.html b/2018/04/22/heap/index.html
deleted file mode 100644
index c03061b..0000000
--- a/2018/04/22/heap/index.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>heap | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Src code from https://golang.org/src/container/heap/heap.go HeapPackage heap provides heap operations for any type that implements heap.Interface. A heap is a tree with the property that each node is">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="heap">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/22/heap/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Src code from https://golang.org/src/container/heap/heap.go HeapPackage heap provides heap operations for any type that implements heap.Interface. A heap is a tree with the property that each node is">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://algs4.cs.princeton.edu/24pq/images/heap-ops.png">
-<meta property="og:updated_time" content="2018-06-26T08:46:10.620Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="heap">
-<meta name="twitter:description" content="Src code from https://golang.org/src/container/heap/heap.go HeapPackage heap provides heap operations for any type that implements heap.Interface. A heap is a tree with the property that each node is">
-<meta name="twitter:image" content="https://algs4.cs.princeton.edu/24pq/images/heap-ops.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-heap"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      heap
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-22T09:44:48.000Z" itemprop="datePublished">
-        Apr 22, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>Src code from <a href="https://golang.org/src/container/heap/heap.go" target="_blank" rel="noopener">https://golang.org/src/container/heap/heap.go</a></p>
-<h1 id="Heap"><a href="#Heap" class="headerlink" title="Heap"></a>Heap</h1><p>Package heap provides heap operations for any type that implements heap.Interface. A heap is a tree with the property that each node is the minimum-valued node in its subtree.</p>
-<p>The minimum element in the tree is the root, at index 0.</p>
-<p>A heap is a common way to implement a priority queue. To build a priority queue, implement the Heap interface with the (negative) priority as the ordering for the Less method, so Push adds items while Pop removes the highest-priority item from the queue. </p>
-<p><img src="https://algs4.cs.princeton.edu/24pq/images/heap-ops.png" alt="heap-ops"></p>
-<h2 id="Interface"><a href="#Interface" class="headerlink" title="Interface"></a>Interface</h2><p>Any type that implements heap.Interface may be used as a min-heap with the following invariants (established after Init has been called or if the data is empty or sorted):</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">!h.Less(j, i) </span><br><span class="line">for 0 &lt;= i &lt; h.Len() and 2*i+1 &lt;= j &lt;= 2*i+2 and j &lt; h.Len()</span><br></pre></td></tr></table></figure>
-<p>Note that Push and Pop in this interface are for package heap’s implementation to call. To add and remove things from the heap, use heap.Push and heap.Pop.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Interface <span class="keyword">interface</span> &#123;</span><br><span class="line">    sort.Interface</span><br><span class="line">    Push(h Interface, x <span class="keyword">interface</span>&#123;&#125;) <span class="comment">// add x as element Len()</span></span><br><span class="line">    Pop(h Interface) <span class="keyword">interface</span>&#123;&#125; <span class="comment">// remove and return element Len() - 1.</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Init-Heap"><a href="#Init-Heap" class="headerlink" title="Init Heap"></a>Init Heap</h2><p>A heap must be initialized before any of the heap operations can be used. Init is idempotent with respect to the heap invariants and may be called whenever the heap invariants may have been invalidated. Its complexity is O(n) where n = h.Len().</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Init</span><span class="params">(h Interface)</span></span> &#123;</span><br><span class="line">    <span class="comment">// heapify</span></span><br><span class="line">    n := h.Len()</span><br><span class="line">    <span class="keyword">for</span> i := n/<span class="number">2</span> <span class="number">-1</span>; i &gt;= <span class="number">0</span>; i-- &#123;</span><br><span class="line">        down(h, i, n)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Swim-up"><a href="#Swim-up" class="headerlink" title="Swim up"></a>Swim up</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">up</span><span class="params">(h Interface, j <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        i := (j - <span class="number">1</span>) / <span class="number">2</span></span><br><span class="line">        <span class="keyword">if</span> i == j || !h.Less(j, i) &#123;</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">        h.Swap(i, j)</span><br><span class="line">        j = i</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Sink-down"><a href="#Sink-down" class="headerlink" title="Sink down"></a>Sink down</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">down</span><span class="params">(h Interface, i0, n <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    i := i0</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        j1 := <span class="number">2</span>*i + <span class="number">1</span></span><br><span class="line">        <span class="keyword">if</span> j1 &gt;= n || j1 &lt; <span class="number">0</span> &#123;</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">        j := j1</span><br><span class="line">        <span class="keyword">if</span> j2 := j1 + <span class="number">1</span>; j2 &lt; n &amp;&amp; h.Less(j2, j1) &#123;</span><br><span class="line">            j = j2</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> !h.Less(j, i) &#123;</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">         h.Swap(i, j)</span><br><span class="line">         i = j</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> i &gt; i0</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="push"><a href="#push" class="headerlink" title="push"></a>push</h2><p>Push pushes the element x onto the heap. The complexity is O(log(n)) where n = h.Len().</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Push</span><span class="params">(h Interface, x <span class="keyword">interface</span>&#123;&#125;)</span></span> &#123;</span><br><span class="line">    h.Push(x)</span><br><span class="line">    up(h, h.Len()<span class="number">-1</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="pop"><a href="#pop" class="headerlink" title="pop"></a>pop</h2><p>Pop removes the minimum element (according to Less) from the heap and returns it. The complexity is O(log(n)) where n = h.Len(). It is equivalent to Remove(h, 0).</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Pop</span><span class="params">(h Interface)</span> <span class="title">interface</span></span>&#123;&#125; &#123;</span><br><span class="line">    n := h.Len()<span class="number">-1</span></span><br><span class="line">    h.Swap(<span class="number">0</span>, n)</span><br><span class="line">    down(h, <span class="number">0</span>, n)</span><br><span class="line">    <span class="keyword">return</span> h.Pop()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Fix"><a href="#Fix" class="headerlink" title="Fix"></a>Fix</h2><p>Fix re-establishes the heap ordering after the element at index i has changed its value. Changing the value of the element at index i and then calling Fix is equivalent to, but less expensive than, calling Remove(h, i) followed by a Push of the new value. The complexity is O(log(n)) where n = h.Len().</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Fix</span><span class="params">(h Interface, i <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> !down(h, i, h.Len()) &#123;</span><br><span class="line">        up(h, i)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Remove"><a href="#Remove" class="headerlink" title="Remove"></a>Remove</h2><p>Remove removes the element at index i from the heap. The complexity is O(log(n)) where n = h.Len().</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Remove</span><span class="params">(h Interface, i <span class="keyword">int</span>)</span> <span class="title">interface</span></span>&#123;&#125; &#123;</span><br><span class="line">    n := h.Len()<span class="number">-1</span></span><br><span class="line">    <span class="keyword">if</span> n != i &#123;</span><br><span class="line">        h.Swap(i, n)</span><br><span class="line">        <span class="keyword">if</span> !down(h, i, n) &#123;</span><br><span class="line">            up(h, i)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> n.Pop()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Priority-Queue"><a href="#Priority-Queue" class="headerlink" title="Priority Queue"></a>Priority Queue</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"container/heap"</span></span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// An Item is something we manage in a priority queue.</span></span><br><span class="line"><span class="keyword">type</span> Item <span class="keyword">struct</span> &#123;</span><br><span class="line">    value    <span class="keyword">string</span> <span class="comment">// The value of the item; arbitrary.</span></span><br><span class="line">    priority <span class="keyword">int</span>    <span class="comment">// The priority of the item in the queue.</span></span><br><span class="line">    <span class="comment">// The index is needed by update and is maintained by the heap.Interface methods.</span></span><br><span class="line">    index <span class="keyword">int</span> <span class="comment">// The index of the item in the heap.</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// A PriorityQueue implements heap.Interface and holds Items.</span></span><br><span class="line"><span class="keyword">type</span> PriorityQueue []*Item</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(pq PriorityQueue)</span> <span class="title">Len</span><span class="params">()</span> <span class="title">int</span></span> &#123; <span class="keyword">return</span> <span class="built_in">len</span>(pq) &#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(pq PriorityQueue)</span> <span class="title">Less</span><span class="params">(i, j <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    <span class="comment">// We want Pop to give us the highest, not lowest, priority so we use greater than here.</span></span><br><span class="line">    <span class="keyword">return</span> pq[i].priority &gt; pq[j].priority</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(pq PriorityQueue)</span> <span class="title">Swap</span><span class="params">(i, j <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    pq[i], pq[j] = pq[j], pq[i]</span><br><span class="line">    pq[i].index = i</span><br><span class="line">    pq[j].index = j</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(pq *PriorityQueue)</span> <span class="title">Push</span><span class="params">(x <span class="keyword">interface</span>&#123;&#125;)</span></span> &#123;</span><br><span class="line">    n := <span class="built_in">len</span>(*pq)</span><br><span class="line">    item := x.(*Item)</span><br><span class="line">    item.index = n</span><br><span class="line">    *pq = <span class="built_in">append</span>(*pq, item)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(pq *PriorityQueue)</span> <span class="title">Pop</span><span class="params">()</span> <span class="title">interface</span></span>&#123;&#125; &#123;</span><br><span class="line">    old := *pq</span><br><span class="line">    n := <span class="built_in">len</span>(old)</span><br><span class="line">    item := old[n<span class="number">-1</span>]</span><br><span class="line">    item.index = <span class="number">-1</span> <span class="comment">// for safety</span></span><br><span class="line">    *pq = old[<span class="number">0</span> : n<span class="number">-1</span>]</span><br><span class="line">    <span class="keyword">return</span> item</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// update modifies the priority and value of an Item in the queue.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(pq *PriorityQueue)</span> <span class="title">update</span><span class="params">(item *Item, value <span class="keyword">string</span>, priority <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    item.value = value</span><br><span class="line">    item.priority = priority</span><br><span class="line">    heap.Fix(pq, item.index)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// This example creates a PriorityQueue with some items, adds and manipulates an item,</span></span><br><span class="line"><span class="comment">// and then removes the items in priority order.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="comment">// Some items and their priorities.</span></span><br><span class="line">    items := <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span>&#123;</span><br><span class="line">        <span class="string">"banana"</span>: <span class="number">3</span>, <span class="string">"apple"</span>: <span class="number">2</span>, <span class="string">"pear"</span>: <span class="number">4</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Create a priority queue, put the items in it, and</span></span><br><span class="line">    <span class="comment">// establish the priority queue (heap) invariants.</span></span><br><span class="line">    pq := <span class="built_in">make</span>(PriorityQueue, <span class="built_in">len</span>(items))</span><br><span class="line">    i := <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> value, priority := <span class="keyword">range</span> items &#123;</span><br><span class="line">        pq[i] = &amp;Item&#123;</span><br><span class="line">            value:    value,</span><br><span class="line">            priority: priority,</span><br><span class="line">            index:    i,</span><br><span class="line">        &#125;</span><br><span class="line">        i++</span><br><span class="line">    &#125;</span><br><span class="line">	heap.Init(&amp;pq)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Insert a new item and then modify its priority.</span></span><br><span class="line">    item := &amp;Item&#123;</span><br><span class="line">        value:    <span class="string">"orange"</span>,</span><br><span class="line">        priority: <span class="number">1</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    heap.Push(&amp;pq, item)</span><br><span class="line">    pq.update(item, item.value, <span class="number">5</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Take the items out; they arrive in decreasing priority order.</span></span><br><span class="line">    <span class="keyword">for</span> pq.Len() &gt; <span class="number">0</span> &#123;</span><br><span class="line">        item := heap.Pop(&amp;pq).(*Item)</span><br><span class="line">        fmt.Printf(<span class="string">"%.2d:%s "</span>, item.priority, item.value)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/23/RSS/index.html b/2018/04/23/RSS/index.html
deleted file mode 100644
index 05af0ce..0000000
--- a/2018/04/23/RSS/index.html
+++ /dev/null
@@ -1,246 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>RSS | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="fetcher12345678910111213141516171819202122232425262728type Item struct &amp;#123;    Title, Channel, GUID string&amp;#125;type Fetcher interface &amp;#123;    Fetch() (items []Item, next time.Time, err error)&amp;#12">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="RSS">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/23/RSS/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="fetcher12345678910111213141516171819202122232425262728type Item struct &amp;#123;    Title, Channel, GUID string&amp;#125;type Fetcher interface &amp;#123;    Fetch() (items []Item, next time.Time, err error)&amp;#12">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:09.380Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="RSS">
-<meta name="twitter:description" content="fetcher12345678910111213141516171819202122232425262728type Item struct &amp;#123;    Title, Channel, GUID string&amp;#125;type Fetcher interface &amp;#123;    Fetch() (items []Item, next time.Time, err error)&amp;#12">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-RSS"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      RSS
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-23T13:50:37.000Z" itemprop="datePublished">
-        Apr 23, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <h2 id="fetcher"><a href="#fetcher" class="headerlink" title="fetcher"></a>fetcher</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Item <span class="keyword">struct</span> &#123;</span><br><span class="line">    Title, Channel, GUID <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Fetcher <span class="keyword">interface</span> &#123;</span><br><span class="line">    Fetch() (items []Item, next time.Time, err error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Fetch</span><span class="params">(domain <span class="keyword">string</span>)</span> <span class="title">Fetcher</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;rssFetcher&#123;channel: domain&#125;</span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> rssFetcher <span class="keyword">struct</span> &#123;</span><br><span class="line">    channel <span class="keyword">string</span></span><br><span class="line">    items   []Item</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *rssFetcher)</span> <span class="title">Fetch</span><span class="params">()</span> <span class="params">(items []Item, next time.Time, err error)</span></span> &#123;</span><br><span class="line">    now := time.Now()</span><br><span class="line">    next = now.Add(time.Duration(rand.Intn(<span class="number">5</span>)) * <span class="number">500</span> * time.Millisecond)</span><br><span class="line">	  item := Item&#123;</span><br><span class="line">        Channel: f.channel,</span><br><span class="line">        Title:   fmt.Sprintf(<span class="string">"Item %d"</span>, <span class="built_in">len</span>(f.items)),</span><br><span class="line">    &#125;</span><br><span class="line">    item.GUID = item.Channel + <span class="string">"/"</span> + item.Title</span><br><span class="line">    f.items = <span class="built_in">append</span>(f.items, item)</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="subscription"><a href="#subscription" class="headerlink" title="subscription"></a>subscription</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Subscription <span class="keyword">interface</span> &#123;</span><br><span class="line">    Updates() &lt;-<span class="keyword">chan</span> Item <span class="comment">// stream of Items</span></span><br><span class="line">    Close() error         <span class="comment">// close the stream</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Subscribe</span><span class="params">(fetcher Fetcher)</span> <span class="title">Subscription</span></span> &#123;</span><br><span class="line">    s := &amp;sub&#123;</span><br><span class="line">        fetcher: fetcher,</span><br><span class="line">        updates: <span class="built_in">make</span>(<span class="keyword">chan</span> Item),</span><br><span class="line">        closing: <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">chan</span> error),</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">go</span> s.loop()</span><br><span class="line">    <span class="keyword">return</span> s</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> sub <span class="keyword">struct</span> &#123;</span><br><span class="line">    fetcher Fetcher</span><br><span class="line">    updates <span class="keyword">chan</span> Item</span><br><span class="line">    closing <span class="keyword">chan</span> <span class="keyword">chan</span> error</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *sub)</span> <span class="title">Updates</span><span class="params">()</span> &lt;-<span class="title">chan</span> <span class="title">Item</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> s.updates</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *sub)</span> <span class="title">Close</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    errc := <span class="built_in">make</span>(<span class="keyword">chan</span> error)</span><br><span class="line">    s.closing &lt;- errc</span><br><span class="line">    <span class="keyword">return</span> &lt;-errc</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *sub)</span> <span class="title">loop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">const</span> maxPending = <span class="number">10</span></span><br><span class="line">    <span class="keyword">type</span> fetchResult <span class="keyword">struct</span> &#123;</span><br><span class="line">        fetched []Item</span><br><span class="line">        next    time.Time</span><br><span class="line">        err     error</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> fetchDone <span class="keyword">chan</span> fetchResult</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> pending []Item</span><br><span class="line">    <span class="keyword">var</span> next time.Time</span><br><span class="line">    <span class="keyword">var</span> err error</span><br><span class="line">    <span class="keyword">var</span> seen = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">bool</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> fetchDeplay time.Duration</span><br><span class="line">        <span class="keyword">if</span> now := time.Now(); next.After(now) &#123;</span><br><span class="line">            fetchDelay = next.Sub(now)</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">var</span> startFetch &lt;-<span class="keyword">chan</span> time.Time</span><br><span class="line">        <span class="keyword">if</span> fetchDone == <span class="literal">nil</span> &amp;&amp; <span class="built_in">len</span>(pending) &lt; maxPending &#123;</span><br><span class="line">            startFetch = time.After(fetchDelay)</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">var</span> first Item</span><br><span class="line">        <span class="keyword">var</span> updates <span class="keyword">chan</span> Item</span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(pending) &gt; <span class="number">0</span> &#123;</span><br><span class="line">            first = pending[<span class="number">0</span>]</span><br><span class="line">            updates = s.updates</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> errc := &lt;-s.closing:</span><br><span class="line">            errc &lt;- err</span><br><span class="line">            <span class="built_in">close</span>(s.updates)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        <span class="keyword">case</span> &lt;-startFetch:</span><br><span class="line">            fetchDone = <span class="built_in">make</span>(<span class="keyword">chan</span> fetchResult, <span class="number">1</span>)</span><br><span class="line">            <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">                fetched, next, err := s.fetcher.Fetch()</span><br><span class="line">                fetchDone &lt;- fetchResult&#123;fetched, next, err&#125;</span><br><span class="line">            &#125;()</span><br><span class="line">        <span class="keyword">case</span> result := &lt;-fetchDone:</span><br><span class="line">            fetchDone = <span class="literal">nil</span></span><br><span class="line">            fetched := result.fetched</span><br><span class="line">            next, err = result.next, result.err</span><br><span class="line">            <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">                next = time.Now().Add(<span class="number">10</span> * time.second)</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">for</span> _, item := <span class="keyword">range</span> fetched &#123;</span><br><span class="line">                <span class="keyword">if</span> !seen[item.GUID] &#123;</span><br><span class="line">                    pending = <span class="built_in">append</span>(pending, item)</span><br><span class="line">                    seen[item.GUID] = <span class="literal">true</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        <span class="keyword">case</span> updates &lt;- first:</span><br><span class="line">            pending = pending[<span class="number">1</span>:]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="merge"><a href="#merge" class="headerlink" title="merge"></a>merge</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> merge <span class="keyword">struct</span> &#123;</span><br><span class="line">    subs    []Subscription</span><br><span class="line">    updates <span class="keyword">chan</span> Item</span><br><span class="line">    quit    <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    errs    <span class="keyword">chan</span> error</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Merge</span><span class="params">(subs ...Subscription)</span> <span class="title">Subscription</span></span> &#123;</span><br><span class="line">    m := &amp;merge&#123;</span><br><span class="line">        subs:    subs,</span><br><span class="line">        updates: <span class="built_in">make</span>(<span class="keyword">chan</span> Item),</span><br><span class="line">        quit:    <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;),</span><br><span class="line">        errs:    <span class="built_in">make</span>(<span class="keyword">chan</span> error),</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> _, sub := <span class="keyword">range</span> subs &#123;</span><br><span class="line">        <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(s Subscription)</span></span> &#123;</span><br><span class="line">            <span class="keyword">for</span> &#123;</span><br><span class="line">                <span class="keyword">var</span> it Item</span><br><span class="line">                <span class="keyword">select</span> &#123;</span><br><span class="line">                <span class="keyword">case</span> it = &lt;-s.Updates():</span><br><span class="line">                <span class="keyword">case</span> &lt;-m.quit:</span><br><span class="line">                    m.errs &lt;- s.Close()</span><br><span class="line">                    <span class="keyword">return</span></span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">select</span> &#123;</span><br><span class="line">                <span class="keyword">case</span> m.updates &lt;- it:</span><br><span class="line">                <span class="keyword">case</span> &lt;-m.quit:</span><br><span class="line">                    m.errs &lt;- s.Close()</span><br><span class="line">                    <span class="keyword">return</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;(sub)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> m</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *merge)</span> <span class="title">Updates</span><span class="params">()</span> &lt;-<span class="title">chan</span> <span class="title">Item</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> m.updates</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *merge)</span> <span class="title">Close</span><span class="params">()</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line">    <span class="built_in">close</span>(m.quit)</span><br><span class="line">    <span class="keyword">for</span> _ = <span class="keyword">range</span> m.subs &#123;</span><br><span class="line">        <span class="keyword">if</span> e := &lt;-m.errs; e != <span class="literal">nil</span> &#123;</span><br><span class="line">            err = e</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">close</span>(m.updates)</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    merged := Merge(</span><br><span class="line">        Subscribe(Fetch(<span class="string">"blog.goland.org"</span>)),</span><br><span class="line">        Subscribe(Fetch(<span class="string">"gooog.blogspot.com"</span>)),</span><br><span class="line">        Subscribe(Fetch(<span class="string">"gers.blogspot.com"</span>)))</span><br><span class="line"></span><br><span class="line">    time.AfterFunc(<span class="number">3</span>*time.Second, <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        fmt.Println(<span class="string">"Merged subsription closed. Errors: "</span>, merged.Close())</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">for</span> it := <span class="keyword">range</span> merged.Updates() &#123;</span><br><span class="line">        fmt.Println(it.Channel, it.Title)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/24/PKCS7_Padding/index.html b/2018/04/24/PKCS7_Padding/index.html
deleted file mode 100644
index 0722bd9..0000000
--- a/2018/04/24/PKCS7_Padding/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>PKCS7 Padding | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="由于某些特定加密算法的要求，例如AES中的CBC，要求被加密的数据是特定块大小的整数倍，例如在AES中一个块大小即BlockSize的大小为16字节，故被加密数据的长度 len(src) % BlockSize == 0 ，但现实生活中要求加密的数据长度往往是随机的，所以需要有一种可靠高效的数据填充方法（padding）。 现在我们的问题是这样的，一个不定长度的数据作为加密的输入，我们需要把它填充">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="PKCS7 Padding">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/24/PKCS7_Padding/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="由于某些特定加密算法的要求，例如AES中的CBC，要求被加密的数据是特定块大小的整数倍，例如在AES中一个块大小即BlockSize的大小为16字节，故被加密数据的长度 len(src) % BlockSize == 0 ，但现实生活中要求加密的数据长度往往是随机的，所以需要有一种可靠高效的数据填充方法（padding）。 现在我们的问题是这样的，一个不定长度的数据作为加密的输入，我们需要把它填充">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:28.048Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="PKCS7 Padding">
-<meta name="twitter:description" content="由于某些特定加密算法的要求，例如AES中的CBC，要求被加密的数据是特定块大小的整数倍，例如在AES中一个块大小即BlockSize的大小为16字节，故被加密数据的长度 len(src) % BlockSize == 0 ，但现实生活中要求加密的数据长度往往是随机的，所以需要有一种可靠高效的数据填充方法（padding）。 现在我们的问题是这样的，一个不定长度的数据作为加密的输入，我们需要把它填充">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-PKCS7_Padding"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      PKCS7 Padding
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-24T08:26:24.000Z" itemprop="datePublished">
-        Apr 24, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>由于某些特定加密算法的要求，例如AES中的CBC，要求被加密的数据是特定块大小的整数倍，例如在AES中一个块大小即BlockSize的大小为16字节，故被加密数据的长度 <code>len(src) % BlockSize == 0</code> ，但现实生活中要求加密的数据长度往往是随机的，所以需要有一种可靠高效的数据填充方法（padding）。</p>
-<p>现在我们的问题是这样的，一个不定长度的数据作为加密的输入，我们需要把它填充到固定的长度，即满足 <code>len(src) % BlockSize == 0</code> 的条件，并且在解密时可以获得原来的数据。</p>
-<p>现在的前提是BlockSize为16字节，输入长度随机。流程大致经过下面几步，填充=&gt;加密=&gt;网络传输=&gt;解密=&gt;去填充。问题的难点就是如何保证去填充之后可以获取原来填充之前的数据。</p>
-<p>我们的初始数据即待加密数据的格式如下</p>
-<p>|XX16bytesXX|XX16bytesXX|…….|XX16bytesXX|XX?bytesXX|</p>
-<p>填充后得到的数据格式为如下。</p>
-<p>|XX16bytesXX|XX16bytesXX|…….|XX16bytesXX|XX16bytesXX|</p>
-<p>这里我们使用 |XX16bytesXX| 表示一段16字节的随机数据。也就是说我们需要把最后的?bytes填充到固定长度的16bytes，这里？的取值范围是0到15。现在我们就来引入PKCS7这种填充标准。</p>
-<p>PKCS7填充的做法是这样的，首先它会确定需要被填充的字节的长度，也就是上述所说的?bytes的那一段字节。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">padding := aes.BlockSize - <span class="built_in">len</span>(src)%aes.BlockSize</span><br></pre></td></tr></table></figure>
-<p>上面的代码段非常好理解，首先对待加密的数据长度对BlockSize取模，获得我们的?bytes，再利用它与BlockSize的差值获得我们需要填充的长度值，这里的padding就是一个int值。</p>
-<p>下面就是真正填充的一个逻辑了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">padtext := bytes.Repeat([]<span class="keyword">byte</span>&#123;<span class="keyword">byte</span>(padding)&#125;, padding)</span><br></pre></td></tr></table></figure>
-<p>这一行代码乍看起来有点复杂，我们一步一步来看，它要做的一件事情就是获得一个用于填充的文字，而这个文字就是利用我们上述获得的padding（注意它是一个int）转化成一个byte后重复padding次。</p>
-<p>也就是说假设我们的padding是7，也就是需要填充7字节的信息，那我们的padtext也就是我们填充的文字就是 7 7 7 7 7 7 7，当然我们这里的每个7都是一个byte。</p>
-<p>以此类推，同理我们padtext里面的每一个数字就是一个byte，6 6 6 6 6 6 应该理解成byte(6) byte(6) byte(6) byte(6) byte(6) byte(6)。</p>
-<p>获得了我们的填充信息后，我们将原数据与我们的填充信息相连接就行了，下面就是我们完整填充过程的函数，非常简单。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">PKCS7Padding</span><span class="params">(src []<span class="keyword">byte</span>)</span> []<span class="title">byte</span></span> &#123;</span><br><span class="line">    padding := aes.BlockSize - <span class="built_in">len</span>(src)%aes.BlockSize</span><br><span class="line">    padtext := bytes.Repeat([]<span class="keyword">byte</span>&#123;<span class="keyword">byte</span>(padding)&#125;, padding)</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">append</span>(src, padtext...)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>理解了PKCS7中填充的标准之后，我们再来看一下如何去填充，去填充的过程也非常简单，但是在工程代码中实现还需要考虑一些特殊的边界情况。</p>
-<p>下面直接给出去填充的代码。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">PKCS7Unpadding</span><span class="params">(src []<span class="keyword">byte</span>)</span> <span class="params">([]<span class="keyword">byte</span>, error)</span></span> &#123;</span><br><span class="line">    length := <span class="built_in">len</span>(src)</span><br><span class="line">    unpadding := <span class="keyword">int</span>(src[length - <span class="number">1</span>])</span><br><span class="line">	</span><br><span class="line">    <span class="keyword">if</span> unpadding &gt; aes.BlockSize || unpadding == <span class="number">0</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span>, fmt.Errorf(<span class="string">"invalid unpadding"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">	  </span><br><span class="line">    pad := src[<span class="built_in">len</span>(src)-unpadding:]</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; unpadding; i++ &#123;</span><br><span class="line">        <span class="keyword">if</span> pad[i] != <span class="keyword">byte</span>(unpadding) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, fmt.Errorf(<span class="string">"invalid padding"</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> src[:(<span class="built_in">len</span>(src)-unpadding)], <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>这里我们需要去填充的为src，讲src的最后一个byte取出再转换为int，这个数值就是我们之前填充字节的个数，记为unpadding，如果unpadding的值大于BlockSize或者出现unpadding为0的情况，这种情况是一场的因为我们填充的时候就将padding值约束在[1, BlockSize-1)，所以出现不符合要求的padding值都将返回异常。</p>
-<p>然后将数组末尾取出unpadding个字节，将unpadding个字节分别与byte(unpadding)这个字节进行比较，如果不想等，则返回异常。</p>
-<p>最后如果一切都没有问题，则返回去除padding个字节后的byte数组。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/25/FSM/index.html b/2018/04/25/FSM/index.html
deleted file mode 100644
index b5a91f2..0000000
--- a/2018/04/25/FSM/index.html
+++ /dev/null
@@ -1,276 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Finite State Machine | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在实际工程代码当中，常常会用到有限状态机(Finite-state Machine. FSM)，例如在p2p网络中一个节点可能拥有多种状态，有限状态机可以用于表示有限个状态及所有可能的状态之间转移的情况。利用有限状态机就可以轻松地解决节点在不同状态之间转移的情况。这种编程模型可以避免丑陋的switch语句。 以门的开启和关闭举例，一扇门拥有两种状态（state），open和closed，我们将门关">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Finite State Machine">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/25/FSM/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在实际工程代码当中，常常会用到有限状态机(Finite-state Machine. FSM)，例如在p2p网络中一个节点可能拥有多种状态，有限状态机可以用于表示有限个状态及所有可能的状态之间转移的情况。利用有限状态机就可以轻松地解决节点在不同状态之间转移的情况。这种编程模型可以避免丑陋的switch语句。 以门的开启和关闭举例，一扇门拥有两种状态（state），open和closed，我们将门关">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:40.495Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Finite State Machine">
-<meta name="twitter:description" content="在实际工程代码当中，常常会用到有限状态机(Finite-state Machine. FSM)，例如在p2p网络中一个节点可能拥有多种状态，有限状态机可以用于表示有限个状态及所有可能的状态之间转移的情况。利用有限状态机就可以轻松地解决节点在不同状态之间转移的情况。这种编程模型可以避免丑陋的switch语句。 以门的开启和关闭举例，一扇门拥有两种状态（state），open和closed，我们将门关">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-FSM"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Finite State Machine
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-25T01:58:24.000Z" itemprop="datePublished">
-        Apr 25, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在实际工程代码当中，常常会用到有限状态机(Finite-state Machine. FSM)，例如在p2p网络中一个节点可能拥有多种状态，有限状态机可以用于表示有限个状态及所有可能的状态之间转移的情况。利用有限状态机就可以轻松地解决节点在不同状态之间转移的情况。这种编程模型可以避免丑陋的switch语句。</p>
-<p>以门的开启和关闭举例，一扇门拥有两种状态（state），open和closed，我们将门关上，那它的状态就由open转移到closed，这里我们将open称为初始状态，将closed称为目标状态，分别用src和dst表示。而导致状态转移的动作我们称它为事件（event），状态的转移都是由特定事件触发的。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> EventDesc <span class="keyword">struct</span> &#123;</span><br><span class="line">    Name <span class="keyword">string</span> </span><br><span class="line">    Src []<span class="keyword">string</span> </span><br><span class="line">    Dst <span class="keyword">string</span>  </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Events []EventDesc</span><br></pre></td></tr></table></figure>
-<p>这里Name表示触发状态转移的事件名称，Src是状态转移过程中的初始状态，注意到它是一个数组，因为可以有多个不同的初始状态转移到同一个目标状态，而Dst是状态转移过程中的目标状态。上面的结构体就代表了有限状态机中触发状态转移的事件，可以把它理解成一个导火索，有了它，有限状态机才在不同的状态之间跳跃。</p>
-<p>下面我们再来定义有限状态机的结构体，一个有限状态机需要哪些信息呢，首先，肯定需要一个值来标定它现在处于什么状态，也就是有限个状态中它处于哪个阶段，还需要一个东西来表示各个状态之间如何转移，如在事件E发生的情况下状态A转移到状态B。还需要一个回调方法集合（callbacks），它可以用于在状态转移发生时需要分别调用什么方法。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> eKey <span class="keyword">struct</span> &#123;</span><br><span class="line">    event <span class="keyword">string</span></span><br><span class="line">    src <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> cKey <span class="keyword">struct</span> &#123;</span><br><span class="line">    target <span class="keyword">string</span></span><br><span class="line">    callbackType <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> FSM <span class="keyword">struct</span> &#123;</span><br><span class="line">    current <span class="keyword">string</span></span><br><span class="line">    transitions <span class="keyword">map</span>[eKey]<span class="keyword">string</span></span><br><span class="line">    callbacks <span class="keyword">map</span>[cKey]<span class="keyword">string</span></span><br><span class="line">    transition <span class="function"><span class="keyword">func</span><span class="params">()</span></span></span><br><span class="line"><span class="function">&#125;</span></span><br></pre></td></tr></table></figure>
-<p>还是拿开门关门举例子，当门刚开始的状态是open，那么current=open，我们用手关门，就会查看transitions这个map中open和关门这个动作所对应的目标状态是什么，发现是closed，然后在状态转移的过程中还会调用注册过的callback方法。以上就是基本的实现一个FSM的思路。</p>
-<p>下面我们来讨论一下回调方法（callback）的种类。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    callbackNone <span class="keyword">int</span> = <span class="literal">iota</span></span><br><span class="line">    callbackBeforeEvent</span><br><span class="line">    callbackLeaveState</span><br><span class="line">    callbackEnterState</span><br><span class="line">    callbackAfterState</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
-<p>触发一次状态的导火索是一个特定的事件Event，我们记为E，因为E的发生，状态A变成状态B，所以我们一共可以定义四种回调方法，分别是在事件发生之前和之后，也就是callbackBeforeEvent，callbackAfterEvent，还有就是离开初始状态和进入目标状态的回调函数，callbackLeaveState和callbackEnterState。</p>
-<p>而一个callback其实就是一个回调函数 <code>type Callback func(*Event)</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewFSM</span><span class="params">(initial <span class="keyword">string</span>, events []EventDesc, callbacks <span class="keyword">map</span>[<span class="keyword">string</span>]Callback)</span> *<span class="title">FSM</span></span> &#123;</span><br><span class="line">	<span class="keyword">var</span> f FSM</span><br><span class="line">	f.current = initial</span><br><span class="line">	f.transitions = <span class="built_in">make</span>(<span class="keyword">map</span>[eKey]<span class="keyword">string</span>)</span><br><span class="line">	f.callbacks = <span class="built_in">make</span>(<span class="keyword">map</span>[cKey]Callback)</span><br><span class="line"></span><br><span class="line">	<span class="comment">// Build transition map and store sets of all events and states.</span></span><br><span class="line">	allEvents := <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">bool</span>)</span><br><span class="line">	allStates := <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">bool</span>)</span><br><span class="line">	<span class="keyword">for</span> _, e := <span class="keyword">range</span> events &#123;</span><br><span class="line">		<span class="keyword">for</span> _, src := <span class="keyword">range</span> e.Src &#123;</span><br><span class="line">			f.transitions[eKey&#123;e.Name, src&#125;] = e.Dst</span><br><span class="line">			allStates[src] = <span class="literal">true</span></span><br><span class="line">			allStates[e.Dst] = <span class="literal">true</span></span><br><span class="line">		&#125;</span><br><span class="line">		allEvents[e.Name] = <span class="literal">true</span></span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">// Map all callbacks to events/states.</span></span><br><span class="line">	<span class="keyword">for</span> name, c := <span class="keyword">range</span> callbacks &#123;</span><br><span class="line">		<span class="keyword">var</span> target <span class="keyword">string</span></span><br><span class="line">		<span class="keyword">var</span> callbackType <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line">		<span class="keyword">switch</span> &#123;</span><br><span class="line">		<span class="keyword">case</span> strings.HasPrefix(name, <span class="string">"before_"</span>):</span><br><span class="line">			target = strings.TrimPrefix(name, <span class="string">"before_"</span>)</span><br><span class="line">			<span class="keyword">if</span> target == <span class="string">"event"</span> &#123;</span><br><span class="line">				target = <span class="string">""</span></span><br><span class="line">				callbackType = callbackBeforeEvent</span><br><span class="line">			&#125; <span class="keyword">else</span> <span class="keyword">if</span> _, ok := allEvents[target]; ok &#123;</span><br><span class="line">				callbackType = callbackBeforeEvent</span><br><span class="line">			&#125;</span><br><span class="line">		<span class="keyword">case</span> strings.HasPrefix(name, <span class="string">"leave_"</span>):</span><br><span class="line">			target = strings.TrimPrefix(name, <span class="string">"leave_"</span>)</span><br><span class="line">			<span class="keyword">if</span> target == <span class="string">"state"</span> &#123;</span><br><span class="line">				target = <span class="string">""</span></span><br><span class="line">				callbackType = callbackLeaveState</span><br><span class="line">			&#125; <span class="keyword">else</span> <span class="keyword">if</span> _, ok := allStates[target]; ok &#123;</span><br><span class="line">				callbackType = callbackLeaveState</span><br><span class="line">			&#125;</span><br><span class="line">		<span class="keyword">case</span> strings.HasPrefix(name, <span class="string">"enter_"</span>):</span><br><span class="line">			target = strings.TrimPrefix(name, <span class="string">"enter_"</span>)</span><br><span class="line">			<span class="keyword">if</span> target == <span class="string">"state"</span> &#123;</span><br><span class="line">				target = <span class="string">""</span></span><br><span class="line">				callbackType = callbackEnterState</span><br><span class="line">			&#125; <span class="keyword">else</span> <span class="keyword">if</span> _, ok := allStates[target]; ok &#123;</span><br><span class="line">				callbackType = callbackEnterState</span><br><span class="line">			&#125;</span><br><span class="line">		<span class="keyword">case</span> strings.HasPrefix(name, <span class="string">"after_"</span>):</span><br><span class="line">			target = strings.TrimPrefix(name, <span class="string">"after_"</span>)</span><br><span class="line">			<span class="keyword">if</span> target == <span class="string">"event"</span> &#123;</span><br><span class="line">				target = <span class="string">""</span></span><br><span class="line">				callbackType = callbackAfterEvent</span><br><span class="line">			&#125; <span class="keyword">else</span> <span class="keyword">if</span> _, ok := allEvents[target]; ok &#123;</span><br><span class="line">				callbackType = callbackAfterEvent</span><br><span class="line">			&#125;</span><br><span class="line">		<span class="keyword">default</span>:</span><br><span class="line">			target = name</span><br><span class="line">			<span class="keyword">if</span> _, ok := allStates[target]; ok &#123;</span><br><span class="line">				callbackType = callbackEnterState</span><br><span class="line">			&#125; <span class="keyword">else</span> <span class="keyword">if</span> _, ok := allEvents[target]; ok &#123;</span><br><span class="line">				callbackType = callbackAfterEvent</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> callbackType != callbackNone &#123;</span><br><span class="line">			f.callbacks[cKey&#123;target, callbackType&#125;] = c</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> &amp;f</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<ol>
-<li>在new一个FSM的时候，我们先定义它的初始状态current，还有状态机中所有可能的状态迁移情况以及它的回调函数。</li>
-<li>这里我们建立所有可能的状态转移的情况。</li>
-<li>注册回调函数，也就是在事件发生前后，和改变状态的时候的回调函数。</li>
-</ol>
-<p>在初始化完一个FSM之后，也就是说规定了FSM该拥有的所有状态以及状态转移时候应该调用的函数之后，我们来看看如何让这个状态机动起来，我们之前已经知道，触发状态机变化的就是外部的特定的事件，所以我们需要灵活地去处理这些事件，来使得我们的状态机可以动起来。</p>
-<p>在上面我们定义了EventDesc这个结构体，注意到那个结构体是多对一的，也就是多个初始状态对应一个目标状态，我们现在定义一个真正的一对一的事件，这里的一对一指的是一个初始状态对应一个目标状态。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Event <span class="keyword">struct</span> &#123;</span><br><span class="line">    FSM *FSM</span><br><span class="line">    Event <span class="keyword">string</span></span><br><span class="line">    Src <span class="keyword">string</span></span><br><span class="line">    Dst <span class="keyword">string</span></span><br><span class="line">    Err error</span><br><span class="line">    Args []<span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">    canceled <span class="keyword">bool</span> </span><br><span class="line">    async <span class="keyword">bool</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>所以我们如何调用FSM并且进而使它的状态进行转化并且调用相应预先注册好的回调函数呢，我们通过向FSM实例传送一个event事件，FSM会先判断当前是否正在转移之中，也就是 f.transition 是否为nil，若不为nil则说明状态机正在状态转移之中，否则则说明不是，继而综合FSM当前的状态和此次遇到的事件决定目标状态，然后按顺序调用回调函数beforeEventCallbacks =&gt; leaveStateCallbacks =&gt; enterStateCallbacks =&gt; afterEventCallbacks。这样一次状态转移就算完成了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *FSM)</span> <span class="title">Event</span><span class="params">(event <span class="keyword">string</span>, args ...<span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">	<span class="keyword">if</span> f.transition != <span class="literal">nil</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> &amp;InTransitionError&#123;event&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	dst, ok := f.transitions[eKey&#123;event, f.current&#125;]</span><br><span class="line">	<span class="keyword">if</span> !ok &#123;</span><br><span class="line">		<span class="keyword">for</span> ekey := <span class="keyword">range</span> f.transitions &#123;</span><br><span class="line">			<span class="keyword">if</span> ekey.event == event &#123;</span><br><span class="line">				<span class="keyword">return</span> &amp;InvalidEventError&#123;event, f.current&#125;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;</span><br><span class="line">		<span class="keyword">return</span> &amp;UnknownEventError&#123;event&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	e := &amp;Event&#123;f, event, f.current, dst, <span class="literal">nil</span>, args, <span class="literal">false</span>, <span class="literal">false</span>&#125;</span><br><span class="line"></span><br><span class="line">	err := f.beforeEventCallbacks(e)</span><br><span class="line">	<span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> err</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> f.current == dst &#123;</span><br><span class="line">		f.afterEventCallbacks(e)</span><br><span class="line">		<span class="keyword">return</span> &amp;NoTransitionError&#123;e.Err&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	f.transition = <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">		f.current = dst</span><br><span class="line">		f.enterStateCallbacks(e)</span><br><span class="line">		f.afterEventCallbacks(e)</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	err = f.leaveStateCallbacks(e)</span><br><span class="line">	<span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> err</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	err = f.Transition()</span><br><span class="line">	<span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">		<span class="keyword">return</span> &amp;InternalError&#123;&#125;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> e.Err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *FSM)</span> <span class="title">Transition</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">	  <span class="keyword">if</span> f.transition == <span class="literal">nil</span> &#123;</span><br><span class="line">		  <span class="keyword">return</span> &amp;NotInTransitionError&#123;&#125;</span><br><span class="line">	  &#125;</span><br><span class="line">	  f.transition()</span><br><span class="line">	  f.transition = <span class="literal">nil</span></span><br><span class="line">	  <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="有限状态机的简单实践"><a href="#有限状态机的简单实践" class="headerlink" title="有限状态机的简单实践"></a>有限状态机的简单实践</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">    <span class="string">"github.com/looplab/fsm"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    fsm := fsm.NewFSM(</span><br><span class="line">        <span class="string">"closed"</span>,</span><br><span class="line">        fsm.Events&#123;</span><br><span class="line">            &#123;Name: <span class="string">"open"</span>, Src: []<span class="keyword">string</span>&#123;<span class="string">"closed"</span>&#125;, Dst: <span class="string">"open"</span>&#125;,</span><br><span class="line">            &#123;Name: <span class="string">"close"</span>, Src: []<span class="keyword">string</span>&#123;<span class="string">"open"</span>&#125;, Dst: <span class="string">"closed"</span>&#125;,</span><br><span class="line">        &#125;,</span><br><span class="line">        fsm.Callbacks&#123;&#125;,</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    fmt.Println(fsm.Current())</span><br><span class="line"></span><br><span class="line">    err := fsm.Event(<span class="string">"open"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fmt.Println(fsm.Current())</span><br><span class="line"></span><br><span class="line">    err = fsm.Event(<span class="string">"close"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fmt.Println(fsm.Current())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上述例子就定义了一个简单的开门和关门的状态机，这里我们门这个状态机的初始状态是closed，它可以利用open这个事件将状态从closed状态转移到open状态，也可以利用close这个事件将状态从open状态转移到closed状态。注意这里没有定义回调函数（fsm.Callbacks{}为空），所以这两件事件触发的时候什么事情也不会发生。</p>
-<p>而调用事件就是通过fsm.Event(“open”)或fsm.Event(“close”)来完成的。</p>
-<p>上述就是实现一个简单的有限状态机的代码啦，具体的实现可以参考<a href="http://github.com/looplab/fsm" target="_blank" rel="noopener">Finite State Machine</a>。</p>
-<p>简单总结一下，实现有限状态机需要下面几件事情。</p>
-<ol>
-<li>有限状态机的初始状态</li>
-<li>有限状态机各个状态之间迁移的各种情况，也就是状态拓扑图</li>
-<li>状态迁移时的回调方法</li>
-</ol>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/25/Fanin/index.html b/2018/04/25/Fanin/index.html
deleted file mode 100644
index cc0b8af..0000000
--- a/2018/04/25/Fanin/index.html
+++ /dev/null
@@ -1,252 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Fan-in | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在对消息的处理过程中，我们常常会遇到不同来源的消息，如在Golang中这些消息来自于不同的通道，但是这些消息在本质上都是相同的，所以，如何把这些消息进行聚合后再处理，就是我们这篇文章需要探讨的内容。下面我们引入Fanin这种编程模型。 假设Master节点需要处理3个Slave节点的消息，这3个Slave节点的消息我们使用Golang中的通道进行模拟。 1234567891011121314151">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Fan-in">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/25/Fanin/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在对消息的处理过程中，我们常常会遇到不同来源的消息，如在Golang中这些消息来自于不同的通道，但是这些消息在本质上都是相同的，所以，如何把这些消息进行聚合后再处理，就是我们这篇文章需要探讨的内容。下面我们引入Fanin这种编程模型。 假设Master节点需要处理3个Slave节点的消息，这3个Slave节点的消息我们使用Golang中的通道进行模拟。 1234567891011121314151">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:37.019Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Fan-in">
-<meta name="twitter:description" content="在对消息的处理过程中，我们常常会遇到不同来源的消息，如在Golang中这些消息来自于不同的通道，但是这些消息在本质上都是相同的，所以，如何把这些消息进行聚合后再处理，就是我们这篇文章需要探讨的内容。下面我们引入Fanin这种编程模型。 假设Master节点需要处理3个Slave节点的消息，这3个Slave节点的消息我们使用Golang中的通道进行模拟。 1234567891011121314151">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Fanin"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Fan-in
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-25T12:35:24.000Z" itemprop="datePublished">
-        Apr 25, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在对消息的处理过程中，我们常常会遇到不同来源的消息，如在Golang中这些消息来自于不同的通道，但是这些消息在本质上都是相同的，所以，如何把这些消息进行聚合后再处理，就是我们这篇文章需要探讨的内容。下面我们引入Fanin这种编程模型。</p>
-<p>假设Master节点需要处理3个Slave节点的消息，这3个Slave节点的消息我们使用Golang中的通道进行模拟。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Message <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Fanin</span><span class="params">(cs ...&lt;-<span class="keyword">chan</span> *Message)</span> &lt;-<span class="title">chan</span> *<span class="title">Message</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line">    </span><br><span class="line">    out := <span class="built_in">make</span>(<span class="keyword">chan</span> *Message)</span><br><span class="line">    </span><br><span class="line">    send := <span class="function"><span class="keyword">func</span><span class="params">(c &lt;-<span class="keyword">chan</span> *Message)</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> n := <span class="keyword">range</span> c &#123;</span><br><span class="line">            out &lt;- n</span><br><span class="line">        &#125;</span><br><span class="line">        wg.Done()</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    wg.Add(<span class="built_in">len</span>(cs))</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> c := <span class="keyword">range</span> cs &#123;</span><br><span class="line">        <span class="keyword">go</span> send(c)</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        wg.Wait()</span><br><span class="line">        <span class="built_in">close</span>(out)</span><br><span class="line">    &#125;()</span><br><span class="line">    <span class="keyword">return</span> out</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在函数中我们新建一个用于消息输出的通道out，并且遍历所有cs中的输入通道c，将中的消息取出后再重新放入out当中，这样就达到了将多个通道合并为一个通道的目的。</p>
-<p>但是上述方法也有其弊端，就是需要提前知晓所有的输入通道，但是在很多情况下，输入通道可能是动态增加的，那这种情况下我们应该怎么办呢？</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Message <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> MessageFan <span class="keyword">struct</span> &#123;</span><br><span class="line">    ins []&lt;-<span class="keyword">chan</span> *Message</span><br><span class="line">    out &lt;-<span class="keyword">chan</span> *Message</span><br><span class="line">    lock sync.Mutex</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewMessageFan</span><span class="params">()</span> *<span class="title">MessageFan</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;MessageFan&#123;</span><br><span class="line">        ins: []&lt;-<span class="keyword">chan</span> *Message,</span><br><span class="line">        out: <span class="built_in">make</span>(&lt;-<span class="keyword">chan</span> *Message),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(fan *MessageFan)</span> <span class="title">AddFaninChannel</span><span class="params">(channel &lt;-<span class="keyword">chan</span> *Message)</span></span> &#123;</span><br><span class="line">    fan.lock.Lock()</span><br><span class="line">    <span class="keyword">defer</span> fan.lock.Unlock()</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> _, c := <span class="keyword">range</span> fan.in &#123;</span><br><span class="line">        <span class="keyword">if</span> c == channel &#123;</span><br><span class="line">            fmt.Println(<span class="string">"Received duplicate connection"</span>)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    fan.ins = <span class="built_in">append</span>(fan.ins, channel)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> msg := <span class="keyword">range</span> channel &#123;</span><br><span class="line">            out &lt;- msg</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        fan.lock.Lock()</span><br><span class="line">        <span class="keyword">defer</span> fan.lock.Unlock()</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">for</span> i, c := <span class="keyword">range</span> fan.ins &#123;</span><br><span class="line">            <span class="keyword">if</span> c == channel &#123;</span><br><span class="line">                fan.ins = <span class="built_in">append</span>(fan.ins[:i], fan.ins[i+<span class="number">1</span>:]...)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(fan *MessageFan)</span> <span class="title">GetOutChannel</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> fan.out</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>这里我们定义了一个 <code>MessageFan</code> 结构体，里面包含了一个输入通道的数组和一个输出通道，在实例化 <code>MessageFan</code> 的时候，注意，我们仅仅对 <code>out</code>进行了 <code>make</code> 操作，因为 <code>out</code> 通道是确定的，只有一个，而我们的输入通道却是 <code>runtime</code> 时决定的，所以无法使用 <code>make</code> 操作。当我们调用 <code>AddFaninChannel</code> 方法的时候，我们先遍历 <code>ins</code> 这个通道数组，看有没有相同的实现已经加入过的通道，有则返回，没有则将它加入 <code>ins</code> ，同样的，在 <code>goroutine</code> 中轮询这个 <code>channel</code> ，将它的消息塞入 <code>out</code> 中，注意，在一般情况下该for循环是阻塞的，如果for循环返回，则说明 <code>channel</code> 已经被关闭了，即在代码的某处执行了 <code>close(channel)</code> 这个操作，所以说明它已经没有作用了，我们就可以把它在我们的ins数组中删除。    </p>
-<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>上述两种方法都实现了Fanin这种编程模型，当你遇到那种需要对不同来源但是类型却相同的消息进行集中处理时，就可以考虑使用这种编程模型啦。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/25/Protobuf/index.html b/2018/04/25/Protobuf/index.html
deleted file mode 100644
index dd66fe9..0000000
--- a/2018/04/25/Protobuf/index.html
+++ /dev/null
@@ -1,257 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Protocol Buffer | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Protobuf是一种用于信息交换的数据格式，你们可能会问我可以用JSON，再不济XML也可以用啊，为什么要接触这个完全没有用过的玩意儿呢？答案只有两个字：高效。使用XML不仅会占用更多的存储空间，而且会降低整个系统的性能。 搞过分布式系统的朋友一定知道，消息在分布式系统中起着至关重要的作用，例如两个节点之间相互交换自己的状态信息，一个网络中节点之间的交流就需要负载在消息之上，与人类一样，只有节点">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Protocol Buffer">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/25/Protobuf/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Protobuf是一种用于信息交换的数据格式，你们可能会问我可以用JSON，再不济XML也可以用啊，为什么要接触这个完全没有用过的玩意儿呢？答案只有两个字：高效。使用XML不仅会占用更多的存储空间，而且会降低整个系统的性能。 搞过分布式系统的朋友一定知道，消息在分布式系统中起着至关重要的作用，例如两个节点之间相互交换自己的状态信息，一个网络中节点之间的交流就需要负载在消息之上，与人类一样，只有节点">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:22.632Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Protocol Buffer">
-<meta name="twitter:description" content="Protobuf是一种用于信息交换的数据格式，你们可能会问我可以用JSON，再不济XML也可以用啊，为什么要接触这个完全没有用过的玩意儿呢？答案只有两个字：高效。使用XML不仅会占用更多的存储空间，而且会降低整个系统的性能。 搞过分布式系统的朋友一定知道，消息在分布式系统中起着至关重要的作用，例如两个节点之间相互交换自己的状态信息，一个网络中节点之间的交流就需要负载在消息之上，与人类一样，只有节点">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Protobuf"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Protocol Buffer
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-25T08:03:24.000Z" itemprop="datePublished">
-        Apr 25, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>Protobuf是一种用于信息交换的数据格式，你们可能会问我可以用JSON，再不济XML也可以用啊，为什么要接触这个完全没有用过的玩意儿呢？答案只有两个字：高效。使用XML不仅会占用更多的存储空间，而且会降低整个系统的性能。</p>
-<p>搞过分布式系统的朋友一定知道，消息在分布式系统中起着至关重要的作用，例如两个节点之间相互交换自己的状态信息，一个网络中节点之间的交流就需要负载在消息之上，与人类一样，只有节点之间有一套共用的语言，分布式系统才能正常工作下去。而且protobuf可以让我们非常方便的定义消息的类型，它还提供了供我们序列化和反序列化的API，下面我们就来看看该如何使用它。</p>
-<h2 id="前期准备"><a href="#前期准备" class="headerlink" title="前期准备"></a>前期准备</h2><p>首先需要安装protobuf，使用macOS的用户可以考虑使用brew进行安装，安装完了之后还需要安装Go语言的protobuf插件—proto-gen-go，这个插件会被安装在 <code>$GOPATH/bin</code> 目录下。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ brew install protobuf</span><br><span class="line">$ go get -u github.com/golang/protobuf/protoc-gen-go</span><br></pre></td></tr></table></figure>
-<h2 id="定义我们自己的消息格式"><a href="#定义我们自己的消息格式" class="headerlink" title="定义我们自己的消息格式"></a>定义我们自己的消息格式</h2><p>使用protobuf，我们只需要定义一个以 <code>.proto</code> 结尾的文件，这里我们以PBFT算法中的几个消息类型为例子进行讲解，首先注意到”=1”， “=2”这样的标记，这些标记是为了二进制编码用的。其次，如果一个消息中有多个类似的成员，也就是一个数组，我们可以使用 <code>repeated</code> 这个关键字来表示。</p>
-<figure class="highlight protobuf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">syntax = &quot;proto3&quot;;</span><br><span class="line"></span><br><span class="line">import &quot;google/protobuf/timestamp.proto&quot;;</span><br><span class="line"></span><br><span class="line">package pbft;</span><br><span class="line"></span><br><span class="line">message request &#123;</span><br><span class="line">    google.protobuf.Timestamp timestamp = 1;</span><br><span class="line">    bytes payload = 2;</span><br><span class="line">    uint64 replica_id = 3;</span><br><span class="line">    bytes signature = 4;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">message request_batch &#123;</span><br><span class="line">    repeated request batch = 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">message pre_prepare &#123;</span><br><span class="line">    uint64 view = 1;</span><br><span class="line">    uint64 sequence_number = 2;</span><br><span class="line">    string batch_digest = 3;</span><br><span class="line">    request_batch request_batch = 4;</span><br><span class="line">    uint64 replica_id = 5;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">message prepare &#123;</span><br><span class="line">    uint64 view = 1;</span><br><span class="line">    uint64 sequence_number = 2;</span><br><span class="line">    string batch_digest = 3;</span><br><span class="line">    uint64 replica_id = 4;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">message commit &#123;</span><br><span class="line">    uint64 view = 1;</span><br><span class="line">    uint64 sequence_number = 2;</span><br><span class="line">    string batch_digest = 3;</span><br><span class="line">    uint64 replica_id = 4;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="使用protoc编译器编译我们的消息"><a href="#使用protoc编译器编译我们的消息" class="headerlink" title="使用protoc编译器编译我们的消息"></a>使用protoc编译器编译我们的消息</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/messages.proto</span><br></pre></td></tr></table></figure>
-<p>在命令行中运行上述命令，<code>-I</code> 表示你的源文件所在的目录，<code>--go_out</code>  表示你指定的生成目标文件（messages.pb.go）的目录，一般来说与源文件所在的目录相同，最后就是我们需要编译的源文件的路径。</p>
-<h2 id="使用protobuf提供的API对消息进行写操作"><a href="#使用protobuf提供的API对消息进行写操作" class="headerlink" title="使用protobuf提供的API对消息进行写操作"></a>使用protobuf提供的API对消息进行写操作</h2><p>我们可以使用 <code>proto.Marshal()</code> 对数据进行序列化。序列化之后得到的是一个字节数组（ []byte ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">prep := &amp;pb.Prepare&#123;</span><br><span class="line">    view: <span class="number">1</span>,</span><br><span class="line">    SequenceNumber: <span class="number">2</span>,</span><br><span class="line">    BatchDigest: <span class="string">"aaaaa"</span>,</span><br><span class="line">    ReplicaId: <span class="number">11</span>,    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">out, err := proto.Marshal(prep)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    fmt.Printf(<span class="string">"Error marshalling prepare: %s"</span>, err) </span><br><span class="line">    <span class="keyword">return</span> </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err := ioutil.WriteFile(fname, out, <span class="number">0644</span>); err != <span class="literal">nil</span> &#123;</span><br><span class="line">    fmt.Printf(<span class="string">"Error writing file: %s"</span>, err) </span><br><span class="line">    <span class="keyword">return</span>    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="使用protobuf提供的API对消息进行读操作"><a href="#使用protobuf提供的API对消息进行读操作" class="headerlink" title="使用protobuf提供的API对消息进行读操作"></a>使用protobuf提供的API对消息进行读操作</h2><p>对编码过的数据调用 <code>proto.Unmarshal</code> 就可以进行反序列化操作得到原来的信息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">in, err := ioutil.ReadFile(fname)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    fmt.Printf(<span class="string">"Error reading file: %s"</span>, err) </span><br><span class="line">    <span class="keyword">return</span>    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">prep := &amp;pb.Prepare&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err := proto.Unmarshal(in, prep); err != <span class="literal">nil</span> &#123;</span><br><span class="line">    fmt.Printf(<span class="string">"Error unmarshalling prepare: %s"</span>, err)</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当然了，上面两个例子是将序列化的数据存储到文件中，同样的，我们可以将序列化后的数据直接在网上传播，因为序列化后的数据已经是 <code>wire format</code> 了。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/25/gRPC/index.html b/2018/04/25/gRPC/index.html
deleted file mode 100644
index 8a24415..0000000
--- a/2018/04/25/gRPC/index.html
+++ /dev/null
@@ -1,270 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>gRPC | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="首先，在了解 gRPC 之前，要搞清楚什么是 RPC ，RPC ， Remote Procedure Call ，即远程过程调度，它采用 C/S模型，本质就是客户端通过网络向远程计算机程序也就是服务端发送请求服务，远程服务器执行后向客户端返回答复，RPC 是分布式系统中非常重要的一个组成部分。 RPC 和本地方法调用最大的区别就在于程序是否在一个地址空间内执行，那么我们为什么要用到 RPC 呢，例">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="gRPC">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/25/gRPC/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="首先，在了解 gRPC 之前，要搞清楚什么是 RPC ，RPC ， Remote Procedure Call ，即远程过程调度，它采用 C/S模型，本质就是客户端通过网络向远程计算机程序也就是服务端发送请求服务，远程服务器执行后向客户端返回答复，RPC 是分布式系统中非常重要的一个组成部分。 RPC 和本地方法调用最大的区别就在于程序是否在一个地址空间内执行，那么我们为什么要用到 RPC 呢，例">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://camo.githubusercontent.com/e4deb67aa41f71d46774f192b05b75be5c3da112/68747470733a2f2f7261772e6769746875622e636f6d2f6875696368656e2f7a6572672f6d61737465722f646f632f7a6572672e706e67">
-<meta property="og:updated_time" content="2018-06-26T08:45:57.427Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="gRPC">
-<meta name="twitter:description" content="首先，在了解 gRPC 之前，要搞清楚什么是 RPC ，RPC ， Remote Procedure Call ，即远程过程调度，它采用 C/S模型，本质就是客户端通过网络向远程计算机程序也就是服务端发送请求服务，远程服务器执行后向客户端返回答复，RPC 是分布式系统中非常重要的一个组成部分。 RPC 和本地方法调用最大的区别就在于程序是否在一个地址空间内执行，那么我们为什么要用到 RPC 呢，例">
-<meta name="twitter:image" content="https://camo.githubusercontent.com/e4deb67aa41f71d46774f192b05b75be5c3da112/68747470733a2f2f7261772e6769746875622e636f6d2f6875696368656e2f7a6572672f6d61737465722f646f632f7a6572672e706e67">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-gRPC"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      gRPC
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-25T08:27:24.000Z" itemprop="datePublished">
-        Apr 25, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>首先，在了解 <code>gRPC</code> 之前，要搞清楚什么是 <code>RPC</code> ，<code>RPC</code> ， <code>Remote Procedure Call</code> ，即远程过程调度，它采用 <code>C/S</code>模型，本质就是客户端通过网络向远程计算机程序也就是服务端发送请求服务，远程服务器执行后向客户端返回答复，<code>RPC</code> 是分布式系统中非常重要的一个组成部分。</p>
-<p><code>RPC</code> 和本地方法调用最大的区别就在于程序是否在一个地址空间内执行，那么我们为什么要用到 <code>RPC</code> 呢，例如我们要写一个分布式爬虫的框架，因为自己的笔记本电脑处理能力有限，为了提高爬虫效率，我们租借了几台 <code>8C16G</code> 的高性能服务器帮我们完成任务，这样就可以由客户端发送爬虫指令，具体的粗活累活可以由服务器代替完成，如下面 <code>client</code> 向服务器发送一个 <code>crawl request</code> ，里面包含了我们要爬取的网站的具体信息，在服务器完成任务之后，向 <code>client</code> 返回一个 <code>crawl response</code> ，也就是爬虫的结果。</p>
-<p><img src="https://camo.githubusercontent.com/e4deb67aa41f71d46774f192b05b75be5c3da112/68747470733a2f2f7261772e6769746875622e636f6d2f6875696368656e2f7a6572672f6d61737465722f646f632f7a6572672e706e67" alt="grpc"></p>
-<p>关于 <code>RPC</code> ，不同的语言有不同的解决方案，例如在golang的标准库中就提供了 <code>net/rpc</code> 这个解决方案，虽然这个方法效率很高，但是它的缺点也是比较致命的，就是它仅能在golang程序中使用，而我们今天的主角，<code>gRPC</code> 就是一个跨语言平台的通用高性能 <code>RPC</code> 库，听着是不是很酷炫，下面就让我们来仔细学习一下吧。</p>
-<h2 id="利用gRPC定义我们的服务"><a href="#利用gRPC定义我们的服务" class="headerlink" title="利用gRPC定义我们的服务"></a>利用gRPC定义我们的服务</h2><p>在使用 <code>gRPC</code> 之前我们需要安装它，在命令行中输入以下命令。</p>
-<p><code>$ go get -u google.golang.org/grpc</code></p>
-<p><code>gRPC</code> 在定义服务时采用了 <code>protobuf</code> 的语法格式，我们需要定义 <code>gRPC</code> 中请求消息和答复消息的数据格式，这个我们应该已经非常熟悉了，就是定义两个 <code>message</code> （详情可以参考 <code>protobuf</code> 的官方文档），<code>CrawlRequest</code> 和 <code>CrawlResponse</code> ，除此之外我们还要定义一个 <code>service</code> ，说白了也就是我们要定义的 <code>RPC</code> 方法。也就是说我们向服务器发送一个 <code>CrawlRequest</code> 消息，服务器处理完成后会向我们返回一个 <code>CrawlResponse</code> 。</p>
-<figure class="highlight protobuf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">service Crawl &#123;</span><br><span class="line">    rpc Crawl (CrawlRequest) returns (CrawlResponse) &#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">message CrawlRequest &#123;</span><br><span class="line">    string url = 1;</span><br><span class="line">    int64 timeout = 2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">message CrawlResponse &#123;</span><br><span class="line">    string content = 1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>使用 <code>gRPC</code> 的好处就在于它可以根据我们定义的服务自动生成相应的服务端和客户端的代码，也就是说我们只要关心具体调用服务的逻辑，剩下具体的实现由框架帮我们干就可以了。</p>
-<p>由于是 <code>protobuf</code> 文件，我们使用 <code>protoc</code> 来编译它就可以了。</p>
-<p><code>$ protoc --go_out=plugins=grpc:. *.proto</code></p>
-<h2 id="gRPC-原理"><a href="#gRPC-原理" class="headerlink" title="gRPC 原理"></a>gRPC 原理</h2><p><code>gRPC</code> 相当于给我们一个框架，具体的代码就在我们的 <code>crawl.proto</code> 这个文件经过 <code>protoc</code> 编译后的得到的 <code>crawl.pb.go</code> 这个文件中，下面的代码都是由 <code>protoc</code> 经过编译后自动生成的，编译后的文件都具有类似的格式，基本看一个例子就可以一通百通了。</p>
-<p>编译后得到的代码在客户端部分定义了一个大写的 <code>CrawlClient</code> 这个interface，而小写的 <code>crawlClient</code> 结构体则具体实现了它，注意到一个 <code>crawlClient</code> 中包含了一个<code>grpc.ClientConn</code> 结构体，与 <code>net.Conn</code> 类似，它是真正发送网络请求的结构体，<code>grpc.Invoke</code> 则才是具体发送网络请求的行为。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> CrawlClient <span class="keyword">interface</span> &#123;</span><br><span class="line">    Crawl(ctx context.Context, in *CrawlRequest, opts ...grpc.CallOption) (*CrawlResponse, error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> crawlClient <span class="keyword">struct</span> &#123;</span><br><span class="line">    cc *grpc.ClientConn</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> NewCrawlClient(cc *grpc.ClientConn) CrawlClient &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;crawlClient&#123;cc&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *crawlClient)</span> <span class="title">Crawl</span><span class="params">(ctx context.Context, </span></span></span><br><span class="line"><span class="function"><span class="params">                            in *CrawlRequest, </span></span></span><br><span class="line"><span class="function"><span class="params">                            opts ...grpc.CallOption)</span> <span class="params">(*CrawlResponse, error)</span></span> &#123;</span><br><span class="line">    out := <span class="built_in">new</span>(CrawlResponse)</span><br><span class="line">    err := grpc.Invoke(ctx, <span class="string">"/protos.Crawl/Crawl"</span>, in, out, c.cc, opts...)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> out, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>与 <code>CrawClient</code> 不同的是，并没有结构体直接实现 <code>CrawlServer</code> 这个接口，毕竟 <code>gRPC</code> 仅仅是一个框架，具体的逻辑代码还是需要我们自己去填充的。<code>RegisterCrawlServer</code> 方法则向 <code>gRPC</code> 注册该服务，注册的过程也需要我们自己在代码中调用。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> CrawlServer <span class="keyword">interface</span> &#123;</span><br><span class="line">    Crawl(context.Context, *CrawlRequest) (*CrawlResponse, error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RegisterCrawlServer</span><span class="params">(s *grpc.Server, srv CrawlServer)</span></span> &#123;</span><br><span class="line">    s.RegisterService(&amp;_Crawl_serviceDesc, srv)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> _<span class="title">Crawl_Crawl_Handler</span><span class="params">(srv <span class="keyword">interface</span>&#123;&#125;, </span></span></span><br><span class="line"><span class="function"><span class="params">                          ctx context.Context, </span></span></span><br><span class="line"><span class="function"><span class="params">                          dec <span class="keyword">func</span>(<span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">error</span>, </span></span><br><span class="line"><span class="function">                          <span class="title">interceptor</span> <span class="title">grpc</span>.<span class="title">UnaryServerInterceptor</span>) <span class="params">(<span class="keyword">interface</span>&#123;&#125;, error)</span></span> &#123;</span><br><span class="line">    in := <span class="built_in">new</span>(CrawlRequest)</span><br><span class="line">    <span class="keyword">if</span> err := dec(in); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> interceptor == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> srv.(CrawlServer).Crawl(ctx, in)</span><br><span class="line">    &#125;</span><br><span class="line">    info := &amp;grpc.UnaryServerInfo&#123;</span><br><span class="line">        Server:     srv,</span><br><span class="line">        FullMethod: <span class="string">"/protos.Crawl/Crawl"</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    handler := <span class="function"><span class="keyword">func</span><span class="params">(ctx context.Context, req <span class="keyword">interface</span>&#123;&#125;)</span> <span class="params">(<span class="keyword">interface</span>&#123;&#125;, error)</span></span> &#123;</span><br><span class="line">        <span class="keyword">return</span> srv.(CrawlServer).Crawl(ctx, req.(*CrawlRequest))</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> interceptor(ctx, in, info, handler)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> _Crawl_serviceDesc = grpc.ServiceDesc&#123;</span><br><span class="line">    ServiceName: <span class="string">"protos.Crawl"</span>,</span><br><span class="line">    HandlerType: (*CrawlServer)(<span class="literal">nil</span>),</span><br><span class="line">    Methods: []grpc.MethodDesc&#123;</span><br><span class="line">        &#123;</span><br><span class="line">            MethodName: <span class="string">"Crawl"</span>,</span><br><span class="line">            Handler:    _Crawl_Crawl_Handler,</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    Streams:  []grpc.StreamDesc&#123;&#125;,</span><br><span class="line">    Metadata: <span class="string">"crawl.proto"</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Server"><a href="#Server" class="headerlink" title="Server"></a>Server</h2><p>下面需要我们自己实现具体的业务逻辑（这里就是爬虫的业务逻辑），毕竟 <code>gRPC</code> 可不能猜到我们究竟要干什么事情，我们先定义一个包含 <code>http.Client</code> 的结构体 <code>crawlServer</code> ，当然了，<code>crawlServer</code> 究竟要包含什么要看具体的业务场景了，这里因为是爬虫所以要包含 <code>http.Client</code> 用于发送http请求。</p>
-<p>所以我们在 <code>Crawl</code> 方法中实现具体的爬虫逻辑。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> crawlServer <span class="keyword">struct</span>&#123;</span><br><span class="line">    client *http.Client</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *crawlServer)</span> <span class="title">Crawl</span><span class="params">(ctx context.Context, in *pb.CrawlRequest)</span> <span class="params">(*pb.CrawlResponse, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> s.internalCrawl(in)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *crawlServer)</span> <span class="title">internalCrawl</span><span class="params">(in *pb.CrawlRequest)</span> <span class="params">(*pb.CrawlResponse, error)</span></span> &#123;</span><br><span class="line">    <span class="comment">// .... 具体的爬虫逻辑</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>与普通的 <code>tcp</code> 网络编程类似的，我们需要监听特定的端口，当这个端口监听到来自客户端的连接请求时，<code>gRPC</code> 会接受该连接请求，并且新起一个 <code>goroutine</code> 去处理该请求，然后读取该请求的消息类型，<code>gRPC</code> 内部会去检查这个消息的类型，最后决定调用哪个 handler（也就是之前Register过的）去处理该请求，具体处理后向客户端返回答复。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">listener, err := net.Listen(<span class="string">"tcp"</span>, *address)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    log.Fatal(err)</span><br><span class="line">&#125;</span><br><span class="line">s:= grpc.NewServer()</span><br><span class="line">pb.RegisterCrawlServer(s, &amp;crawlServer&#123;&#125;)</span><br><span class="line">s.Serve(listener)</span><br></pre></td></tr></table></figure>
-<h2 id="Client"><a href="#Client" class="headerlink" title="Client"></a>Client</h2><p>在客户端这里，我们需要一个类似 <code>net.Conn</code> 这样的结构体用于发送和接受消息，在 <code>gRPC</code> 中，我们可以通过类似 <code>net.Dial</code> 的方法 <code>grpc.Dial</code> 来返回一个 <code>grpc.ClientConn</code> 结构体，然后通过该结构体新建一个客户端 <code>pb.NewCrawlClient</code> ，最后用这个客户端发送我们的请求就可以了，在很多地方，客户端也被叫做 <code>stub</code>， 因为它仅仅有方法调用的接口，而真正实现业务逻辑的方法还是在服务端上面。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">conn, err := grpc.Dial(*address, grpc.WithInsecure())</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    log.Fatal(err)</span><br><span class="line">&#125;</span><br><span class="line">client := pb.NewCrawlClient(conn)</span><br><span class="line"></span><br><span class="line">request := pb.CrawlRequest&#123;</span><br><span class="line">    Url:     *url,</span><br><span class="line">    Timeout: <span class="number">10000</span>,</span><br><span class="line">&#125;</span><br><span class="line">response, err := client.Crawl(context.Background(), &amp;request)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    log.Fatal(err)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在使用 <code>gRPC</code> 时，我们需要明确自己的责任与分工，什么事情应该我们自己干，而什么事情又是框架帮我们干好而我们不需要重复去做的。其实说到底，我们使用<code>RPC</code> 的目的就是让任务在远程执行后返回处理结果，具体的任务该怎么执行 <code>gRPC</code> 肯定是不知道的，所以相关的业务逻辑应该在服务端进行定义，毕竟活是服务端干的（如上面结构体 <code>crawlServer</code> 实现的 <code>Crawl</code> 方法），我们只需要定义相关的 <code>Request</code> 和 <code>Response</code> 消息，再定义一个 <code>service</code> 服务，用 <code>protoc</code> 编译生成相应的代码，最后再定义服务端上面的处理逻辑就可以了。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/26/EventProcessEngine/index.html b/2018/04/26/EventProcessEngine/index.html
deleted file mode 100644
index 4cb5cae..0000000
--- a/2018/04/26/EventProcessEngine/index.html
+++ /dev/null
@@ -1,269 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Event Process Engine | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在许多情况下，尤其是在搞一致性算法的时候，如何对事件（Event）集中进行处理就变成了一件很重要的事情，下面，我们来介绍如何写一个简单的事件处理引擎，并且向上层提供一个简单可用（无脑）的API供其他程序员使用。 首先我们需要明白我们要对各种各样的事件进行处理，例如，在PBFT中，我们的消息类型有 Preprepare ， Prepare ， Commit ， ViewChange 等等，具体的消息">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Event Process Engine">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/26/EventProcessEngine/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在许多情况下，尤其是在搞一致性算法的时候，如何对事件（Event）集中进行处理就变成了一件很重要的事情，下面，我们来介绍如何写一个简单的事件处理引擎，并且向上层提供一个简单可用（无脑）的API供其他程序员使用。 首先我们需要明白我们要对各种各样的事件进行处理，例如，在PBFT中，我们的消息类型有 Preprepare ， Prepare ， Commit ， ViewChange 等等，具体的消息">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:15.070Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Event Process Engine">
-<meta name="twitter:description" content="在许多情况下，尤其是在搞一致性算法的时候，如何对事件（Event）集中进行处理就变成了一件很重要的事情，下面，我们来介绍如何写一个简单的事件处理引擎，并且向上层提供一个简单可用（无脑）的API供其他程序员使用。 首先我们需要明白我们要对各种各样的事件进行处理，例如，在PBFT中，我们的消息类型有 Preprepare ， Prepare ， Commit ， ViewChange 等等，具体的消息">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-EventProcessEngine"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Event Process Engine
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-26T01:43:24.000Z" itemprop="datePublished">
-        Apr 26, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在许多情况下，尤其是在搞一致性算法的时候，如何对事件（Event）集中进行处理就变成了一件很重要的事情，下面，我们来介绍如何写一个简单的事件处理引擎，并且向上层提供一个简单可用（无脑）的API供其他程序员使用。</p>
-<p>首先我们需要明白我们要对各种各样的事件进行处理，例如，在PBFT中，我们的消息类型有 <code>Preprepare</code> ， <code>Prepare</code> ， <code>Commit</code> ， <code>ViewChange</code> 等等，具体的消息类型的定义我们可以使用protobuf来，而无论是什么事件，我们在Golang中我们都可以把它们抽象成一个 <code>interface{}</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Event <span class="keyword">interface</span>&#123;&#125;</span><br></pre></td></tr></table></figure>
-<p>这里我们定义的 <code>Event</code> 是我们以后围绕着处理的中心，我们继续看。定义完了 <code>Event</code> ，我们还要定义一个 <code>Event</code> 的接受者（Receiver），也就是事物处理的核心。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Receiver <span class="keyword">interface</span> &#123;</span><br><span class="line">    ProcessEvent(e Event) Event</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在这里我们注意到这是一个 <code>interface</code> ，只要你定义的对象实现了 <code>ProcessEvent</code> 这个方法，那么它就是一个 <code>Receiver</code> ，当然，你自己定义的 <code>ProcessEvent</code> 里面才是真正的业务逻辑，这里仅仅提供一个框架而已。</p>
-<p>定义完了事件的接受者，<code>Receiver</code>，我们来看下更高层次的管理者 <code>Manager</code> ，如果把 <code>Manager</code> 想象成公司里的领导，那么他负责的事情就是调度，并且指派任务给专门的个体也就是我们的 <code>Receiver</code> 去处理。 <code>Receiver</code> 是具体干活的，而 <code>Manager</code> 则是分配任务的。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Manager <span class="keyword">interface</span> &#123;</span><br><span class="line">    Inject(Event)</span><br><span class="line">    Queue() &lt;-<span class="keyword">chan</span> Event</span><br><span class="line">    SetReceiver(Receiver)</span><br><span class="line">    Start()</span><br><span class="line">    Halt()</span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> managerImpl &#123;</span><br><span class="line">    threaded </span><br><span class="line">    receiver Receiver</span><br><span class="line">    events <span class="keyword">chan</span> Event</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> threaded <span class="keyword">struct</span> &#123;</span><br><span class="line">    exit <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>一个Manager的职能具体有两大点，一就是管理事件的队列（events这个通道），二就是取出队列中的事件，指派接受者（SetReceiver(Receiver)）进行处理（Start）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(em *managerImpl)</span> <span class="title">Queue</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> em.events</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(em *managerImpl)</span> <span class="title">SetReceiver</span><span class="params">(receiver Receiver)</span></span> &#123;</span><br><span class="line">    em.receiver = receiver</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewManagerImpl</span><span class="params">()</span> <span class="title">Manager</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;managerImpl&#123;</span><br><span class="line">        events: <span class="built_in">make</span>(<span class="keyword">chan</span> Event),</span><br><span class="line">        threaded: threaded&#123;<span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(em *managerImpl)</span> <span class="title">Start</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">go</span> em.eventLoop()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Manager</code> 的启动就是就是开了一个goroutine对消息进行循环处理，下面来看一下 <code>eventLoop</code> 的实现。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(em *managerImpl)</span> <span class="title">eventLoop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> e := &lt;-em.events:</span><br><span class="line">            em.Inject(e)</span><br><span class="line">        <span class="keyword">case</span> &lt;-em.exit:</span><br><span class="line">            logger.Debug(<span class="string">"event told to exit"</span>)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>eventLoop</code> 里面是咋一看是一个死循环，但它还是有出口的，它通过 <code>for select</code> 机制一直去轮询 <code>em.events</code> 和<code>em.exit</code>这两个通道，如果 <code>em.exit</code> 这个通道有值，则说明该事件处理循环要退出了，这就是程序的一个出口，但如果<code>em.events</code>有消息返回，我们则将它插入到我们 <code>manager</code> 的事件队列里等待被处理，也就是调用 <code>em.Inject(e)</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(em *managerImpl)</span> <span class="title">Inject</span><span class="params">(event Event)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> em.Receiver != <span class="literal">nil</span> &#123;</span><br><span class="line">        SendEvent(em.Receiver, event)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Inject</code> 行为的主体是 <code>manager</code> ， <code>manager</code> 把任务（event）分配给我们的 <code>receiver</code>。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">SendEvent</span><span class="params">(receiver Receiver, event Event)</span></span> &#123;</span><br><span class="line">    next := Event</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        next  := receiver.ProcessEvent(next)</span><br><span class="line">        <span class="keyword">if</span> next == <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>SendEvent</code> 函数才是真正干活的主力，它主要就是调用 <code>Receiver</code> 实现定义好的 <code>ProcessEvent</code> 方法，因为处理一个事件后可能会返回另一件事件，所以循环处理它直到为空时候返回。看到这里，你可能会不理解处理意见事件会什么会返回另一件事件呢，其实现实中处理完A事件返回B事件的例子有很多，例如在PBFT中，处理完 <code>Preprepare</code> 事件，我们赶忙就要开始处理 <code>Prepare</code> 事件了。这种例子还有很多，以后有机会我们再详细介绍。</p>
-<p>上面就是我们整个事件处理的引擎了，不难，但是设计的非常精妙，下面我们来看如何使用它。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> aEvent Event</span><br><span class="line"><span class="keyword">type</span> bEvent Event</span><br><span class="line"><span class="keyword">type</span> cEvent Event</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Instance <span class="keyword">struct</span>&#123;</span><br><span class="line">    manager Manager</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(i *Instance)</span> <span class="title">ProcessEvent</span><span class="params">(e Event)</span> <span class="title">Event</span></span> &#123;</span><br><span class="line">    <span class="keyword">switch</span> et := e.(<span class="keyword">type</span>) &#123;</span><br><span class="line">    <span class="keyword">case</span> aEvent:</span><br><span class="line">        fmt.Println(<span class="string">"Received A Event, return B Event"</span>)</span><br><span class="line">        <span class="keyword">return</span> bEvent</span><br><span class="line">    <span class="keyword">case</span> bEvent:</span><br><span class="line">        fmt.Println(<span class="string">"Received B Event, return C Event"</span>)</span><br><span class="line">        <span class="keyword">return</span> cEvent</span><br><span class="line">    <span class="keyword">case</span> cEvent:</span><br><span class="line">        fmt.Println(<span class="string">"Received C Event, return nil"</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        fmt.Println(<span class="string">"Received undefined message type"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> i Instance</span><br><span class="line">    i.manager = NewManagerImpl()</span><br><span class="line">    i.manager.SetReceiver(i)</span><br><span class="line">    i.manager.Start()</span><br><span class="line"></span><br><span class="line">    i.manager.Queue() &lt;- aEvent</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>这里我们定义了三种事件类型，并且定义了一个包含manager的结构体，这个结构体实现了 <code>ProcessEvent</code> 方法，也就是说它实现了 <code>Receiver</code> 这个接口， <code>ProcessEvent</code> 方法里通过判断接收到的event的类型，来进行相应的处理，注意到处理完<code>aEvent</code>会返回<code>bEvent</code>，这就说我们说的处理完一件事件再返回一件事件的例子了。</p>
-<p>在 <code>main</code> 函数中，我们新起一个 <code>Instance</code> 实例，并初始化里面的 <code>manager</code> ，把 <code>manager</code> 的 <code>receiver</code> 设置为自己，因为是 <code>Instance</code> 实现了 <code>ProcessEvent</code> 方法，所以说谁实现了 <code>ProcessEvent</code> 方法， <code>SetReceiver</code> 就设置为谁，最后再用 <code>Start</code> 起一个goroutine不断地处理接收进行的事件。</p>
-<p>在我们向manager管理的事件队列中插入一个 <code>aEvent</code> 事件后， <code>eventLoop</code> 就会开始处理事件，命令行中应该会依次输出：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Received A Event, return B Event</span><br><span class="line">Received B Event, return C Event</span><br><span class="line">Received C Event, return nil</span><br></pre></td></tr></table></figure>
-<p>这个事件处理引擎的实现非常精妙，还是希望读者可以反复阅读几次。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/26/FactoryPattern/index.html b/2018/04/26/FactoryPattern/index.html
deleted file mode 100644
index fab1eea..0000000
--- a/2018/04/26/FactoryPattern/index.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Factory Pattern | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="工厂模式是设计模式里面的一种，具体点属于创建模式（creational pattern），它提供了一种创建对象的最佳方式。与传统的new来进行初始化对象不同，工厂模式在初始化对象时不会向客户端暴露创建的逻辑，也就减少了出错时到处修改的麻烦，工厂方法虽然稍为增加了程序猿的工作量，但会给系统带来更大的可拓展性和尽量少的修改。 下面我们来看一下如何使用工厂模式，工厂模式有几个要点，掌握住了几个要点，就可">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Factory Pattern">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/26/FactoryPattern/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="工厂模式是设计模式里面的一种，具体点属于创建模式（creational pattern），它提供了一种创建对象的最佳方式。与传统的new来进行初始化对象不同，工厂模式在初始化对象时不会向客户端暴露创建的逻辑，也就减少了出错时到处修改的麻烦，工厂方法虽然稍为增加了程序猿的工作量，但会给系统带来更大的可拓展性和尽量少的修改。 下面我们来看一下如何使用工厂模式，工厂模式有几个要点，掌握住了几个要点，就可">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:30.661Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Factory Pattern">
-<meta name="twitter:description" content="工厂模式是设计模式里面的一种，具体点属于创建模式（creational pattern），它提供了一种创建对象的最佳方式。与传统的new来进行初始化对象不同，工厂模式在初始化对象时不会向客户端暴露创建的逻辑，也就减少了出错时到处修改的麻烦，工厂方法虽然稍为增加了程序猿的工作量，但会给系统带来更大的可拓展性和尽量少的修改。 下面我们来看一下如何使用工厂模式，工厂模式有几个要点，掌握住了几个要点，就可">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-FactoryPattern"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Factory Pattern
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-26T15:27:24.000Z" itemprop="datePublished">
-        Apr 26, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>工厂模式是设计模式里面的一种，具体点属于创建模式（creational pattern），它提供了一种创建对象的最佳方式。与传统的new来进行初始化对象不同，工厂模式在初始化对象时不会向客户端暴露创建的逻辑，也就减少了出错时到处修改的麻烦，工厂方法虽然稍为增加了程序猿的工作量，但会给系统带来更大的可拓展性和尽量少的修改。</p>
-<p>下面我们来看一下如何使用工厂模式，工厂模式有几个要点，掌握住了几个要点，就可以轻松写代码了。</p>
-<ul>
-<li>Creator: 申明我们的工厂方法，会返回抽象的Product</li>
-<li>Product: 申明我们的工厂方法会返回的东西</li>
-<li>Concrete Creator: 具体的工厂，返回一个特定的Product或者说是Concrete Product</li>
-<li>Concrete Product: 具体的Product的实现</li>
-</ul>
-<p>我们以实现一个制造电脑组件的工厂方法作为例子来深入了解一下工厂模式的使用吧，我们的工厂会生产鼠标，键盘，显示器这三种组件，我们把工厂定义为接口 <code>Factory</code> ，而生产的产品定义为 <code>Product</code> 。<code>Factory</code>  通过 <code>Create()</code> 来生产 <code>Product</code> ，这就是工厂方法的精髓所在。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Factory <span class="keyword">interface</span> &#123;</span><br><span class="line">    Create(spec Spec) Component</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Component <span class="keyword">interface</span> &#123;</span><br><span class="line">    Make(io.Writer) error</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Spec <span class="keyword">struct</span> &#123;</span><br><span class="line">    MadeIn <span class="keyword">string</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面我们都实现了三种产品，分别是 <code>Mouse</code> ，<code>Keyboard</code> 和 <code>Screen</code> 。注意到他们都实现了 <code>Component</code> 接口，说明它们都是电脑的组件。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Mouse <span class="keyword">struct</span> &#123;</span><br><span class="line">    MadeIn    <span class="keyword">string</span></span><br><span class="line">    Bluetooth <span class="keyword">bool</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mouse)</span> <span class="title">Make</span><span class="params">(w io.Writer)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    _, err := fmt.Fprintf(w, <span class="string">"The mouse is made in %s, and bluetooth enabled is %v\n"</span>, m.MadeIn, m.Bluetooth)</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Keyboard <span class="keyword">struct</span> &#123;</span><br><span class="line">    MadeIn    <span class="keyword">string</span></span><br><span class="line">    Bluetooth <span class="keyword">bool</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(k *Keyboard)</span> <span class="title">Make</span><span class="params">(w io.Writer)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    _, err := fmt.Fprintf(w, <span class="string">"The Keyboard is made in %s, and bluetooth enabled is %v\n"</span>, k.MadeIn, k.Bluetooth)</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Screen <span class="keyword">struct</span> &#123;</span><br><span class="line">    MadeIn     <span class="keyword">string</span></span><br><span class="line">    Resolution <span class="keyword">uint64</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Screen)</span> <span class="title">Make</span><span class="params">(w io.Writer)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    _, err := fmt.Fprintf(w, <span class="string">"The Screen is made in %s, And the resolution is %d\n"</span>, s.MadeIn, s.Resolution)</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>然后我们定义具体的工厂，来生产具体的电脑组件，<code>MouseFactory</code> ，<code>KeyboardFactory</code> 和 <code>ScreenFactory</code> 都实现了 <code>Factory</code> 接口，并且返回具体的 <code>Component</code> 例如 <code>Mouse</code> ，<code>Keyboard</code> 和 <code>Screen</code> 。也就是说让子类决定实例化哪一个工厂类，工厂模式使得其创建过程延迟到子类，当然这里说子类并不是特别恰当，毕竟golang里没有类的概念。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> MouseFactory <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(mf *MouseFactory)</span> <span class="title">Create</span><span class="params">(spec Spec)</span> <span class="title">Component</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Mouse&#123;</span><br><span class="line">        MadeIn:    <span class="string">"China"</span>,</span><br><span class="line">        Bluetooth: <span class="literal">true</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> KeyboardFactory <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(kf *KeyboardFactory)</span> <span class="title">Create</span><span class="params">(spec Spec)</span> <span class="title">Component</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Keyboard&#123;</span><br><span class="line">        MadeIn:    <span class="string">"China"</span>,</span><br><span class="line">        Bluetooth: <span class="literal">false</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ScreenFactory <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(sf *ScreenFactory)</span> <span class="title">Create</span><span class="params">(spec Spec)</span> <span class="title">Component</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Screen&#123;</span><br><span class="line">        MadeIn: <span class="string">"China"</span>,</span><br><span class="line">        Resolution: <span class="number">4000000</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Computer</code> 这个结构体包含了不同的工厂，这就可以让我们自定义<code>Computer</code> 所包含的内容。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Computer <span class="keyword">struct</span> &#123;</span><br><span class="line">    ComponentFactories []Factory</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Computer)</span> <span class="title">Make</span><span class="params">(w io.Writer)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    spec := Spec&#123;</span><br><span class="line">        MadeIn: <span class="string">"China"</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> _, err := fmt.Fprintln(w, <span class="string">"Computer Manufacture Begin"</span>); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> _, factory := <span class="keyword">range</span> c.ComponentFactories &#123;</span><br><span class="line">        component := factory.Create(spec)</span><br><span class="line">        <span class="keyword">if</span> err := component.Make(w); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> err</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    _, err := fmt.Fprintln(<span class="string">"Computer Manufacture Done"</span>)</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>注意到通过工厂模式来产生实例时非常简单，因为我们之前已经把代码封装好了，这样就减少了出现错误或者业务需求改变时修改代码的机会了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">c := &amp;Computer&#123;</span><br><span class="line">    ComponentFactories: []Factory&#123;</span><br><span class="line">        &amp;MouseFactory&#123;&#125;,</span><br><span class="line">        &amp;ScreenFactory&#123;&#125;,</span><br><span class="line">        &amp;KeyboardFactory&#123;&#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">c.Make(os.Stdout)</span><br></pre></td></tr></table></figure>
-<p>工厂方法是实现代码去耦合的非常精妙的一种方法，希望读者可以仔细品味并加以掌握。如果下次你的项目中需要在很多地方初始化相同的对象，你可以抛弃传统的new方法而转向使用工厂模式来新建对象。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/26/LeakyBuffer/index.html b/2018/04/26/LeakyBuffer/index.html
deleted file mode 100644
index 0162d9f..0000000
--- a/2018/04/26/LeakyBuffer/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Leaky Buffer | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在科学上网服务中，客户端不断地向shadowsocks服务器发送数据，服务器从网络中读取经过加密的数据然后进行解密操作，为了避免重复的分配内存和释放内存操作，我们引入 LeakyBuffer 这种编程模型，LeakyBuffer 通常也被叫做 LeakyBucket ，或者说是漏桶模型。LeakyBuffer 维护了固定个数个字节数组（free list），如果我们的程序需要使用内存， 那么它会从">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Leaky Buffer">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/26/LeakyBuffer/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在科学上网服务中，客户端不断地向shadowsocks服务器发送数据，服务器从网络中读取经过加密的数据然后进行解密操作，为了避免重复的分配内存和释放内存操作，我们引入 LeakyBuffer 这种编程模型，LeakyBuffer 通常也被叫做 LeakyBucket ，或者说是漏桶模型。LeakyBuffer 维护了固定个数个字节数组（free list），如果我们的程序需要使用内存， 那么它会从">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:33.913Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Leaky Buffer">
-<meta name="twitter:description" content="在科学上网服务中，客户端不断地向shadowsocks服务器发送数据，服务器从网络中读取经过加密的数据然后进行解密操作，为了避免重复的分配内存和释放内存操作，我们引入 LeakyBuffer 这种编程模型，LeakyBuffer 通常也被叫做 LeakyBucket ，或者说是漏桶模型。LeakyBuffer 维护了固定个数个字节数组（free list），如果我们的程序需要使用内存， 那么它会从">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-LeakyBuffer"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Leaky Buffer
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-26T06:21:24.000Z" itemprop="datePublished">
-        Apr 26, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在科学上网服务中，客户端不断地向shadowsocks服务器发送数据，服务器从网络中读取经过加密的数据然后进行解密操作，为了避免重复的分配内存和释放内存操作，我们引入 <code>LeakyBuffer</code> 这种编程模型，<code>LeakyBuffer</code> 通常也被叫做 <code>LeakyBucket</code> ，或者说是漏桶模型。<code>LeakyBuffer</code> 维护了固定个数个字节数组（free list），如果我们的程序需要使用内存， 那么它会从 <code>LeakyBuffer</code> 维护的 <code>freelist</code> 去拿，如果 <code>freelist</code> 中没有了，则再重新make一个，当程序使用完了这段内存，不像通常那么被golang的runtime进行垃圾回收操作，我们把它重新放回 <code>LeakyBuffer</code> 维护的 <code>freelist</code> 中。</p>
-<p>下面我们来看一下 <code>Leaky Buffer</code> 的实现吧。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> leakyBufferSize = <span class="number">4096</span></span><br><span class="line"><span class="keyword">const</span> maxNum = <span class="number">2048</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> LeakyBuffer <span class="keyword">struct</span> &#123;</span><br><span class="line">    bufferSize  <span class="keyword">int</span></span><br><span class="line">    freeList <span class="keyword">chan</span> []<span class="keyword">byte</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>LeakyBuffer</code> 的实现非常简单，它主要维护了两个变量，一就是每个 <code>buffer</code>  的大小，而就是一个 <code>freelist</code> ，真正用于维护我们的内存。</p>
-<p>在上面的代码中我们定义每个 <code>buffer</code> 的大小是4096，这里的单位是字节，<code>freelist</code> 的长度是2048，所以我们这个 <code>LeakyBuffer</code> 总共可以使用的内存大小就是 4096 * 2048 B 也就是 8MB ，这对于一般的网络应用已经足够了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> leakyBuf = NewLeakyBuffer(maxNum, leakyBufferSize)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewLeakyBuffer</span><span class="params">(n, bufSize <span class="keyword">int</span>)</span> *<span class="title">LeakyBuffer</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;LeakyBuffer&#123;</span><br><span class="line">        bufferSize: bufSize,</span><br><span class="line">        freeList: <span class="built_in">make</span>(<span class="keyword">chan</span> []<span class="keyword">byte</span>, n)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>NewLeakyBuffer</code> 返回一个 <code>LeakyBuffer</code> 指针，它维护的 <code>freelist</code>  就是一个容量为n的通道。</p>
-<p>下面我们来看看如何使用 <code>LeakyBuffer</code> ，<code>LeakyBuffer</code> 只定义了两种操作，存和取。</p>
-<h2 id="取操作"><a href="#取操作" class="headerlink" title="取操作"></a>取操作</h2><p><code>Get</code> 操作从 <code>LeakyBuffer</code> 所维护的 <code>freelist</code> 的通道中取出一个字节数组，如果 <code>freelist</code> 为空，则说明没有多余的空闲字节数组，则自己make一个字节数组然后返回。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(lb *LeakyBuffer)</span> <span class="title">Get</span><span class="params">()</span> <span class="params">(b []<span class="keyword">byte</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> b := &lt;- lb.freeList:</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, lb.bufferSize)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="存操作"><a href="#存操作" class="headerlink" title="存操作"></a>存操作</h2><p>当程序使用完了这段内存空间后，我们将它重新放回 <code>LeakyBuffer</code> 中进行回收而不是用 <code>golang runtime</code> 进行垃圾回收，注意一种特殊情况，就是当 <code>freelist</code> 已经满了，这时我们会执行default case， 也就是什么事情也不干，然后这个无家可归的字节数组就会自动被系统进行垃圾回收，这就是 <code>LeakyBuffer</code> 这个名字中 Leaky 的由来，也就是有可能会泄漏出去。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(lb *LeakyBuffer)</span> <span class="title">Put</span><span class="params">(b []<span class="keyword">byte</span>)</span></span> &#123;</span><br><span class="line">     <span class="keyword">if</span> lb.bufferSize != <span class="built_in">len</span>(b) &#123;</span><br><span class="line">         <span class="built_in">panic</span>(<span class="string">"invalid buffer size that's put into leaky buffer"</span>)</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="keyword">select</span> &#123;</span><br><span class="line">     <span class="keyword">case</span> lb.freeList &lt;- b:</span><br><span class="line">     <span class="keyword">default</span>:</span><br><span class="line">     &#125;</span><br><span class="line">     <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上述就是 <code>LeakyBuffer</code> 的实现了，如果下次你遇到需要重复分配很多相同大小的内存空间时，不妨可以使用一下这个编程模型。</p>
-<h2 id="Golang-标准库的实现"><a href="#Golang-标准库的实现" class="headerlink" title="Golang 标准库的实现"></a>Golang 标准库的实现</h2><p>在 golang 标准库中也实现了类似于 <code>LeakyBuffer</code> 的接口，<code>sync.Pool</code> ，有兴趣的读者不妨阅读一下它的源码，这里就不再重复介绍了。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/27/EventTimer/index.html b/2018/04/27/EventTimer/index.html
deleted file mode 100644
index 953496f..0000000
--- a/2018/04/27/EventTimer/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Event Timer | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="还记得我们在 EventProcessEngine 里讲过的 Event Manager 吗，我们这里要实现的 Event Timer 其实和那个是有点耦合的，本篇博客与EventProcessEngine 是姊妹篇，如果没有看过的小伙伴建议先看上一篇再来看这一篇。 关于定时器，golang的标准库已经提供了一个免费的解决方案给我们了 。标准库里的 Timer 结构体里包含一个 &amp;lt;- cha">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Event Timer">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/27/EventTimer/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="还记得我们在 EventProcessEngine 里讲过的 Event Manager 吗，我们这里要实现的 Event Timer 其实和那个是有点耦合的，本篇博客与EventProcessEngine 是姊妹篇，如果没有看过的小伙伴建议先看上一篇再来看这一篇。 关于定时器，golang的标准库已经提供了一个免费的解决方案给我们了 。标准库里的 Timer 结构体里包含一个 &amp;lt;- cha">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:22.065Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Event Timer">
-<meta name="twitter:description" content="还记得我们在 EventProcessEngine 里讲过的 Event Manager 吗，我们这里要实现的 Event Timer 其实和那个是有点耦合的，本篇博客与EventProcessEngine 是姊妹篇，如果没有看过的小伙伴建议先看上一篇再来看这一篇。 关于定时器，golang的标准库已经提供了一个免费的解决方案给我们了 。标准库里的 Timer 结构体里包含一个 &amp;lt;- cha">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-EventTimer"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Event Timer
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-27T06:47:24.000Z" itemprop="datePublished">
-        Apr 27, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>还记得我们在 <a href="EventProcessEngine.md">EventProcessEngine</a> 里讲过的 <code>Event Manager</code> 吗，我们这里要实现的 <code>Event Timer</code> 其实和那个是有点耦合的，本篇博客与<a href="EventProcessEngine.md">EventProcessEngine</a> 是姊妹篇，如果没有看过的小伙伴建议先看上一篇再来看这一篇。</p>
-<p>关于定时器，golang的标准库已经提供了一个免费的解决方案给我们了 。标准库里的 <code>Timer</code> 结构体里包含一个 <code>&lt;- chan Time</code> 通道，在经历过一定的时间后，该通道就会返回，这样就达到了倒计时的目的，当然还有一个 <code>Reset</code> 方法用于重置我们的定时器。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Timer <span class="keyword">struct</span> &#123;</span><br><span class="line">    C &lt;- <span class="keyword">chan</span> Time</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">AfterFunc</span><span class="params">(d Duration, f <span class="keyword">func</span>()</span>) *<span class="title">Timer</span> </span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">NewTimer</span><span class="params">(d Duration)</span> *<span class="title">Timer</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(t *Timer)</span> <span class="title">Reset</span><span class="params">(d Duration)</span> <span class="title">bool</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(t *Timer)</span> <span class="title">Stop</span><span class="params">()</span> <span class="title">bool</span></span></span><br></pre></td></tr></table></figure>
-<p>那么为什么要实现一个自己的定时器呢，当然是觉得官方提供的不够用啦。</p>
-<p>先说一说我们的 <code>EventTimer</code> 会在哪里用到，例如在分布式系统中，主节点需要向从节点周期性发送心跳消息，以期望从节点可以判定主节点有没有出现宕机之类的故障，所以每个从节点都需要设置一个心跳超时的定时器，如果在规定的时间内，从节点接收到了来自主节点的心跳消息，那么从节点将定时器重置，如果没有收到，那么从节点会发起申请成为主节点的请求。</p>
-<p>下面例举几个在PBFT算法中定义的几个定时器超时的事件。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// viewChangeTimerEvent is sent when the view change timer expires</span></span><br><span class="line"><span class="keyword">type</span> viewChangeTimerEvent <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// viewChangeResendTimerEvent is sent when the view change resend timer expires</span></span><br><span class="line"><span class="keyword">type</span> viewChangeResendTimerEvent <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// batchTimerEvent is sent when the batch timer expires</span></span><br><span class="line"><span class="keyword">type</span> batchTimerEvent <span class="keyword">struct</span>&#123;&#125;</span><br></pre></td></tr></table></figure>
-<p>所以我们接下来需要实现的定时器需要有两个功能，第一点就是老功能，定时操作，第二点是增加的新功能，当定时器超时将我们预设好的事件发送给我们的事件管理器（Event Manager）作进一步处理。</p>
-<p>首先，我们来定义一下我们自己实现的 <code>Timer</code> 需要实现的接口，作为一个定时器，第一要务肯定是定时了，所以我们需要它有倒计时的功能，当倒计时结束我们发送事先定义好的事件给我们的事件管理器（Event Manager），第二点我们需要在不需要它的时候随时停止它。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Event <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Timer <span class="keyword">interface</span> &#123;</span><br><span class="line">    SoftReset(timeout time.Duration, event Event)</span><br><span class="line">    Reset(timeout time.Duration, event Event)</span><br><span class="line">    Stop()</span><br><span class="line">    Halt()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> threaded <span class="keyword">struct</span> &#123;</span><br><span class="line">    exit <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> timerImpl <span class="keyword">struct</span> &#123;</span><br><span class="line">    threaded </span><br><span class="line">    timerChan &lt;- <span class="keyword">chan</span> time.Time</span><br><span class="line">    startChan <span class="keyword">chan</span> *timerStart</span><br><span class="line">    stopChan  <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    manager   Manager</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> timerStart <span class="keyword">struct</span> &#123;</span><br><span class="line">    hard     <span class="keyword">bool</span></span><br><span class="line">    event    Event</span><br><span class="line">    duration time.Duration</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">newTimer</span><span class="params">(manager Manager)</span> <span class="title">Timer</span></span> &#123;</span><br><span class="line">    et := &amp;timerImpl&#123;</span><br><span class="line">        threaded:  threaded&#123;<span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)&#125;,</span><br><span class="line">        startChan: <span class="built_in">make</span>(<span class="keyword">chan</span> *timerStart),</span><br><span class="line">        stopChan:  <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;),</span><br><span class="line">        manager: manager,</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">go</span> et.loop()</span><br><span class="line">    <span class="keyword">return</span> et</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>interface <code>Timer</code> 中的 <code>Reset</code> 和 <code>SoftReset</code> 方法的功能都是让定时器重新开始倒计时，倒计时结束向我们的事件管理器发送事件，然后由事件管理器对我们的事件进行集中处理。它们之间的区别就是 <code>Reset</code> 会清除掉之前所有定时的事件，而 <code>SoftReset</code> 则不会，<code>Stop</code> 和 <code>Halt</code> 则非常简单，就是停止定时器，但<code>Stop</code> 会清除掉所有定时的事件。</p>
-<p><code>timerImpl</code>  实现了 <code>Timer</code> 接口，这里就可以清楚地看到 <code>Reset</code> 和 <code>SoftReset</code> 就是向 <code>startChan</code> 中发送我们的倒计时事件，也就是和我们的定时器申明，在 <code>timeout</code> 这么长的时间后，发射一个 <code>event</code> 事件。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *timerImpl)</span> <span class="title">Reset</span><span class="params">(timeout time.Duration, event Event)</span></span> &#123;</span><br><span class="line">    t.startChan &lt;- &amp;timerStart&#123;</span><br><span class="line">        duration: timeout,</span><br><span class="line">        event: event,</span><br><span class="line">        hard: <span class="literal">true</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *timerImpl)</span> <span class="title">SoftReset</span><span class="params">(timeout time.Duration, event Event)</span></span> &#123;</span><br><span class="line">     t.startChan &lt;- &amp;timerStart&#123;</span><br><span class="line">         duration: timeout,</span><br><span class="line">         event: event,</span><br><span class="line">         hard: <span class="literal">false</span>,</span><br><span class="line">     &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *timerImpl)</span> <span class="title">Stop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    et.stopChan &lt;- <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *timerImpl)</span> <span class="title">Halt</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> &lt;-t.threaded.exit:</span><br><span class="line">        logger.Warning(<span class="string">"Attempted to halt a threaded object twice"</span>)</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        <span class="built_in">close</span>(t.threaded.exit)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>接下来我们用工厂模式来新建我们的 <code>Timer</code>， 使用工厂模式有很多好处，我们会在另一篇博客中详细讲述它的用法和好处。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> TimerFactory <span class="keyword">interface</span> &#123;</span><br><span class="line">    CreateTimer() Timer</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> timerFactoryImpl <span class="keyword">struct</span> &#123;</span><br><span class="line">    manager Manager</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewTimerFactory</span><span class="params">(manager Manager)</span> <span class="title">TimerFactory</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;timerFactoryImpl(manager)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(etf *timerFactoryImpl)</span> <span class="title">CreateTimer</span><span class="params">()</span> <span class="title">Timer</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> newTimer(etf.manager)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>最后我们来看一下定时器最核心的函数 <code>loop()</code> 的实现。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(et *timerImpl)</span> <span class="title">loop</span><span class="params">()</span></span> &#123;</span><br><span class="line">	<span class="keyword">var</span> eventDestChan <span class="keyword">chan</span>&lt;- Event</span><br><span class="line">	<span class="keyword">var</span> event Event</span><br><span class="line"></span><br><span class="line">	<span class="keyword">for</span> &#123;</span><br><span class="line">		<span class="comment">// A little state machine, relying on the fact that nil channels will block on read/write indefinitely</span></span><br><span class="line"></span><br><span class="line">		<span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="comment">// case 1.</span></span><br><span class="line">		<span class="keyword">case</span> start := &lt;-et.startChan:</span><br><span class="line">			<span class="keyword">if</span> et.timerChan != <span class="literal">nil</span> &#123;</span><br><span class="line">				<span class="keyword">if</span> start.hard &#123;</span><br><span class="line">					logger.Debug(<span class="string">"Resetting a running timer"</span>)</span><br><span class="line">				&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">					<span class="keyword">continue</span></span><br><span class="line">				&#125;</span><br><span class="line">			&#125;</span><br><span class="line">			logger.Debug(<span class="string">"Starting timer"</span>)</span><br><span class="line">			et.timerChan = time.After(start.duration)</span><br><span class="line">			<span class="keyword">if</span> eventDestChan != <span class="literal">nil</span> &#123;</span><br><span class="line">				logger.Debug(<span class="string">"Timer cleared pending event"</span>)</span><br><span class="line">			&#125;</span><br><span class="line">			event = start.event</span><br><span class="line">			eventDestChan = <span class="literal">nil</span></span><br><span class="line">    <span class="comment">// case 2.</span></span><br><span class="line">		<span class="keyword">case</span> &lt;-et.stopChan:</span><br><span class="line">			<span class="keyword">if</span> et.timerChan == <span class="literal">nil</span> &amp;&amp; eventDestChan == <span class="literal">nil</span> &#123;</span><br><span class="line">				logger.Debug(<span class="string">"Attempting to stop an unfired idle timer"</span>)</span><br><span class="line">			&#125;</span><br><span class="line">			et.timerChan = <span class="literal">nil</span></span><br><span class="line">			logger.Debug(<span class="string">"Stopping timer"</span>)</span><br><span class="line">			<span class="keyword">if</span> eventDestChan != <span class="literal">nil</span> &#123;</span><br><span class="line">				logger.Debug(<span class="string">"Timer cleared pending event"</span>)</span><br><span class="line">			&#125;</span><br><span class="line">			eventDestChan = <span class="literal">nil</span></span><br><span class="line">			event = <span class="literal">nil</span></span><br><span class="line">    <span class="comment">// case 3.</span></span><br><span class="line">		<span class="keyword">case</span> &lt;-et.timerChan:</span><br><span class="line">			logger.Debug(<span class="string">"Event timer fired"</span>)</span><br><span class="line">			et.timerChan = <span class="literal">nil</span></span><br><span class="line">			eventDestChan = et.manager.Queue()</span><br><span class="line">    <span class="comment">// case 4.</span></span><br><span class="line">		<span class="keyword">case</span> eventDestChan &lt;- event:</span><br><span class="line">			logger.Debug(<span class="string">"Timer event delivered"</span>)</span><br><span class="line">			eventDestChan = <span class="literal">nil</span></span><br><span class="line">    <span class="comment">// case 5.</span></span><br><span class="line">		<span class="keyword">case</span> &lt;-et.exit:</span><br><span class="line">			logger.Debug(<span class="string">"Halting timer"</span>)</span><br><span class="line">			<span class="keyword">return</span></span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>虽然又一点恐怖，还是一步一步来吧。</p>
-<p>首先，说一下大致的思路，<code>loop()</code> 方法在开头定义了 <code>eventDestChan</code> 通道变量和 <code>event</code> 变量分别用于记录事件发送的目的地和事件本身。<code>loop()</code> 方法使用 <code>for select</code> 机制去轮询 <code>timerImpl</code> 中定义的几个通道。并且5个case条件中都是等待从通道中读取数据，2和5都是非正常流程，而1，3，4则是正常的流程。我们先从非正常流程说起。</p>
-<p>当程序某处调用 <code>Stop()</code> 方法时，<code>stopChan</code> 里就会有数据 <code>struct{}</code> ，<code>case 2</code> 就会被执行，我们分别将<code>timerChan</code>，<code>eventDstChan</code>，<code>event</code> 设置为nil就可以达到暂停的目的了，非常简单。</p>
-<p>当程序某处调用 <code>Halt()</code> 方法时，同样道理， <code>case 5</code> 会被执行，整个定时器将会被暂停，然后返回，这里也没有什么难度。</p>
-<p>接下来我们来捋一捋正常的流程也就是倒计时结束时发射事件的流程。一般来说正常的流程无非是程序某处调用了 <code>Reset()</code> 或者 <code>SoftReset()</code> 方法，那么我们的 <code>startChan</code> 里面就会有一个 <code>timerStart</code> 结构体，此时 <code>case 1</code> 就会被执行，然后判断当前时候是否有正在倒计时的时间，如果有并且新事件为hard，那么我们可以重置之前的倒计时，如果不是，则进入下一个for循环中。之后我们通过设置 <code>et.timerChan = time.After(start.duration)</code> 来真正开始倒计时，并且设置倒计时结束后要发生的event，但此时 <code>eventDestChan</code> 仍应设置为nil，毕竟倒计时还没有结束呢，超时事件不能马上发射。</p>
-<p>5，4， 3， 2， 1，眼瞧着我们之前设置好的倒计时结束了，那么我们的 <code>case 3</code> 就会被紧接着执行了，倒计时结束，说明超时事件已经触发了，但是现在我们超时事件究竟应该发送给谁还不知道，通过设置 <code>eventDestChan = et.manager.Queue()</code> 就将我们的事件目的地设置为我们的事件管理器，然后通过设置 <code>et.timerChan = nil</code> 就可以暂停我们的定时器了。</p>
-<p>执行完 <code>case 3</code>， 注意到我们现在 <code>event</code> 和 <code>eventDstChan</code> 都已经不为nil了，那么终于可以执行我们的 <code>case 4</code> 了，此处才真正地将我们的超时事件发送给我们的事件处理的目的地，之后的流程就交给我们的事件管理器（Event Manager）来处理啦。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/27/MerkleTree/index.html b/2018/04/27/MerkleTree/index.html
deleted file mode 100644
index 40bcde2..0000000
--- a/2018/04/27/MerkleTree/index.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Merkle Tree | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Merkle Tree 在各个领域都有着广泛的应用，就拿我们熟悉的 bittorrent 来举例，在我们使用 bittorrent 下载的时候，客户端会向许多并不信任的节点去下载目标文件的某个片段，利用 Merkle proofs 我们就可以验证我们下载的部分片段是否属于整个文件的一部分。Merkle proofs 可以用于验证某个数据子集是否从属于更大的集合。 那么下面我们来看一下如何实现一个">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Merkle Tree">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/27/MerkleTree/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Merkle Tree 在各个领域都有着广泛的应用，就拿我们熟悉的 bittorrent 来举例，在我们使用 bittorrent 下载的时候，客户端会向许多并不信任的节点去下载目标文件的某个片段，利用 Merkle proofs 我们就可以验证我们下载的部分片段是否属于整个文件的一部分。Merkle proofs 可以用于验证某个数据子集是否从属于更大的集合。 那么下面我们来看一下如何实现一个">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:59.699Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Merkle Tree">
-<meta name="twitter:description" content="Merkle Tree 在各个领域都有着广泛的应用，就拿我们熟悉的 bittorrent 来举例，在我们使用 bittorrent 下载的时候，客户端会向许多并不信任的节点去下载目标文件的某个片段，利用 Merkle proofs 我们就可以验证我们下载的部分片段是否属于整个文件的一部分。Merkle proofs 可以用于验证某个数据子集是否从属于更大的集合。 那么下面我们来看一下如何实现一个">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-MerkleTree"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Merkle Tree
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-27T04:18:24.000Z" itemprop="datePublished">
-        Apr 27, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><code>Merkle Tree</code> 在各个领域都有着广泛的应用，就拿我们熟悉的 <code>bittorrent</code> 来举例，在我们使用 <code>bittorrent</code> 下载的时候，客户端会向许多并不信任的节点去下载目标文件的某个片段，利用 <code>Merkle proofs</code> 我们就可以验证我们下载的部分片段是否属于整个文件的一部分。<code>Merkle proofs</code> 可以用于验证某个数据子集是否从属于更大的集合。</p>
-<p>那么下面我们来看一下如何实现一个 <code>Merkle Tree</code> 吧。与传统的二叉树类似，每个 <code>Merkle Tree</code> 中由许多节点组成，每个节点都指向它的左孩子节点，右孩子节点和父节点，同时，还有一个flag指明它是否为叶子结点等其他元信息。<code>Content</code> 是每个节点所存储的内容，只要实现了该接口 <code>Content</code> 的结构体都能被节点所存储。</p>
-<h2 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Node <span class="keyword">struct</span> &#123;</span><br><span class="line">    Parent *Node</span><br><span class="line">    Left   *Node</span><br><span class="line">    Right  *Node</span><br><span class="line">    leaf   <span class="keyword">bool</span></span><br><span class="line">    dup    <span class="keyword">bool</span></span><br><span class="line">    Hash   []<span class="keyword">byte</span></span><br><span class="line">    C      Content</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Content <span class="keyword">interface</span> &#123;</span><br><span class="line">    CalculateHash() []<span class="keyword">byte</span></span><br><span class="line">    Equals(other Content) <span class="keyword">bool</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> MerkleTree <span class="keyword">struct</span> &#123;</span><br><span class="line">    Root       *Node</span><br><span class="line">    merkleRoot []<span class="keyword">byte</span></span><br><span class="line">    Leafs      []*Node</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在 <code>Merkle Tree</code> 当中，有一个非常重要的特性就是获取节点的哈希值，我们来定义一个helper function 用于计算节点的哈希值。计算哈希分为两种情况，第一种就是如果当前被计算的节点为叶子结点，那么我们调用interface <code>Content</code> 中的 <code>CalculateHash</code> 方法来计算所存储内容的哈希值，如果不是叶子结点，则说明是中间层的节点，那么就计算左子节点和右子节点的哈希值的拼接值的哈希值，即 <code>H(P) = H( H(P.L) + H(P.R) )</code>。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">calculateNodeHash</span><span class="params">()</span> []<span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n.leaf &#123;</span><br><span class="line">        <span class="keyword">return</span> n.C.CalculateHash()</span><br><span class="line">    &#125;</span><br><span class="line">    h := sha256.New()</span><br><span class="line">    h.Write(<span class="built_in">append</span>(n.Left.Hash, n.Right.Hash...))</span><br><span class="line">    <span class="keyword">return</span> h.Sum(<span class="literal">nil</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="新建一棵树"><a href="#新建一棵树" class="headerlink" title="新建一棵树"></a>新建一棵树</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewTree</span><span class="params">(cs []Content)</span> <span class="params">(*MerkleTree, error)</span></span> &#123;</span><br><span class="line">    root, leafs, err := buildWithContent(cs)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    mk := &amp;MerkleTree&#123;</span><br><span class="line">        Root: root,</span><br><span class="line">        merkleRoot: root.Hash,</span><br><span class="line">        Leafs: leafs</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> mk, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">buildWithContent</span><span class="params">(cs []Content)</span> <span class="params">(*Node, []*Node, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(cs) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, <span class="literal">nil</span>, errors.New(<span class="string">"Error: cannot construct tree with no content"</span>)</span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="keyword">var</span> leafs []*Node</span><br><span class="line">    <span class="keyword">for</span> _, c := <span class="keyword">range</span> cs &#123;</span><br><span class="line">        leafs = <span class="built_in">append</span>(leafs, &amp;Node&#123;</span><br><span class="line">            Hash: c.CalculateHash(),</span><br><span class="line">            C: c,</span><br><span class="line">            leaf: <span class="literal">true</span>,</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(cs) % <span class="number">2</span> == <span class="number">1</span> &#123;</span><br><span class="line">        duplicate := &amp;Node&#123;</span><br><span class="line">            Hash: leafs[<span class="built_in">len</span>(leafs)<span class="number">-1</span>].Hash,</span><br><span class="line">            C: leafs[<span class="built_in">len</span>(leafs)<span class="number">-1</span>].C,</span><br><span class="line">            leaf: <span class="literal">true</span>,</span><br><span class="line">            dup: <span class="literal">true</span>,</span><br><span class="line">        &#125;</span><br><span class="line">        leafs = <span class="built_in">append</span>(leafs, duplicate)</span><br><span class="line">    &#125;</span><br><span class="line">    root := buildIntermediate(leafs)</span><br><span class="line">    <span class="keyword">return</span> root, leafs, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>buildIntermediate</code> 函数利用递归的方法建立树，递归在树的建立中是一种非常常用的套路，只需要特别关注一下它的退出条件就可以了，这里的退出条件就是最后仅剩两个节点了，说明已经可以返回根节点，那么函数执行到这里就可以返回了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">buildIntermediate</span><span class="params">(nl []*Node)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> nodes []*Node</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(nl); i += <span class="number">2</span> &#123;</span><br><span class="line">        h := sha256.New()</span><br><span class="line">        <span class="keyword">var</span> l, r <span class="keyword">int</span> = i, i+<span class="number">1</span></span><br><span class="line">        <span class="keyword">if</span> r == <span class="built_in">len</span>(nl) &#123;</span><br><span class="line">            r = <span class="built_in">len</span>(nl)<span class="number">-1</span></span><br><span class="line">        &#125;</span><br><span class="line">        h.Write(nl[l].Hash, nl[r].Hash...)</span><br><span class="line">        n := &amp;Node&#123;</span><br><span class="line">            Left:  nl[l],</span><br><span class="line">            Right: nl[r],</span><br><span class="line">            Hash:  h.Sum(<span class="literal">nil</span>),</span><br><span class="line">        &#125;</span><br><span class="line">        nodes = <span class="built_in">append</span>(nodes, n)</span><br><span class="line">        nl[l].Parent = n</span><br><span class="line">        nl[r].Parent = n</span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(nl) == <span class="number">2</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> n</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> buildIntermediate(nodes)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>只有当叶子结点的个数为 <code>2^n</code> 的时候，才能保证每一层的中节点都能两两配对，但一般来说叶子结点的个数不一定恰好为 <code>2^n</code> ，在这种情况下，就可以将每一层的最右边的结点进行自我复制，自己与自己配对然后再计算哈希值，上面的算法就采用了这样的解决方法。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">     ┌───┴──┐       ┌────┴───┐         ┌─────┴─────┐          ┌─────┴─────┐</span><br><span class="line">  ┌──┴──┐   │    ┌──┴──┐     │      ┌──┴──┐     ┌──┴──┐    ┌──┴──┐     ┌──┴──┐</span><br><span class="line">┌─┴─┐ ┌─┴─┐ │  ┌─┴─┐ ┌─┴─┐ ┌─┴─┐  ┌─┴─┐ ┌─┴─┐ ┌─┴─┐   │  ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ </span><br><span class="line">   (5-leaf)         (6-leaf)             (7-leaf)                (8-leaf)</span><br></pre></td></tr></table></figure>
-<h2 id="验证内容是否存在在-Merkle-Tree-中"><a href="#验证内容是否存在在-Merkle-Tree-中" class="headerlink" title="验证内容是否存在在 Merkle Tree 中"></a>验证内容是否存在在 Merkle Tree 中</h2><p>那么，我们又如何验证某个部分的内容是否真正存在于我们的 <code>MerkleTree</code> 中呢。具体的思路非常简单，就是遍历该树的叶子结点，看有没有与我们要验证的内容相一致的，如果没有则直接返回false，如果有则开始真正的验证阶段，验证的基本思路也不难，就是一个从叶子节点往根节点走并且验证这条路上的哈希值是否都正确的过程，先获取当前遍历的节点的父节点，然后判断父节点的左子节点和右子节点的哈希值是否相匹配，如果不匹配，则直接返回false，如果匹配，则继续验证知道根节点为止。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *MerkleTree)</span> <span class="title">VerifyContent</span><span class="params">(expectedMerkleRoot []<span class="keyword">byte</span>, content Content)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> _, l := <span class="keyword">range</span> m.Leafs &#123;</span><br><span class="line">        <span class="keyword">if</span> l.C.Content.Equals(content) &#123;</span><br><span class="line">            currentParent := l.Parent</span><br><span class="line">            <span class="keyword">for</span> currentParent != <span class="literal">nil</span> &#123;</span><br><span class="line">                h := sha256.New()</span><br><span class="line">               h.Write(<span class="built_in">append</span>(currentParent.Left.calculateNodeHash(), currentParent.Right.calculateNodeHash()...))  </span><br><span class="line">                <span class="keyword">if</span> bytes.Compare(h.Sum(<span class="literal">nil</span>), currentParent.Hash) != <span class="number">0</span> &#123;</span><br><span class="line">                    <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">                &#125; </span><br><span class="line">                currentParent = currentParent.Parent</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/29/BloomFilter/index.html b/2018/04/29/BloomFilter/index.html
deleted file mode 100644
index 914dfe5..0000000
--- a/2018/04/29/BloomFilter/index.html
+++ /dev/null
@@ -1,274 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Bloom Filter | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="当我们写爬虫应用的时候，有一件事情是值得我们仔细考虑的，在抓取网上数据的时候，我们的爬虫会沿着当前爬取的网页中的链接继续进行深度优先搜索或者广度优先搜索，但是很显然，这些链接形成的拓扑图肯定不是一个有向无环图，所以肯定会重复抓取某些网页，这肯定不是我们所想要的，为了避免重复抓取导致的返工，我们不加思索的增加了一个 map 来存储当前已经被抓取过的url，这在要求抓取的url数量较少的时候或许是一个">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Bloom Filter">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/29/BloomFilter/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="当我们写爬虫应用的时候，有一件事情是值得我们仔细考虑的，在抓取网上数据的时候，我们的爬虫会沿着当前爬取的网页中的链接继续进行深度优先搜索或者广度优先搜索，但是很显然，这些链接形成的拓扑图肯定不是一个有向无环图，所以肯定会重复抓取某些网页，这肯定不是我们所想要的，为了避免重复抓取导致的返工，我们不加思索的增加了一个 map 来存储当前已经被抓取过的url，这在要求抓取的url数量较少的时候或许是一个">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Bloom_filter.svg/649px-Bloom_filter.svg.png">
-<meta property="og:updated_time" content="2018-06-26T08:43:58.506Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Bloom Filter">
-<meta name="twitter:description" content="当我们写爬虫应用的时候，有一件事情是值得我们仔细考虑的，在抓取网上数据的时候，我们的爬虫会沿着当前爬取的网页中的链接继续进行深度优先搜索或者广度优先搜索，但是很显然，这些链接形成的拓扑图肯定不是一个有向无环图，所以肯定会重复抓取某些网页，这肯定不是我们所想要的，为了避免重复抓取导致的返工，我们不加思索的增加了一个 map 来存储当前已经被抓取过的url，这在要求抓取的url数量较少的时候或许是一个">
-<meta name="twitter:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Bloom_filter.svg/649px-Bloom_filter.svg.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-BloomFilter"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Bloom Filter
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-28T16:00:04.000Z" itemprop="datePublished">
-        Apr 29, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>当我们写爬虫应用的时候，有一件事情是值得我们仔细考虑的，在抓取网上数据的时候，我们的爬虫会沿着当前爬取的网页中的链接继续进行深度优先搜索或者广度优先搜索，但是很显然，这些链接形成的拓扑图肯定不是一个有向无环图，所以肯定会重复抓取某些网页，这肯定不是我们所想要的，为了避免重复抓取导致的返工，我们不加思索的增加了一个 <code>map</code> 来存储当前已经被抓取过的url，这在要求抓取的url数量较少的时候或许是一个不错的解决方案，但是一旦我们要抓取亿级别的url数量时（在现在这种自媒体爆发的时代还是很正常的一件事情），假设我们要抓取的url平均大小是20字节，那么不考虑其他开销，1亿个url需要消耗的内存就是20GB，这显然<br>是不现实的。我们需要一种更加优化的解决方案。</p>
-<p>上述的问题可以抽象为，给定一个元素E，问它是否存在于给定的集合S中，上述使用 <code>map</code> 的存储导致空间开销过大的主要原因就是我们需要存储原来的url，那有没有一种方法不存储每条消息而可以知晓它是否存在于特定的集合中呢，答案就是 <code>Bloom Filter</code>。</p>
-<p><code>Bloom Filter</code> 是一个空间和时间都非常高效的数据结构，它解决的问题也非常简单，就是用于查询特定元素是否存在于某个集合当中，但是这种高效是引入错误率的基础上的高效，下面我们引入 <code>BloomFilter</code> 的两个特性。</p>
-<ul>
-<li>False Positive </li>
-</ul>
-<p><code>Bloom Filter</code> 可能会出现 <code>False Positive</code> 的概率，就是指查询特定元素E是否存在于集合E中，真实情况是E不存在，但是 <code>Bloom Filter</code> 却出现了误判，当 <code>Bloom Filter</code> 存储的元素越多，出现误判的概率也就会越大（一般来说会把误判率控制在可以接受的范围内），这是由 <code>Bloom Filter</code> 本身的特性造成的。</p>
-<ul>
-<li>False Negative</li>
-</ul>
-<p><code>False Negative</code> 指的是元素E本来存在于集合S中，但是 <code>Bloom Filter</code>却出现误判，认为元素E并不存在于集合S中，这种情况是绝对不会出现的，这也是由<code>Bloom Filter</code> 本身的特性决定的。</p>
-<p><code>Bloom Filter</code>实现的思路非常简单，它主要由两个元素组成。</p>
-<ol>
-<li>一张位图，决定了 <code>BloomFilter</code> 在空间上是高效的。</li>
-<li>多个哈希函数，决定了 <code>BloomFilter</code> 是查询时间上是高效的，理论上的时间复杂度是 <code>O(1)</code>。</li>
-</ol>
-<p>下面这张图就大概描述了 <code>Bloom Filter</code> 实现的大致思路，我们来简单过一遍。</p>
-<p>假设当前由集合 <code>S: {x, y, z}</code> ，我们需要查询元素w是否存在于集合S中，第一步应该是位图的构建，位图开始是是一张全部为0的数组，当第一个元素x进入时，程序会通过 <code>Bloom Filter</code> 的所有哈希函数计算出哈希函数对应的哈希值，并将哈希值对应位图的相应位置都设置为1，y和z同理，也就是说此时位图的某些地方已经被设置为1了，但是其余地方都是0。此时我们需要查询元素w是否存在于集合S中，先利用 <code>Bloom Filter</code> 的所有哈希函数计算出相应的哈希值，并利用哈希值查询对应的位图中元素是否都为1，如果都为1，那么则说明元素w可能存在于该集合中，但是只要有一个位置为0，就可以直接判定该元素不存在于该集合中。</p>
-<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Bloom_filter.svg/649px-Bloom_filter.svg.png" alt="alt text"></p>
-<p>下面是 <code>Bloom Filter</code> 的简单实现，<code>bitmap</code> 就是位图，<code>k</code> 是哈希函数的个数，<code>n</code> 是当前存储的元素的个数，当然这里存储的意思并不是把整个元素存储下来，而是在位图中进行标记的意思，<code>m</code> 是整个 <code>Bloom Filter</code> 或者说位图的大小。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> BloomFilter <span class="keyword">struct</span> &#123;</span><br><span class="line">    bitmap []<span class="keyword">bool</span></span><br><span class="line">    k      <span class="keyword">int</span></span><br><span class="line">    n      <span class="keyword">int</span></span><br><span class="line">    m      <span class="keyword">int</span></span><br><span class="line">    hashfn hash.Hash64</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewBloomFilter</span><span class="params">(numHashFuncs, bfSize <span class="keyword">int</span>)</span> *<span class="title">BloomFilter</span></span> &#123;</span><br><span class="line">    bf := <span class="built_in">new</span>(BloomFilter)</span><br><span class="line">    bf.bitmap = <span class="built_in">make</span>([]<span class="keyword">bool</span>, bfSize)</span><br><span class="line">    bf.k, bf.m = numHashFuncs, bfSize</span><br><span class="line">    bf.n = <span class="number">0</span></span><br><span class="line">    bf.hashfn = fnv.New64()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>getHash</code> 就是利用 <code>Bloom Filter</code> 中事先定义的哈希函数计算对应的多个哈希值，这里可以挑选抗碰撞性较好的哈希函数来提高我们程序的鲁棒性。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(bf *BloomFilter)</span> <span class="title">getHash</span><span class="params">(b []<span class="keyword">byte</span>)</span> <span class="params">(<span class="keyword">uint32</span>, <span class="keyword">uint32</span>)</span></span> &#123;</span><br><span class="line">    bf.hashfn.Reset()</span><br><span class="line">    bf.hashfn.Write(b)</span><br><span class="line">    hash64 := bf.hashfn.Sum64()</span><br><span class="line">    h1 := <span class="keyword">uint32</span>(hash64 &amp; ((<span class="number">1</span> &lt;&lt; <span class="number">32</span>) - <span class="number">1</span>))</span><br><span class="line">    h2 := <span class="keyword">uint32</span>(hash64 &gt;&gt; <span class="number">32</span>)</span><br><span class="line">    <span class="keyword">return</span> h1, h2</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Add</code> 将元素 e 加入 <code>Bloom Filter</code> 中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(bf *BloomFilter)</span> <span class="title">Add</span><span class="params">(e []<span class="keyword">byte</span>)</span></span> &#123;</span><br><span class="line">    h1, h2 := bf.getHash(e)</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; bf.k; i++ &#123;</span><br><span class="line">        ind := (h1 + <span class="keyword">uint32</span>(i)*h2) % <span class="keyword">uint32</span>(bf.m)</span><br><span class="line">        bf.bitmap[ind] = <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">    bf.n++</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Check</code> 检查特定元素 e 是否存在于 <code>Bloom Filter</code> 中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(bf *BloomFilter)</span> <span class="title">Check</span><span class="params">(e []<span class="keyword">byte</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    h1, h2 := bf.getHash(e)</span><br><span class="line">    result := <span class="literal">true</span></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; bf.k; i++ &#123;</span><br><span class="line">        ind := (h1 + <span class="keyword">uint32</span>(i)*h2) % <span class="keyword">uint32</span>(bf.m)</span><br><span class="line">        result = result &amp; bf.bitmap[ind]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>函数 <code>FalsePositiveRate()</code> 可以计算 <code>Bloom Filter</code> 出现 <code>False Positive</code> 的概率，这个公式有严格的数学证明，有兴趣的同学可以参考一下它的证明过程，我们现在只需要掌握一点就可以了，就是它存储的元素个数（n）越多，它出现 <code>False Positive</code> 的概率也就越大。但只要调整合适的<code>m</code> 和 <code>k</code> 的值，就可以把错误率控制在可以接受的范围内。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(bf *BloomFilter)</span> <span class="title">FalsePositiveRate</span><span class="params">()</span> <span class="title">float64</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> math.Pow((<span class="number">1</span> - math.Exp(-<span class="keyword">float64</span>(bf.k*bf.n) / <span class="keyword">float64</span>(bf.m))), <span class="keyword">float64</span>(bf.k))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/29/TCP_IP/index.html b/2018/04/29/TCP_IP/index.html
deleted file mode 100644
index 4702b7b..0000000
--- a/2018/04/29/TCP_IP/index.html
+++ /dev/null
@@ -1,260 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>TCP/IP | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="网络是分布式系统之间通信的媒介，掌握网络编程自然变成了程序猿们居家旅行必备技能之一了，与直接使用应用层的 http 协议不同，我们一般使用传输层的协议例如 tcp 进行编程，掌握好了 tcp 编程，我们甚至能写一套类似http 这样的应用层协议，是不是很兴奋呢，那今天就让我们从最简单的例子出发，掌握 tcp/ip 编程的精髓吧。 一般来说大部分网络通信模型是 c/s 模型，也有部分是 p2p 模型">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="TCP&#x2F;IP">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/29/TCP_IP/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="网络是分布式系统之间通信的媒介，掌握网络编程自然变成了程序猿们居家旅行必备技能之一了，与直接使用应用层的 http 协议不同，我们一般使用传输层的协议例如 tcp 进行编程，掌握好了 tcp 编程，我们甚至能写一套类似http 这样的应用层协议，是不是很兴奋呢，那今天就让我们从最简单的例子出发，掌握 tcp/ip 编程的精髓吧。 一般来说大部分网络通信模型是 c/s 模型，也有部分是 p2p 模型">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:44.770Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="TCP&#x2F;IP">
-<meta name="twitter:description" content="网络是分布式系统之间通信的媒介，掌握网络编程自然变成了程序猿们居家旅行必备技能之一了，与直接使用应用层的 http 协议不同，我们一般使用传输层的协议例如 tcp 进行编程，掌握好了 tcp 编程，我们甚至能写一套类似http 这样的应用层协议，是不是很兴奋呢，那今天就让我们从最简单的例子出发，掌握 tcp/ip 编程的精髓吧。 一般来说大部分网络通信模型是 c/s 模型，也有部分是 p2p 模型">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TCP_IP"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      TCP/IP
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-29T11:56:04.000Z" itemprop="datePublished">
-        Apr 29, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>网络是分布式系统之间通信的媒介，掌握网络编程自然变成了程序猿们居家旅行必备技能之一了，与直接使用应用层的 <code>http</code> 协议不同，我们一般使用传输层的协议例如 <code>tcp</code> 进行编程，掌握好了 <code>tcp</code> 编程，我们甚至能写一套类似<code>http</code> 这样的应用层协议，是不是很兴奋呢，那今天就让我们从最简单的例子出发，掌握 <code>tcp/ip</code> 编程的精髓吧。</p>
-<p>一般来说大部分网络通信模型是 <code>c/s</code> 模型，也有部分是 <code>p2p</code> 模型，今天我们先了解一下 <code>c/s</code> 模型的编程使用吧。</p>
-<p>客户端要想与服务器通信，前提必须是服务器已经启动并且监听了某个端口了。如果服务器没有监听而客户端直接连接的话，就会报类似下面这样的错误：</p>
-<p><code>dial tcp 127.0.0.1:8080: connect: connection refused</code></p>
-<p>也就是说，服务器端要调用 <code>net.Listen</code> 接口对特定端口进行监听，监听会返回一个 <code>Listener</code> ，服务器一旦监听到来自客户端的请求，就会调用 <code>Accept</code> 来接受该请求，<code>Accept</code> 会返回一个 <code>net.Conn</code> ，以后服务器就可以使用 <code>net.Conn</code> 与客户端进行通信。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Listener <span class="keyword">interface</span> &#123;</span><br><span class="line">    Accept() (Conn, error)</span><br><span class="line">    Close() error</span><br><span class="line">    Addr() Addr</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Conn <span class="keyword">interface</span> &#123;</span><br><span class="line">    Read(b []<span class="keyword">byte</span>) (n <span class="keyword">int</span>, err error)</span><br><span class="line">    Write(b []<span class="keyword">byte</span>) (n <span class="keyword">int</span>, err error)</span><br><span class="line">    Close() error</span><br><span class="line">    LocalAddr() Addr</span><br><span class="line">    RemoteAddr() Addr</span><br><span class="line">    SetDeadline(t time.Time) error</span><br><span class="line">    SetReadDeadline(t time.Time) error</span><br><span class="line">    SetWriteDeadline(t time.Time) error</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="server-go"><a href="#server-go" class="headerlink" title="server.go"></a>server.go</h2><p>一般来说，服务器需要处理来自多个客户端的请求，所以我们使用goroutine来处理不同客户端的请求，这样就达到一个并发的目的。</p>
-<p>服务器处理客户端请求的主要的流程如下：<br><code>Listen =&gt; Accept =&gt; Read &amp; Write =&gt; Close</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main </span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"log"</span></span><br><span class="line">    <span class="string">"net"</span></span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">    <span class="string">"bufio"</span></span><br><span class="line">    <span class="string">"strings"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    fmt.Println(<span class="string">"Launching server..."</span>)</span><br><span class="line"></span><br><span class="line">    l, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">":8080"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> l.Close()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        conn, err := ln.Accept()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Fatal(err)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">go</span> handleConn(conn)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handleConn</span><span class="params">(c net.Conn)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        m, _ := bufio.NewReader(c).ReadString(<span class="string">'\n'</span>)</span><br><span class="line">        fmt.Print(<span class="string">"Message Received:"</span>, <span class="keyword">string</span>(m))</span><br><span class="line">        newMsg := strings.ToUpper(m)</span><br><span class="line">        c.Write([]<span class="keyword">byte</span>(newMsg + <span class="string">"\n"</span>))</span><br><span class="line">    &#125; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="client-go"><a href="#client-go" class="headerlink" title="client.go"></a>client.go</h2><p>一般来说连接都是由客户端主动发起的，客户端调用 <code>net.Dial</code> 向服务器发起连接行为，在正常情况下，则也返回一个 <code>net.Conn</code> ，注意到客户端和服务器都是通过 <code>net.Conn</code> 进行通信的，linux基础好的同学，就知道它的本质就是一个套接字（socket），而套接字的本质则是一个文件，所以我们可以对待正常文件一样去使用它，例如使用 <code>fmt.Fprintf</code> 来对套接字写入数据。</p>
-<p>主要的流程如下：<br><code>Dial =&gt; Read &amp; Write =&gt; Close</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"os"</span></span><br><span class="line">    <span class="string">"log"</span></span><br><span class="line">    <span class="string">"net"</span></span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">    <span class="string">"bufio"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    c, e := net.Dial(<span class="string">"tcp"</span>, <span class="string">"localhost:8080"</span>)</span><br><span class="line">    <span class="keyword">if</span> e != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(e)</span><br><span class="line">    &#125;</span><br><span class="line">    reader := bufio.NewReader(os.Stdin)</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        fmt.Print(<span class="string">"Text to send: "</span>)</span><br><span class="line">        text, err := reader.ReadString(<span class="string">'\n'</span>)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Fatal(err)</span><br><span class="line">        &#125;</span><br><span class="line">        fmt.Fprintf(c, text + <span class="string">"\n"</span>)</span><br><span class="line">        m, e := bufio.NewReader(c).ReadString(<span class="string">'\n'</span>)</span><br><span class="line">        <span class="keyword">if</span> e != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Fatal(e)</span><br><span class="line">        &#125;</span><br><span class="line">        fmt.Print(<span class="string">"Message from server: "</span> + m)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h2><p>先对两个源文件进行编译。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ go build *.go</span><br></pre></td></tr></table></figure></p>
-<p>在一个命令行中输入：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ./server</span><br></pre></td></tr></table></figure>
-<p>在另一个命令行中输入：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ./client</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/30/ConsistentHashing/index.html b/2018/04/30/ConsistentHashing/index.html
deleted file mode 100644
index 9aaa852..0000000
--- a/2018/04/30/ConsistentHashing/index.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Connection Hashing | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="比如说我们现在有3台服务器用于存储kv值，分别是 {s1, s2, s3} ，而我们用的哈希策略非常简单，例如 h(x) = ( x^2 + 3 * x + 2 ) % 3 ，也就是说当k=1时，对应的v值会被存放在s1上，但如果业务量增加，我们又需要增加一个服务器来均衡负载，此时哈希策略就变成 h(x) = ( x^2 + 3 * x + 2 ) % 4，那按照这种策略，当k=1的时候，应该是把">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Connection Hashing">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/30/ConsistentHashing/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="比如说我们现在有3台服务器用于存储kv值，分别是 {s1, s2, s3} ，而我们用的哈希策略非常简单，例如 h(x) = ( x^2 + 3 * x + 2 ) % 3 ，也就是说当k=1时，对应的v值会被存放在s1上，但如果业务量增加，我们又需要增加一个服务器来均衡负载，此时哈希策略就变成 h(x) = ( x^2 + 3 * x + 2 ) % 4，那按照这种策略，当k=1的时候，应该是把">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://dajh2p2mfq4ra.cloudfront.net/assets/site-images/system_design/consistent_hashing_virtual.jpg">
-<meta property="og:updated_time" content="2018-06-26T08:44:26.493Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Connection Hashing">
-<meta name="twitter:description" content="比如说我们现在有3台服务器用于存储kv值，分别是 {s1, s2, s3} ，而我们用的哈希策略非常简单，例如 h(x) = ( x^2 + 3 * x + 2 ) % 3 ，也就是说当k=1时，对应的v值会被存放在s1上，但如果业务量增加，我们又需要增加一个服务器来均衡负载，此时哈希策略就变成 h(x) = ( x^2 + 3 * x + 2 ) % 4，那按照这种策略，当k=1的时候，应该是把">
-<meta name="twitter:image" content="https://dajh2p2mfq4ra.cloudfront.net/assets/site-images/system_design/consistent_hashing_virtual.jpg">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ConsistentHashing"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Connection Hashing
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-30T10:59:24.000Z" itemprop="datePublished">
-        Apr 30, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>比如说我们现在有3台服务器用于存储kv值，分别是 <code>{s1, s2, s3}</code> ，而我们用的哈希策略非常简单，例如 <code>h(x) = ( x^2 + 3 * x + 2 ) % 3</code> ，也就是说当k=1时，对应的v值会被存放在s1上，但如果业务量增加，我们又需要增加一个服务器来均衡负载，此时哈希策略就变成 <code>h(x) = ( x^2 + 3 * x + 2 ) % 4</code>，那按照这种策略，当k=1的时候，应该是把对应的v值存放在s3上面，然而s3上面并没有存放，为了能够获取到k=1对应的v值，我们就需要将原来三台服务器上的数据做一个 <code>remapping</code> ，也就是说基本上所有的数据都要进行迁移，在小数据量的情况下这倒没什么问题，但是一旦数据量达到T级别，这种开销将是无法忍受的，所以，为了当增删节点时尽量少的数据迁移，我们可以利用一致性哈希这种非常神奇的算法。</p>
-<p>所谓一致性哈希，就是当相应的哈希表调整大小的时候（对应到现实生活中就是服务器增删节点），只有 <code>K/n</code> 个数据需要迁移，这里的 <code>K</code> 是指键的数量，而 <code>n</code>则是指所有的卡槽（对应服务器的数量），如果不用一致性哈希而是用传统的哈希表，当哈希表调整的时候，基本所有的键都要进行 <code>remapping</code>。</p>
-<p>一致性哈希有几个要点，第一个就是它所有的地址空间会形成一个环，例如它的地址空间是从 <code>[0, 2^32-1)</code> ，它的头部和尾部会进行拼接而形成一个环，还有就是虚节点的概念，例如下图中我们有<code>{s1, s2, s3, s4}</code>这四个节点，但每个节点都会有自己的拷贝（称为虚节点），然后这些复制过的节点群会根据特定的哈希算法分布在这个环上面，一般来说都是均匀分布的，而我们要存储的键值对，同样根据与节点相同的哈希算法，算出一个值后，顺时针（或者逆时针）去寻找与自己最近的虚节点的位置，找到最近的虚节点后，就将自己存放在对应的节点上，这就是实现一致性哈希的基本思路，下面就让我们来看一下一致性哈希算法的实现吧。</p>
-<p><img src="https://dajh2p2mfq4ra.cloudfront.net/assets/site-images/system_design/consistent_hashing_virtual.jpg" alt="alt text"></p>
-<h2 id="一致性哈希的实现"><a href="#一致性哈希的实现" class="headerlink" title="一致性哈希的实现"></a>一致性哈希的实现</h2><p>上面我们知道了一致性哈希的核心是一个环，环的地址空间假设是 <code>[0, 2^32-1)</code> ，我们可以用一个map记录虚节点对应的环上的位置，位置我们用一个uint32表示就可以了，因为是遍历map的时候是随机的，所以我们还需要一个数组来记录环上面虚节点的顺序。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> uints []<span class="keyword">uint32</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(x uints)</span> <span class="title">Len</span><span class="params">()</span> <span class="title">int</span></span> &#123; <span class="keyword">return</span> <span class="built_in">len</span>(x) &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(x uints)</span> <span class="title">Less</span><span class="params">(i, j <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123; <span class="keyword">return</span> x[i] &lt; x[j] &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(x uints)</span> <span class="title">Swap</span><span class="params">(i, j <span class="keyword">int</span>)</span></span> &#123; x[i], x[j] = x[j], x[i] &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Consistent <span class="keyword">struct</span> &#123;</span><br><span class="line">    circle <span class="keyword">map</span>[<span class="keyword">uint32</span>]<span class="keyword">string</span></span><br><span class="line">    sortedList uints</span><br><span class="line">    virtualNode <span class="keyword">int</span></span><br><span class="line">    sync.Mutex</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">()</span> *<span class="title">Consistent</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Consistent&#123;</span><br><span class="line">        circle: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">uint32</span>]<span class="keyword">string</span>),</span><br><span class="line">        sortedList: <span class="built_in">make</span>(uints, <span class="number">0</span>)</span><br><span class="line">        virtualNode: <span class="number">20</span>,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>虚节点相当于实节点的影分身，例如s2，s2复制为s2-1，s2-2，s2-3。这些原来的节点和复制出来的节点我们可以把它们形象地称为哨兵。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">KeyNum</span><span class="params">(key <span class="keyword">string</span>, num <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> key + <span class="string">":"</span> + fmt.Sprintf(<span class="string">"%d"</span>, num)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>要想把虚节点对应到一致性哈希的圆环上，我们还需要一个哈希函数用于把我们的哨兵和我们的键值对映射到环上面去。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">hashKey</span><span class="params">(key <span class="keyword">string</span> <span class="keyword">uint32</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(key) &lt; <span class="number">64</span> &#123;</span><br><span class="line">        scratch := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">64</span>)</span><br><span class="line">        <span class="built_in">copy</span>(scratch[:], key)</span><br><span class="line">        <span class="keyword">return</span> crc32.ChecksumIEEE(scratch[:<span class="built_in">len</span>(key)])</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> crc32.ChecksumIEEE([]<span class="keyword">byte</span>(key))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>之前说了，我们加入的键值对经过哈希后会在环上顺时针寻找离自己最近的虚节点的位置，因为我们之前已经用 <code>sortedList</code> 记录了节点在环上的相对顺序了，所以就可以利用二分法去查找对应虚节点的位置啦。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">search</span><span class="params">(key <span class="keyword">uint32</span>)</span> <span class="title">int</span></span> &#123;</span><br><span class="line">    i := sort.Search(<span class="built_in">len</span>(c.sortedList), <span class="function"><span class="keyword">func</span><span class="params">(x <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">        <span class="keyword">return</span> c.sortedList[x] &gt; key</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">if</span> i &gt;= <span class="built_in">len</span>(c.sortedList) &#123;</span><br><span class="line">        i = <span class="number">0</span></span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> i</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当然了，我们一致性哈希就牛逼的地方就在于当动态增删节点的时候，需要<code>remapping</code> 的键值对的数量比较少，动态增删节点无非也就是将该节点影分身后再经过哈希操作对应到环上或者进行相应的删除操作，当然还需要对我们的 <code>sortedList</code> 重新进行排序来对应增删的虚节点。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">Add</span><span class="params">(key <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    c.Lock()</span><br><span class="line">    <span class="keyword">defer</span> c.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> n := <span class="number">0</span>; n &lt; virtualNode; n++ &#123;</span><br><span class="line">        c.circle[c.hashKey(c.KeyNum(key, n))] = key</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    c.updateList()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">Remove</span><span class="params">(key <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    c.Lock()</span><br><span class="line">    <span class="keyword">defer</span> c.Unlock()</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">for</span> n := <span class="number">0</span>; n &lt; c.virtualNode; n++ &#123;</span><br><span class="line">        <span class="built_in">delete</span>(c.circle, c.hashKey(c.KeyNum(key, n)))</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    c.updateList()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">updateList</span><span class="params">()</span></span> &#123;</span><br><span class="line">    list := c.sortedList[:<span class="number">0</span>]</span><br><span class="line">    <span class="keyword">for</span> k, _ := <span class="keyword">range</span> c.circle &#123;</span><br><span class="line">        list = <span class="built_in">append</span>(list, k)</span><br><span class="line">    &#125; </span><br><span class="line">    sort.Sort(list)</span><br><span class="line">    c.sortedList = list</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>最后就是当我们新增一个键值对时，我们可以查找对应的节点。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Consistent)</span> <span class="title">Get</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(<span class="keyword">string</span>, error)</span></span> &#123;</span><br><span class="line">    c.Lock()</span><br><span class="line">    <span class="keyword">defer</span> c.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(c.circle) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>, errors.New(<span class="string">"empty consistent circle"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    key := c.hashKey(name)</span><br><span class="line">    i := c.search(key)</span><br><span class="line">    <span class="keyword">return</span> c.circle[c.sortedList[i]], <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/04/30/Crontab/index.html b/2018/04/30/Crontab/index.html
deleted file mode 100644
index ad26797..0000000
--- a/2018/04/30/Crontab/index.html
+++ /dev/null
@@ -1,265 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>crontab | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="事情的经过是这样子的，室友最近要做一个阿里的项目，大概就是利用软件工程结合机器学习对代码缺陷进行预测分析，现在正处于数据分析阶段，每天都会到github上拉一大堆项目，然后用写好的代码啪啪啪分析一通，一般来说代码都要跑很久，一般都是12小时左右才能出结果，而且等它跑完还要继续跑剩下一个项目，但是作为程序员，这样的体力活自然应该自动化处理啦，毕竟越厉害的程序员是越懒的。 所以，这种周期性，性质类似，">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="crontab">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/04/30/Crontab/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="事情的经过是这样子的，室友最近要做一个阿里的项目，大概就是利用软件工程结合机器学习对代码缺陷进行预测分析，现在正处于数据分析阶段，每天都会到github上拉一大堆项目，然后用写好的代码啪啪啪分析一通，一般来说代码都要跑很久，一般都是12小时左右才能出结果，而且等它跑完还要继续跑剩下一个项目，但是作为程序员，这样的体力活自然应该自动化处理啦，毕竟越厉害的程序员是越懒的。 所以，这种周期性，性质类似，">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:44:38.037Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="crontab">
-<meta name="twitter:description" content="事情的经过是这样子的，室友最近要做一个阿里的项目，大概就是利用软件工程结合机器学习对代码缺陷进行预测分析，现在正处于数据分析阶段，每天都会到github上拉一大堆项目，然后用写好的代码啪啪啪分析一通，一般来说代码都要跑很久，一般都是12小时左右才能出结果，而且等它跑完还要继续跑剩下一个项目，但是作为程序员，这样的体力活自然应该自动化处理啦，毕竟越厉害的程序员是越懒的。 所以，这种周期性，性质类似，">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Crontab"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      crontab
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-04-30T05:58:24.000Z" itemprop="datePublished">
-        Apr 30, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>事情的经过是这样子的，室友最近要做一个阿里的项目，大概就是利用软件工程结合机器学习对代码缺陷进行预测分析，现在正处于数据分析阶段，每天都会到github上拉一大堆项目，然后用写好的代码啪啪啪分析一通，一般来说代码都要跑很久，一般都是12小时左右才能出结果，而且等它跑完还要继续跑剩下一个项目，但是作为程序员，这样的体力活自然应该自动化处理啦，毕竟越厉害的程序员是越懒的。</p>
-<p>所以，这种周期性，性质类似，但是需要大量重复劳动的工作可以写成自动化脚本再结合 <code>crontab</code> 来解决。<code>crontab</code> 就是为了周期性定时执行任务而生的，再也不用盯着电脑屏幕等结果跑完啦，感觉是现在搞AI的人的必备良药呢。</p>
-<p><code>crontab</code> 的语法还是挺简单的，但是咋一看还是一脸懵逼的，其实关于<code>crontab</code> 只要掌握一点就可以使用它了，就是关于时间语法的定义，因为 <code>crontab</code> 就是为了定时执行任务而存在的，所以它有自己的一套语法。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ * * * * * command_to_execute</span><br><span class="line">  | | | | |</span><br><span class="line">  | | | | +- day of week (0 - 7) where sunday is 0 and 7</span><br><span class="line">  | | | +--- month (1 - 12)</span><br><span class="line">  | | +----- day (1 - 31)</span><br><span class="line">  | +------- hour (0 - 23)</span><br><span class="line">  +--------- minute (0 - 59)</span><br></pre></td></tr></table></figure>
-<p>我们要让某个任务在某个特定的时间点执行，时间无非就是哪个月的哪一天的几点几分或者是星期几该执行这项任务，在 <code>crontab</code> 的语法中我们先指定分钟，再次小时，接着一个月中的某一天，然后月份，最后星期几。具体的顺序如下：<code>(min)  (hour)  (day_of_month)  (month)  (day_of_week)</code>。</p>
-<h2 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h2><p>不过上面讲的还是太抽象了，我们来具体举几个例子来掌握crontab的使用吧。</p>
-<p>例如我们已经写好了一个脚本，<code>make_coffee.sh</code> ，因为程序员都有午后喝咖啡的习惯，但是咖啡机每次启动都要预热好久，为了让自己少浪费一点时间，就写了一个脚本让咖啡机在每天下午两点自己开启进行预热，预热完成，我们就可以直接过去接咖啡了。所以，我们要让 <code>crontab</code> 每天下午执行这个脚本，我们应该怎么写呢，按照上面的语法，不是很难。</p>
-<p><code>$ 0 14 * * * /path/to/make_coffee.sh</code></p>
-<p>也就是说 <code>crontab</code> 每天下午两点会启动咖啡机预热，不过现在有个问题，我们周末并不在公司，只有工作日周一到周五在公司，所以，我们上面的语法还是有点问题的，应该让 <code>crontab</code> 指定在工作日才运行。</p>
-<p><code>$ 0 14 * * 1-5 /path/to/make_coffee.sh</code></p>
-<p>只要把第五个 <code>*</code> 换成 <code>1-5</code> 就可以啦，非常简单。</p>
-<p>但是每天喝咖啡可能对身体不太好，那我们改成星期一星期三星期五喝咖啡，其他两天改喝牛奶，那我们应该怎么办呢，将1-5改成 1,3,5 就可以了。</p>
-<p><code>$ 0 14 * * 1,3,5 /path/to/make_coffee.sh</code></p>
-<p><code>crontab</code> 的语法还是有很多的，这里就不一一例举了，我们有一个大致的思路，有了大致的思路，具体问题再去看文档就ok啦。</p>
-<h2 id="crontab管理"><a href="#crontab管理" class="headerlink" title="crontab管理"></a>crontab管理</h2><p>其实直接在命令行中直接数据 <code>crontab</code> 命令并不是一个非常好的习惯，我们最好将这些命令存放在文件中以便持久化的目的，也方便我们进行集中管理，很幸运的是，<code>crontab</code> 已经为我们提供了这些服务啦。</p>
-<p><code>$ crontab -e</code></p>
-<p><code>-e</code> 可以让我们编辑crontab文件，可以在该文件中定义多个 <code>crontab</code> 任务。</p>
-<p><code>$ crontab -l</code></p>
-<p><code>-l</code> 帮助我们查看当前用户定义的所有的 <code>cron jobs</code>。</p>
-<p><code>$ crontab -r</code></p>
-<p><code>-r</code> 则会清除当前用户所有的 <code>cron jobs</code>。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/01/Port_0/index.html b/2018/05/01/Port_0/index.html
deleted file mode 100644
index e9037da..0000000
--- a/2018/05/01/Port_0/index.html
+++ /dev/null
@@ -1,247 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>port 0, WTF? | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="我们都知道 TCP 或者 UDP 的端口号可以从0一直到65535，而0到1023端口则被称为熟知端口，是系统保留使用的端口号，0号端口在 TCP/IP 中也属于保留端口号，但它并不可以在一般的 TCP 或者 UDP 通信中使用。 但是，如果0号端口不能被使用的话，那它又有什么用呢，简单来讲，就是如果程序监听了0号端口，那么它就会触发操作系统自动去寻找在0到65535这个范围内可以使用的端口号（即">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="port 0, WTF?">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/01/Port_0/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="我们都知道 TCP 或者 UDP 的端口号可以从0一直到65535，而0到1023端口则被称为熟知端口，是系统保留使用的端口号，0号端口在 TCP/IP 中也属于保留端口号，但它并不可以在一般的 TCP 或者 UDP 通信中使用。 但是，如果0号端口不能被使用的话，那它又有什么用呢，简单来讲，就是如果程序监听了0号端口，那么它就会触发操作系统自动去寻找在0到65535这个范围内可以使用的端口号（即">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:25.730Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="port 0, WTF?">
-<meta name="twitter:description" content="我们都知道 TCP 或者 UDP 的端口号可以从0一直到65535，而0到1023端口则被称为熟知端口，是系统保留使用的端口号，0号端口在 TCP/IP 中也属于保留端口号，但它并不可以在一般的 TCP 或者 UDP 通信中使用。 但是，如果0号端口不能被使用的话，那它又有什么用呢，简单来讲，就是如果程序监听了0号端口，那么它就会触发操作系统自动去寻找在0到65535这个范围内可以使用的端口号（即">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Port_0"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      port 0, WTF?
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-01T03:11:11.000Z" itemprop="datePublished">
-        May 1, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>我们都知道 <code>TCP</code> 或者 <code>UDP</code> 的端口号可以从0一直到65535，而0到1023端口则被称为熟知端口，是系统保留使用的端口号，0号端口在 <code>TCP/IP</code> 中也属于保留端口号，但它并不可以在一般的 <code>TCP</code> 或者 <code>UDP</code> 通信中使用。</p>
-<p>但是，如果0号端口不能被使用的话，那它又有什么用呢，简单来讲，就是如果程序监听了0号端口，那么它就会触发操作系统自动去寻找在0到65535这个范围内可以使用的端口号（即未被其他程序占用），这样就相当于动态分配一个端口号了，和 <code>DHCP</code> 协议有着异曲同工之妙，不过 <code>DHCP</code> 是用于动态分配IP地址，而0号端口则用于动态分配端口号，而且两者的工作原理也不同。</p>
-<p>所以，如果想要得到一个动态的端口号，我们只要让程序监听0号端口就可以了，即 <code>net.Listen(&quot;tcp&quot;, &quot;127.0.0.1:0&quot;)</code> ，下面给出一个获取动态端口号的示例代码。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"net"</span></span><br><span class="line">    <span class="string">"strconv"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">GetFreePort</span><span class="params">()</span> <span class="params">(port <span class="keyword">int</span>, err error)</span></span> &#123;</span><br><span class="line">    listener, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">"127.0.0.1:0"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> listener.Close()</span><br><span class="line">     </span><br><span class="line">    addr := listener.Addr().String()</span><br><span class="line">    _, portString, err := net.SplitHostPort(addr)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> strconv.Atoi(portString)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    port, err := GetFreePort()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fmt.Println(port)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/01/etcd/index.html b/2018/05/01/etcd/index.html
deleted file mode 100644
index 2ffeeb0..0000000
--- a/2018/05/01/etcd/index.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>etcd | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="etcd 是一个用于存储分布式系统中重要数据结构的存储引擎，而其本身就是一个分布式的键值数据库，例如在微服务架构中的服务注册和发现机制，就可以利用 etcd 作为我们的注册中心进行服务，用于存储服务注册信息。 但是，什么又是服务注册和发现呢，其实这和现在盛行的微服务架构有着密切的联系，在以前那种非微服务时代，应用运行在物理机上面，服务实例对应的网络地址也是相对固定不变的，而到了微服务时代，很多服务">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="etcd">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/01/etcd/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="etcd 是一个用于存储分布式系统中重要数据结构的存储引擎，而其本身就是一个分布式的键值数据库，例如在微服务架构中的服务注册和发现机制，就可以利用 etcd 作为我们的注册中心进行服务，用于存储服务注册信息。 但是，什么又是服务注册和发现呢，其实这和现在盛行的微服务架构有着密切的联系，在以前那种非微服务时代，应用运行在物理机上面，服务实例对应的网络地址也是相对固定不变的，而到了微服务时代，很多服务">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-architecture.png">
-<meta property="og:updated_time" content="2018-06-26T08:45:10.988Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="etcd">
-<meta name="twitter:description" content="etcd 是一个用于存储分布式系统中重要数据结构的存储引擎，而其本身就是一个分布式的键值数据库，例如在微服务架构中的服务注册和发现机制，就可以利用 etcd 作为我们的注册中心进行服务，用于存储服务注册信息。 但是，什么又是服务注册和发现呢，其实这和现在盛行的微服务架构有着密切的联系，在以前那种非微服务时代，应用运行在物理机上面，服务实例对应的网络地址也是相对固定不变的，而到了微服务时代，很多服务">
-<meta name="twitter:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-architecture.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-etcd"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      etcd
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-01T04:28:24.000Z" itemprop="datePublished">
-        May 1, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><code>etcd</code> 是一个用于存储分布式系统中重要数据结构的存储引擎，而其本身就是一个分布式的键值数据库，例如在微服务架构中的服务注册和发现机制，就可以利用 <code>etcd</code> 作为我们的注册中心进行服务，用于存储服务注册信息。</p>
-<p>但是，什么又是服务注册和发现呢，其实这和现在盛行的微服务架构有着密切的联系，在以前那种非微服务时代，应用运行在物理机上面，服务实例对应的网络地址也是相对固定不变的，而到了微服务时代，很多服务实例的网络地址则是动态分配的，而且服务实例也经常面临着失败或者更新的情况，所以这些服务实例对应的网络地址也经常会变化，这对应用的开发者和使用者都是非常不利的，所以引入服务注册和发现这种机制，来适应微服务的这种问题。</p>
-<p><img src="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-architecture.png" alt="alt text"></p>
-<p>我们以 <code>Dubbo</code> 中的服务注册与发现为例，深入理解一下到底什么是服务注册与发现，这里有几个角色需要注意一下，<code>Registry</code> 用于服务信息的登记和提供，<code>Provider</code> 是服务的提供商，它会将自己提供的服务信息注册到<code>Registry</code> 上，而 <code>Consumer</code> 则是相应服务的消费者，它会从 <code>Registry</code> 那里获取服务的信息（一般来说就是接口的地址），再调用 <code>Provider</code> 上提供的真实服务，<code>Monitor</code> 这里仅仅作为记录一些调用次数之类的元信息。注意到这里 <code>Registry</code> 通知 <code>Consumer</code> 服务信息是一个异步的过程，而 <code>Consumer</code> 调用 <code>Provider</code> 的服务则是同步的。</p>
-<p><code>etcd</code> 底层使用 <code>raft</code> 协议来维持集群中服务器间数据的一致性，这在之后的博客中会详细探讨。而 <code>etcd</code> 也提供了非常简单的客户端接口供我们使用，今天我们的目标就是写一个 <code>etcd</code> 的客户端供我们进行服务注册和发现等相关方面的使用。</p>
-<p><code>etcd</code> 无论作为什么用途，其本质都是一个kv存储引擎，而我们要实现的客户端必须提供以下接口的服务。例如向 <code>etcd</code> 写入键值对，获取相应键对应的值，还有获取相应键最新值的机制（通过watch机制）等等。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Store <span class="keyword">interface</span> &#123;</span><br><span class="line">    Put(key <span class="keyword">string</span>, value []<span class="keyword">byte</span>, options *WriteOptions) error</span><br><span class="line">    Get(key <span class="keyword">string</span>) (*KVPair, error)</span><br><span class="line">    Delete(key <span class="keyword">string</span>) error</span><br><span class="line">    Exists(key <span class="keyword">string</span>) (<span class="keyword">bool</span>, error)</span><br><span class="line">    Watch(key <span class="keyword">string</span>, stopCh &lt;-<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;) (&lt;-<span class="keyword">chan</span> *KVPair, error)</span><br><span class="line">    WatchTree(directory <span class="keyword">string</span>, stopCh &lt;-<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;) (&lt;-<span class="keyword">chan</span> []*KVPair, error)</span><br><span class="line">    NewLock(key <span class="keyword">string</span>, options *LockOptions) (Locker, error)</span><br><span class="line">    List(directory <span class="keyword">string</span>) ([]*KVPair, error)</span><br><span class="line">    DeleteTree(directory <span class="keyword">string</span>) error</span><br><span class="line">    AtomicPut(key <span class="keyword">string</span>, value []<span class="keyword">byte</span>, previous *KVPair, options *WriteOptions) (<span class="keyword">bool</span>, *KVPair, error)</span><br><span class="line">    AtomicDelete(key <span class="keyword">string</span>, previous *KVPair) (<span class="keyword">bool</span>, error)</span><br><span class="line">    Close() </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> KVPair <span class="keyword">struct</span> &#123;</span><br><span class="line">    Key       <span class="keyword">string</span></span><br><span class="line">    Value     []<span class="keyword">byte</span></span><br><span class="line">    LastIndex <span class="keyword">uint64</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> WriteOptions <span class="keyword">struct</span> &#123;</span><br><span class="line">    IsDir <span class="keyword">bool</span></span><br><span class="line">    TTL   time.Duration</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> LockOptions <span class="keyword">struct</span> &#123;</span><br><span class="line">    Value     []<span class="keyword">byte</span></span><br><span class="line">    TTL       time.Duration</span><br><span class="line">    RenewLock <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>etcd</code> 官方已经给我们提供了一个client接口了（ github.com/coreos/etcd/client），我们只要在文件头导入它就行了。</p>
-<p><code>import etcd &quot;github.com/coreos/etcd/client</code></p>
-<p>我们对该服务进行一层封装以便实现我们的 <code>Store</code> 接口。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Etcd <span class="keyword">struct</span> &#123;</span><br><span class="line">    client etcd.KeysAPI</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(addrs []<span class="keyword">string</span>, options *Config)</span> <span class="params">(Store, error)</span></span> &#123;</span><br><span class="line">    s := &amp;Etcd&#123;&#125;</span><br><span class="line"></span><br><span class="line">    cfg := &amp;etcd.Config&#123;</span><br><span class="line">        Endpoints:               entries,</span><br><span class="line">        Transport:               etcd.DefaultTransport,</span><br><span class="line">        HeaderTimeoutPerRequest: <span class="number">3</span> * time.Second,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Set options</span></span><br><span class="line">    <span class="keyword">if</span> options != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> options.TLS != <span class="literal">nil</span> &#123;</span><br><span class="line">            setTLS(cfg, options.TLS, addrs)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> options.ConnectionTimeout != <span class="number">0</span> &#123;</span><br><span class="line">            setTimeout(cfg, options.ConnectionTimeout)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> options.Username != <span class="string">""</span> &#123;</span><br><span class="line">            setCredentials(cfg, options.Username, options.Password)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    c, err := etcd.New(*cfg)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    s.client = etcd.NewKeysAPI(c)</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Periodic Cluster Sync</span></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> err := c.AutoSync(context.Background(), periodicSync); err != <span class="literal">nil</span> &#123;</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> s, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当然，客户端与 <code>etcd</code> 服务器的通信一般都不是明文传输的，所以还需要定义用于传输加密相关的结构体。一般在通信过程中会使用TLS加密，所以安全性问题我们就可以不用担心了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Config <span class="keyword">struct</span> &#123;</span><br><span class="line">    ClientTLS         *ClientTLSConfig</span><br><span class="line">    TLS               *tls.Config</span><br><span class="line">    ConnectionTimeout time.Duration</span><br><span class="line">    Bucket            <span class="keyword">string</span></span><br><span class="line">    PersistConnection <span class="keyword">bool</span></span><br><span class="line">    UserName          <span class="keyword">string</span></span><br><span class="line">    Password          <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> ClientTLSConfig <span class="keyword">struct</span> &#123;</span><br><span class="line">    CertFile   <span class="keyword">string</span></span><br><span class="line">    KeyFile    <span class="keyword">string</span></span><br><span class="line">    CACertFile <span class="keyword">string</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面我们来重点看一下三个接口的实现，分别是 <code>Put</code> ，<code>Get</code> 和 <code>Watch</code> ，分别应对现实生活中，<code>Provider</code> 向 <code>etcd</code> 写入可以提供的服务信息，<code>Consumer</code> 在 <code>etcd</code> 中读取服务信息，还有就是在 <code>etcd</code> 上注册的服务信息改变时，<code>Consumer</code> 可以及时获得改变后的值。</p>
-<p><code>Get</code> 操作获取当前 <code>etcd</code> 已经注册的服务信息，也就是服务发现的过程。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Etcd)</span> <span class="title">Get</span><span class="params">(key <span class="keyword">string</span>)</span> <span class="params">(pair *KVPair, err error)</span></span> &#123;</span><br><span class="line">    getOpts := &amp;etcd.GetOptions&#123;</span><br><span class="line">        Quorum: <span class="literal">true</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    result, err := s.client.Get(context.Background(), s.normalize(key), getOpts)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    pair = &amp;KVPair&#123;</span><br><span class="line">        Key:       key,</span><br><span class="line">        Value:     []<span class="keyword">byte</span>(result.Node.Value)</span><br><span class="line">        LastIndex: result.Node.ModifieIndex,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> pair, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Put</code> 操作可以向 <code>etcd</code> 注册相应的服务信息，简单的说就是服务注册。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Etcd)</span> <span class="title">Put</span><span class="params">(key <span class="keyword">string</span>, value []<span class="keyword">byte</span>, opts *WriteOptions)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    setOpts := &amp;etcd.SetOptions&#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> opts != <span class="literal">nil</span> &#123;</span><br><span class="line">        setOpts.Dir = opts.IsDir</span><br><span class="line">        setOpts.TTL = opts.TTL</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    _, err := s.client.Set(context.Background(), s.normalize(key), <span class="keyword">string</span>(value), setOpts)</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当我们关心的某一项键值（对应服务）发生变化时候，我们需要及时获取最新的值以免我们的服务出现过期不可用的情况，例如我们我们提供服务的服务端的一个实例挂掉了，某些编排系统如 <code>k8s</code> 会自动重启这些实例，但是重启后的实例的服务地址可能会出现改变，我们使用这些服务的客户端肯定需要知道更新过后的值，通过 <code>watch</code> 机制就可以及时获取更新后的键值对。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Etcd)</span> <span class="title">Watch</span><span class="params">(key <span class="keyword">string</span>, stopCh &lt;-<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span> <span class="params">(&lt;-<span class="keyword">chan</span> *KVPair, error)</span></span> &#123;</span><br><span class="line">    opts := &amp;etcd.WatcherOptions&#123;Recursive: <span class="literal">false</span>&#125;</span><br><span class="line">    watcher := s.client.Watcher(s.normalize(key), opts)</span><br><span class="line">    watchCh := <span class="built_in">make</span>(<span class="keyword">chan</span> *KVPair)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> <span class="built_in">close</span>(watchCh)</span><br><span class="line"></span><br><span class="line">        pair, err := s.Get(key)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        watchCh &lt;- pair</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            <span class="keyword">select</span> &#123;</span><br><span class="line">            <span class="keyword">case</span> &lt;-stopCh:</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            <span class="keyword">default</span>:</span><br><span class="line">            &#125;</span><br><span class="line">           </span><br><span class="line">            result, err := watcher.Next(context.Background())</span><br><span class="line">            <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            watchCh &lt;- KVPair&#123;</span><br><span class="line">                Key:       key,</span><br><span class="line">                Value:     []<span class="keyword">byte</span>(result.Node.Value),</span><br><span class="line">                LastIndex: result.Node.ModifiedIndex,</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    retrun watchCh, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h3><p>主要是笔者最近要参加阿里的第四届中间件大赛，所以对服务注册和发现做了一些调研工作。在像阿里这种大公司就会提供各种各样的服务端口，而且由于分布式的特性，服务间通讯就变得尤为重要，通常服务提供者暴露服务，服务消费者调用服务，而它们之间的中介服务通常就由<code>etcd</code>，<code>consul</code> 或者 <code>zookeeper</code> 这样的高性能键值数据库来提供。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/01/iobridge/index.html b/2018/05/01/iobridge/index.html
deleted file mode 100644
index e621902..0000000
--- a/2018/05/01/iobridge/index.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>iobridge | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="每个人小时候都或多或少经历过父母冷战吧，当他们冷战的时候，我们这些可怜的小屁孩就成了传话筒，一般事情就会发展成下面这种情况了：   「老爸 -&amp;gt; 我 ：“叫你老妈安静一点”    然后   我 -&amp;gt; 老妈 ：“老妈，老爸叫你安静一点”」   「老妈 -&amp;gt; 我 ：“你老爸才需要安静呢”    然后   我 -&amp;gt; 老爸 ：“老爸，老妈说你才需要安静呢”」 上述对话如此往复，诶，">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="iobridge">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/01/iobridge/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="每个人小时候都或多或少经历过父母冷战吧，当他们冷战的时候，我们这些可怜的小屁孩就成了传话筒，一般事情就会发展成下面这种情况了：   「老爸 -&amp;gt; 我 ：“叫你老妈安静一点”    然后   我 -&amp;gt; 老妈 ：“老妈，老爸叫你安静一点”」   「老妈 -&amp;gt; 我 ：“你老爸才需要安静呢”    然后   我 -&amp;gt; 老爸 ：“老爸，老妈说你才需要安静呢”」 上述对话如此往复，诶，">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:19.737Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="iobridge">
-<meta name="twitter:description" content="每个人小时候都或多或少经历过父母冷战吧，当他们冷战的时候，我们这些可怜的小屁孩就成了传话筒，一般事情就会发展成下面这种情况了：   「老爸 -&amp;gt; 我 ：“叫你老妈安静一点”    然后   我 -&amp;gt; 老妈 ：“老妈，老爸叫你安静一点”」   「老妈 -&amp;gt; 我 ：“你老爸才需要安静呢”    然后   我 -&amp;gt; 老爸 ：“老爸，老妈说你才需要安静呢”」 上述对话如此往复，诶，">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-iobridge"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      iobridge
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-01T13:13:24.000Z" itemprop="datePublished">
-        May 1, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>每个人小时候都或多或少经历过父母冷战吧，当他们冷战的时候，我们这些可怜的小屁孩就成了传话筒，一般事情就会发展成下面这种情况了：</p>
-<p>  「老爸 -&gt; 我 ：“叫你老妈安静一点”<br>    然后<br>   我 -&gt; 老妈 ：“老妈，老爸叫你安静一点”」</p>
-<p>  「老妈 -&gt; 我 ：“你老爸才需要安静呢”<br>    然后<br>   我 -&gt; 老爸 ：“老爸，老妈说你才需要安静呢”」</p>
-<p>上述对话如此往复，诶，可怜天下小屁孩，要是冷战的话，老爸老妈必须通过一个中介人——我来进行语言上的交流。</p>
-<p>在现代网络编程中，也会出现与上述例子极其相似的情况，例如，现在有三台服务器，分别是A，B，C，其中A能与B直接通信，B能与C直接通信，但是A不能与C直接通信，在这种情况下，A要想能与C交流，就必须要经过B，下面我们就来看如何实现上面这种情况吧。</p>
-<p>下面的 <code>iobridge</code> 函数就做了一件传话筒的工作，其原理非常简单，就是从我们的数据源 <code>src</code> 读取（调用 <code>Read</code> 方法）数据，然后将它写到我们的目的地（调用 <code>Write</code> 方法）。也就是相当于我们上述过程中我从老妈那里获取消息，然后再将这个消息发给老爸的过程，注意到，这里函数中数据流的方法是单向的。</p>
-<p>因为在读数据的过程中经常需要开辟新内存，为了节约运行时的成本，我们通过之前写过的 <code>LeakyBuffer</code> 模型来获取内存。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">iobridge</span><span class="params">(src io.Reader, dst io.Writer, shutdown <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span></span> &#123;</span><br><span class="line">    <span class="keyword">defer</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        shutdown &lt;- <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    &#125;()</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        buf := leakyBuffer.Get()</span><br><span class="line">        n, err := src.Read(buf)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> !(err == io.EOF || UseClosedConn(err)) &#123;</span><br><span class="line">                log.Print(<span class="string">"error reading %s:"</span>, src, err)</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">        _, err := dst.Write(buf[:n])</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Prinf(<span class="string">"error writing %s: %s\n"</span>, dst, err)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">        leakyBuffer.Put(buf)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">UseClosedConn</span><span class="params">(err error)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    operr, ok := err.(*net.OpErr)</span><br><span class="line">    <span class="keyword">return</span> ok &amp;&amp; operr.Err.Error() == <span class="string">"use of closed network connection"</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为我们的 <code>net.Conn</code> 同时定义了 <code>Read(b []byte) (n int, err error)</code> 方法和 <code>Write(b []byte) (n int, err error)</code> 方法，而这两个方法分别由接口 <code>io.Reader</code> 和 <code>io.Writer</code> 定义，所以 <code>net.Conn</code> 既是 <code>io.Reader</code> 也是 <code>io.Writer</code> 。故上述方法中的第一个和第二个参数我们都可以使用 <code>net.Conn</code> 做我们的参数。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// defined in package io</span></span><br><span class="line"><span class="keyword">type</span> Reader <span class="keyword">interface</span> &#123;</span><br><span class="line">    Read(p []<span class="keyword">byte</span>) (n <span class="keyword">int</span>, err error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// defined in package io</span></span><br><span class="line"><span class="keyword">type</span> Writer <span class="keyword">interface</span> &#123;</span><br><span class="line">    Write(p []<span class="keyword">byte</span>) (n <span class="keyword">int</span>, err error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// defined in package net</span></span><br><span class="line"><span class="keyword">type</span> Conn <span class="keyword">interface</span> &#123;</span><br><span class="line">    Read(b []<span class="keyword">byte</span>) (n <span class="keyword">int</span>, err error)</span><br><span class="line">    Write(b []<span class="keyword">byte</span>) (n <span class="keyword">int</span>, err error)</span><br><span class="line">    ...</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>这里的main函数应该运行在中间那台服务器也就是B上面，B作为客户端向远程服务器C发起TCP连接，并返回一个套接字conn1，同时B也作为服务器监听端口，服务来自A的连接请求，<code>Accept</code> 成功返回另一个套接字conn2，那么如何使得来个无法直接接触的服务器A和C有来有往的进行交流对话呢，这里的技巧就是起两个goroutine分别调用 <code>iobridge</code> 方法，使得两个 <code>net.Conn</code> conn1和conn2相互传递数据以互通有无，<code>shutdown</code> 这个通道这里算一个hack，用于阻塞main routine 不让其马上返回。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    conn1, err := net.Dial(<span class="string">"tcp"</span>, <span class="string">"remotehost"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(<span class="string">"Error Dialing"</span>)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    l. err := net.Listen(<span class="string">"tcp"</span>, <span class="string">":2333"</span>)</span><br><span class="line">    conn2, err := listener.Accept()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(<span class="string">"Error Accepting Connection"</span>)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    shutdown := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, <span class="number">2</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> iobridge(conn1, conn2, shutdown)</span><br><span class="line">    <span class="keyword">go</span> iobridge(conn2, conn1, shutdown)</span><br><span class="line"></span><br><span class="line">    &lt;-shutdown</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>设有服务器A，B，C，除了A与C不能直接接触，其余两两都能沟通，要想A能与C进行沟通交流，解决方案就是A作为客户端调用 <code>net.Dial</code> 向B发起TCP连接，如果连接成功，则A上会有一个 <code>net.Conn</code> sA，B上也有一个 <code>net.Conn</code> sB1，此时B也作为客户端向C发起TCP连接，B上又多了一个 <code>net.Conn</code> sB2，C上也有一个<code>net.Conn</code> sC。注意这些 <code>net.Conn</code> 的本质都是一个套接字，可以直接当成文件描述符来进行操作。</p>
-<p>此时A和C要想互相交流，唯一的方法就是将sB1和sB2进行某种程度的联系，通过起两个 <code>iobridge</code> 函数，我们就将sB1读到的数据发送给sB2，也可sB2读到的数据发送给sB1，注意，一旦sB1将读到的数据发送给sB2，sB2会马上把这个数据发送给sC，这样就达到了A与C相互交流的目的了。</p>
-<p>聪明的小伙伴一定注意到了，上面讲的就是代理（shadowsocks）的基本工作原理了，是不是很简单也很有趣呢。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/02/DecodingDubboProtocol/index.html b/2018/05/02/DecodingDubboProtocol/index.html
deleted file mode 100644
index eaf9ff3..0000000
--- a/2018/05/02/DecodingDubboProtocol/index.html
+++ /dev/null
@@ -1,290 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Dubbo Protocol | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="之前看 shadowsocks 源码的时候看过好多遍 SOCKS5 的 RFC ，看的一脸懵逼，不知道这些奇奇怪怪的网络协议究竟该如何理解，后来才发现网络协议也并没有那么神秘，无非就是为了让两台计算机使用网络进行通信时能互相理解对方而设定的一系列规则而已。就好像一个中国人和一个法国人聊天，法国人讲法语，而中国人用中文，他们自然很难理解对方究竟要表达什么意思，但是如果二者约定同时用两者都会的语言——">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Dubbo Protocol">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/02/DecodingDubboProtocol/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="之前看 shadowsocks 源码的时候看过好多遍 SOCKS5 的 RFC ，看的一脸懵逼，不知道这些奇奇怪怪的网络协议究竟该如何理解，后来才发现网络协议也并没有那么神秘，无非就是为了让两台计算机使用网络进行通信时能互相理解对方而设定的一系列规则而已。就好像一个中国人和一个法国人聊天，法国人讲法语，而中国人用中文，他们自然很难理解对方究竟要表达什么意思，但是如果二者约定同时用两者都会的语言——">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png">
-<meta property="og:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png">
-<meta property="og:updated_time" content="2018-06-26T08:44:55.222Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Dubbo Protocol">
-<meta name="twitter:description" content="之前看 shadowsocks 源码的时候看过好多遍 SOCKS5 的 RFC ，看的一脸懵逼，不知道这些奇奇怪怪的网络协议究竟该如何理解，后来才发现网络协议也并没有那么神秘，无非就是为了让两台计算机使用网络进行通信时能互相理解对方而设定的一系列规则而已。就好像一个中国人和一个法国人聊天，法国人讲法语，而中国人用中文，他们自然很难理解对方究竟要表达什么意思，但是如果二者约定同时用两者都会的语言——">
-<meta name="twitter:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-DecodingDubboProtocol"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Dubbo Protocol
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-02T07:58:24.000Z" itemprop="datePublished">
-        May 2, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>之前看 <code>shadowsocks</code> 源码的时候看过好多遍 <code>SOCKS5</code> 的 <code>RFC</code> ，看的一脸懵逼，不知道这些奇奇怪怪的网络协议究竟该如何理解，后来才发现网络协议也并没有那么神秘，无非就是为了让两台计算机使用网络进行通信时能互相理解对方而设定的一系列规则而已。就好像一个中国人和一个法国人聊天，法国人讲法语，而中国人用中文，他们自然很难理解对方究竟要表达什么意思，但是如果二者约定同时用两者都会的语言——英语进行交流，那么两者就可以正常交流下去了，因为两者协议了一套规则，可以相互理解的规则（这里的规则就是英语）。</p>
-<p>一般来说要是想自己定义一套网络协议，首先需要做的事情就是定义这个协议中特定位置的字段分别代表什么含义，例如下图中的 <code>Dubbo</code> 协议，它就规定了一个报文中各个字段代表的含义，如下面第一个字节和第二个字节合在一起就叫做一个 <code>Magic Number</code> ，以此类推。</p>
-<p><img src="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png" alt="Dubbo"></p>
-<p>所以，解析网络协议的本质就是去解析一个字节数组，并将它包含的数据转换成特定的含义的过程，下面我们就以解析 <code>Dubbo</code> 协议为例，来看一下如何正确地读取字节数组中的信息，在这之前，我们先了解一下golang标准库中的两个函数。</p>
-<p>第一个就是 <code>bytes.NewBuffer(buf []byte) *bytes.Buffer</code> ，因为我们处理协议本质上就是处理字节数组，使用该函数对字节数组进行封装而不是直接操作字节数组的好处自然不用多说。当使用上述函数的时候，返回的 <code>Buffer</code> 会以 <code>buf</code> 这个字节数组作为它的初始内容，而且在这之后该 <code>Buffer</code> 就会全权掌控该字节数组（也就是说之后我们不可以再碰 <code>buf</code>了）。</p>
-<p>第二个就是 <code>binary.Read(r io.Reader, order ByteOrder, data interface{}) error</code>，该函数可以非常方便的将结构化的二进制数据从 <code>r</code> 中以固定的字节序（ <code>ByteOrder</code> ）读到 <code>data</code>相应的数据字段中，由于<code>bytes.Buffer</code> 实现了<code>io.Reader</code> 中的 <code>Read</code> 方法，所以它也能作为第一个参数传入<code>binary.Read</code> 进行使用。</p>
-<p>很多协议的报文都是变长的，为了方便起见，一般都是先解析定长部分的数据，然后再解析其变长部分的数据。</p>
-<h2 id="Dubbo-协议分析"><a href="#Dubbo-协议分析" class="headerlink" title="Dubbo 协议分析"></a>Dubbo 协议分析</h2><p>在正式写协议解析类的代码之前，最好先明确该协议中各个字段的含义，所谓磨刀不误砍柴工嘛。</p>
-<p><img src="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png" alt="Dubbo"></p>
-<ul>
-<li>Magic 字段，共2字节，包含 <code>Magic High</code> 和 <code>Magic Low</code> 字段，用于特定标识该报文是否采用 <code>Dubbo</code> 协议而存在的，如果是则要求其值等于0xdabb。</li>
-<li>Req/Res，1比特，用于表示该报文是请求报文还是答复报文，当值为1时说明该报文为请求报文，0时为答复报文。</li>
-<li>2way，1比特，当且仅当 <code>Req/Res</code> 为1时有效，也就是该报文为请求报文时，指明是否期望服务器返回数据，当值为1时则表示希望服务器返回数据。</li>
-<li>Event，1比特，标记该报文是否为事件消息，例如心跳消息，则设置为1。</li>
-<li>Serialization ID，5比特，用于表示变长数据部分序列化的方法，例如当使用 <code>fastjson</code> 时它的值为6。</li>
-<li><p>Status，1字节，用于表示请求的状态，其值可以是</p>
-<ul>
-<li>20 - OK</li>
-<li>30 - CLIENT_TIMEOUT</li>
-<li>31 - SERVER_TIMEOUT</li>
-<li>40 - BAD_REQUEST</li>
-<li>50 - BAD_RESPONSE</li>
-<li>60 - SERVICE_NOT_FOUND</li>
-<li>70 - SERVICE_ERROR</li>
-<li>80 - SERVER_ERROR</li>
-<li>90 - CLIENT_ERROR</li>
-<li>100 -SERVER_THREADPOOL_EXHAUSTED_ERROR</li>
-</ul>
-</li>
-<li><p>Request ID，64比特即8字节，用于唯一标识该请求。</p>
-</li>
-<li>Data Length，变长部分的数据长度，4字节长度。</li>
-<li>Variable Part 报文中数据的变长部分，其使用的序列化方法由上述的<code>serializationID</code> 字段决定。</li>
-</ul>
-<h2 id="解析过程"><a href="#解析过程" class="headerlink" title="解析过程"></a>解析过程</h2><p>由于从 <code>Magic Number</code> 到 <code>Data Length</code> 这个数据字段，其总长度都是固定的，所以我们可以定义一个 <code>dubboHeader</code> 结构体包含这些数据字段，其中各个数据字段的类型由协议中各个字段的长度决定，例如 <code>MagicHigh</code> 的长度为一个字节，所以我们在结构体中使用一个 <code>byte</code> 来表示它就可以了，再比如 <code>RequestID</code> 的长度是8字节，我们可以用 <code>uint64</code> 来表示，依次类推。</p>
-<p>由于我们要解析的是一个字节数组，为了后面方便起见，我们使用 <code>bytes.NewBuffer</code> 来封装它，这样就可以得到一个 <code>io.Reader</code> ，然后再使用 <code>binary.Read</code> 就可以解码得到 <code>dubboHeader</code> 这个结构体了。</p>
-<p>当使用 <code>bytes.Buffer</code> 的时候需要注意一点，它里面有类似于指针概念，也就是当我们调用 <code>Read</code> 方法读取多少字节时，内部的指针 <code>off</code> 也会向前移动多少字节的长度，所以当我们使用 <code>binary.Read(buf, binary.BigEndian, &amp;dubboHeader)</code> ，它就会将内部的指针移动 <code>len(dubboHeader)</code> 个长度，这样我们就可以利用 <code>buf.Next</code> 方法获取剩下变长部分的数据啦。</p>
-<p>定长部分解决好之后，我们来看变长部分应该怎么解决，协议中 <code>Serialization ID</code> 字段规定了变长部分数据的序列化方法，例如这里使用 <code>json</code> 格式进行序列化，所以我们只要获取剩余部分的字节数组，然后调用<code>json.Unmarshal</code> 就可以获得剩余部分的数据内容了。</p>
-<h2 id="完整代码段"><a href="#完整代码段" class="headerlink" title="完整代码段"></a>完整代码段</h2><p>自定义解析过程中可能出现的错误类型</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> ErrInvalidMagicNumber = errors.New(<span class="string">"Invalid Magic Number"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> ErrInvalidDataLength = errors.New(<span class="string">"Invalid Data Length"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> ErrUnmarshallingJSON = errors.New(<span class="string">"Encounter Error when Unmarshalling JSON"</span>)</span><br></pre></td></tr></table></figure>
-<p>自定义变长部分数据对应的结构体，注意，结构体中的数据字段必须为大写，否则使用 <code>json.Unmarshal</code> 会出错。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> VariablePart <span class="keyword">struct</span> &#123;</span><br><span class="line">    DubboVersion     <span class="keyword">string</span> <span class="string">`json:"DubboVersion"`</span></span><br><span class="line">    ServiceName      <span class="keyword">string</span> <span class="string">`json:"ServiceName"`</span></span><br><span class="line">    ServiceMethod    <span class="keyword">string</span> <span class="string">`json:"ServiceMethod"`</span></span><br><span class="line">    MethodName       <span class="keyword">string</span> <span class="string">`json:"MethodName"`</span></span><br><span class="line">    MethodParamTypes <span class="keyword">string</span> <span class="string">`json:"MethodParamTypes"`</span></span><br><span class="line">    MethodArguments  <span class="keyword">string</span> <span class="string">`json:"MethodArguments"`</span></span><br><span class="line">    Attachments      <span class="keyword">string</span> <span class="string">`json:"Attachments"`</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>按协议规则一步步解析字节数组并得到相应的信息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Parse</span><span class="params">(b []<span class="keyword">byte</span>)</span> <span class="params">(*VariablePart, error)</span></span> &#123;</span><br><span class="line">    buf := bytes.NewBuffer(b)</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">var</span> dubboHeader <span class="keyword">struct</span> &#123;</span><br><span class="line">        MagicHigh  <span class="keyword">byte</span></span><br><span class="line">        MagicLow   <span class="keyword">byte</span></span><br><span class="line">        Misc       <span class="keyword">byte</span></span><br><span class="line">        Status     <span class="keyword">byte</span></span><br><span class="line">        RequestID  <span class="keyword">uint64</span></span><br><span class="line">        DataLength <span class="keyword">uint32</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> err error</span><br><span class="line">    err = binary.Read(buf, binary.BigEndian, &amp;dubboHeader)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> !(dubboHeader.MagicHigh == <span class="number">0xda</span> &amp;&amp; dubboHeader.MagicLow == <span class="number">0xbb</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, ErrInvalidMagicNumber</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    partBytes := buf.Next(<span class="keyword">int</span>(dubboHeader.DataLength))</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(partBytes) &lt; <span class="keyword">int</span>(dubbo.DataLength) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, ErrInvalidDataLength</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    partBuffer := bytes.NewBuffer(partBytes)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> variablePart VariablePart</span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> dubboHeader.Misc &amp; <span class="number">0x1F</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">        <span class="comment">//</span></span><br><span class="line">    <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">        <span class="comment">//</span></span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        err = json.Unmarshal(partBuffer, &amp;variablePart)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, ErrUnmarshallingJSON</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> &amp;variablePart, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/02/LoadBalancing/index.html b/2018/05/02/LoadBalancing/index.html
deleted file mode 100644
index a74bdca..0000000
--- a/2018/05/02/LoadBalancing/index.html
+++ /dev/null
@@ -1,262 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Load Balancing | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="当服务提供者（Service Provider）将服务注册到 etcd 之后，为了更加理想地分配任务·，我们就要考虑负载均衡问题了，负载均衡的核心就是把让任务合理地分摊到多个执行单元上执行，以期获得更高的吞吐量或者说是数据处理能力，通俗点讲就是大家都有肉吃，没有人会撑死也没人会饿死，大家都得到适合自己的那一份。 下图中，Service Consumer 即服务的消费者，它通过向 Provider">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Load Balancing">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/02/LoadBalancing/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="当服务提供者（Service Provider）将服务注册到 etcd 之后，为了更加理想地分配任务·，我们就要考虑负载均衡问题了，负载均衡的核心就是把让任务合理地分摊到多个执行单元上执行，以期获得更高的吞吐量或者说是数据处理能力，通俗点讲就是大家都有肉吃，没有人会撑死也没人会饿死，大家都得到适合自己的那一份。 下图中，Service Consumer 即服务的消费者，它通过向 Provider">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png">
-<meta property="og:updated_time" content="2018-06-26T08:46:40.000Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Load Balancing">
-<meta name="twitter:description" content="当服务提供者（Service Provider）将服务注册到 etcd 之后，为了更加理想地分配任务·，我们就要考虑负载均衡问题了，负载均衡的核心就是把让任务合理地分摊到多个执行单元上执行，以期获得更高的吞吐量或者说是数据处理能力，通俗点讲就是大家都有肉吃，没有人会撑死也没人会饿死，大家都得到适合自己的那一份。 下图中，Service Consumer 即服务的消费者，它通过向 Provider">
-<meta name="twitter:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-LoadBalancing"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Load Balancing
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-02T10:12:24.000Z" itemprop="datePublished">
-        May 2, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>当服务提供者（Service Provider）将服务注册到 <code>etcd</code> 之后，为了更加理想地分配任务·，我们就要考虑负载均衡问题了，负载均衡的核心就是把让任务合理地分摊到多个执行单元上执行，以期获得更高的吞吐量或者说是数据处理能力，通俗点讲就是大家都有肉吃，没有人会撑死也没人会饿死，大家都得到适合自己的那一份。</p>
-<p>下图中，<code>Service Consumer</code> 即服务的消费者，它通过向 <code>Provider</code> 源源不断地发送服务请求，负载均衡问题要解决的问题就是如何将请求合理地分配给不同的 <code>Service Provider</code> 处理，例如，我们下图中有三台服务提供者，假如服务提供者的服务都是比较消耗时间的（例如计算哈希值），为了增加整个系统的吞吐量，我们要考虑合适的任务分配策略，这就是负载均衡的核心所在，要是只将请求发送给其中一台 <code>Service Provider</code>，那么其它两台都会空闲着不执行任务，这样的话整个系统的吞吐量肯定就上不来了，毕竟没有充分的利用所有的资源，所以，我们要把任务平均地分配给每个执行单元去处理。</p>
-<p><img src="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png" alt="loadbalancing"></p>
-<p>下面我们来实现一个负载均衡的例子，实现的思路非常简单，定义一个 <code>LoadBalancingService</code> 结构体，其中的 <code>etcdClient</code> 用于与 <code>etcd</code> 进行沟通交流以获取相应的注册信息，<code>nodes</code>，<code>nodeMap</code>，<code>nodeCount</code> 用于记录已经注册在 <code>etcd</code> 的服务提供者的信息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> LoadBalancingService <span class="keyword">struct</span> &#123;</span><br><span class="line">    etcdClient client.Client</span><br><span class="line">    connected  <span class="keyword">bool</span></span><br><span class="line">    nodes      []<span class="keyword">string</span></span><br><span class="line">    nodeMap    <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span></span><br><span class="line">    nodeCount  <span class="keyword">int</span></span><br><span class="line">    sync.RWMutex</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *LoadBalancingService)</span> <span class="title">watch</span><span class="params">(watcher client.Watcher)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        resp, err := watcher.Next(context.Background())</span><br><span class="line">        <span class="keyword">if</span> err == <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> resp.Action == <span class="string">"set"</span> &#123;</span><br><span class="line">                n := resp.Node.Value</span><br><span class="line">                s.addNode(n)</span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> resp.Action == <span class="string">"delete"</span> &#123;</span><br><span class="line">                n := resp.PrevNode.Value</span><br><span class="line">                s.removeNode(n)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上面的核心就是 <code>Watcher</code> 机制，在新事件到来之前，<code>Watcher</code> 的<code>Next</code> 方法会一直阻塞，直到事件返回为止，一般来说都是在 <code>for</code> 循环中调用 <code>Next</code> 以期达到轮询（polling）的效果。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Watcher <span class="keyword">interface</span> &#123;</span><br><span class="line">    Next(context.Context) (*Response, error)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Connect</code> 函数就是用于客户端与 <code>etcd</code> 连接并根据 <code>serviceName</code> 读取当前已经注册过的服务，并通过 <code>watch</code> 机制不断地更新当前可用的服务。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span>  <span class="params">(s *LoadBalancingService)</span> <span class="title">Connect</span><span class="params">(serviceName <span class="keyword">string</span>, endPoints []<span class="keyword">string</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> s.connected &#123;</span><br><span class="line">        log.Println(<span class="string">"Can't connect twice"</span>)</span><br><span class="line">        <span class="keyword">return</span> errors.New(<span class="string">"Already connected"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    s.nodeMap = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int</span>)</span><br><span class="line">    s.nodeCount = <span class="number">0</span></span><br><span class="line"></span><br><span class="line">    cfg := client.Config&#123;</span><br><span class="line">        Endpoints:   endpoints,</span><br><span class="line">        Transport:   client.DefaultTransport,</span><br><span class="line">        HeaderTimeoutPerRequest: time.Second,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> err error</span><br><span class="line">    s.etcdClient, err = client.New(cfg)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    kapi := client.NewKeysAPI(s.etcdClient)</span><br><span class="line"></span><br><span class="line">    resp, err := kapi.Get(context.Background(), serviceName, <span class="literal">nil</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> resp.Node.Dir &#123;</span><br><span class="line">            <span class="keyword">for</span> _, peer := resp.Node.Nodes &#123;</span><br><span class="line">                n := peer.Value</span><br><span class="line">                s.addNode(n)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    watcher := kapi.Watcher(serviceName, &amp;client.WatcherOptions&#123;Recursive: <span class="literal">true</span>&#125;)</span><br><span class="line">    <span class="keyword">go</span> s.watch(watcher)</span><br><span class="line">    service.connected = <span class="literal">true</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span>    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>GetNode</code> 采用了随机算法获取当前节点群中的随机节点进行处理我们的任务，这里是负载均衡算法的核心，说白了中随机挑选一个进行发送服务请求让服务提供者进行处理。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *LoadBalancingService)</span> <span class="title">GetNode</span><span class="params">()</span> <span class="params">(<span class="keyword">string</span>, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> !s.connected &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">""</span>, errors.New(<span class="string">"Must call connect first"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    s.RLock()</span><br><span class="line">    <span class="keyword">defer</span> s.RUnlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> s.nodeCount == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">""</span>, ErrEmptyService </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> s.nodes[rand.Intn(s.nodeCount)], <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>addNode</code> 和 <code>removeNode</code> 分别对应远程服务提供者数量增加或者减少时的情况，并更新 <code>LoadBalancingService</code> 结构体中相应的数据结构。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *LoadBalancingService)</span> <span class="title">addNode</span><span class="params">(key <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    s.Lock()</span><br><span class="line">    <span class="keyword">defer</span> s.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> _, ok := s.nodeMap[key]; ok &#123;</span><br><span class="line">        <span class="keyword">if</span> s.nodeCount &gt;= <span class="built_in">len</span>(s.nodes) &#123;</span><br><span class="line">            s.nodes = <span class="built_in">append</span>(s.nodes, key)</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            s.nodes[s.nodeCount] = key</span><br><span class="line">        &#125;</span><br><span class="line">        s.nodeMap[key] = s.nodeCount</span><br><span class="line">        s.nodeCount++</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *LoadBalancingService)</span> <span class="title">removeNode</span><span class="params">(key <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    s.Lock()</span><br><span class="line">    <span class="keyword">defer</span> s.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> index, ok := s.nodeMap[key]; ok &#123;</span><br><span class="line">        <span class="keyword">for</span> i := index; i &lt; <span class="built_in">len</span>(s.nodes)<span class="number">-1</span>; i++ &#123;</span><br><span class="line">            s.nodes[i] = s.nodes[i+<span class="number">1</span>]</span><br><span class="line">        &#125;</span><br><span class="line">        s.nodeCount--</span><br><span class="line">        <span class="built_in">delete</span>(s.nodeMap, key)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="负载均衡算法的改良"><a href="#负载均衡算法的改良" class="headerlink" title="负载均衡算法的改良"></a>负载均衡算法的改良</h2><p>在上面的例子中，我们采用的是随机算法，这种是基于每台处理任务的 <code>Service Provider</code> 性能差不多的情况下作出的抉择，但是现实生活中情况并不总是如此，每台服务器的性能，网络带宽都存在着或多或少的差异，所以，我们需要根据实际情况，对负载均衡的分配方法作相应的改进。</p>
-<p>假设我们的服务提供者的平均综合性能比值为1:2:3，那么每台服务提供者任务分配的比例也应该是1:2:3，所谓能者多劳就是这个意思了。在其他情况下我们也可以根据流量比例分配任务，反正还是要具体问题具体分析。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/02/Screenshot/index.html b/2018/05/02/Screenshot/index.html
deleted file mode 100644
index c3a5d9d..0000000
--- a/2018/05/02/Screenshot/index.html
+++ /dev/null
@@ -1,253 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Screenshot | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在今年年前的时候，像冲顶大会，芝士超人这样的答题赚钱类应用异常火爆，当然了，聪明的程序猿们也不是吃素的，为了提高答对题目的概率，就写了一些程序（脚本）来自动化答题过程，整个作弊的思路并不难，关键点就在于获取手机的当前截屏，然后通过文字识别来获取题目的信息，最后再调用浏览器搜索答案，在浏览器中出现最多的那个基本就可以锁定是答案了（当然还有其他的作弊方法，这里不一一列举），这种作弊方法在初期真是屡试不">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Screenshot">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/02/Screenshot/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在今年年前的时候，像冲顶大会，芝士超人这样的答题赚钱类应用异常火爆，当然了，聪明的程序猿们也不是吃素的，为了提高答对题目的概率，就写了一些程序（脚本）来自动化答题过程，整个作弊的思路并不难，关键点就在于获取手机的当前截屏，然后通过文字识别来获取题目的信息，最后再调用浏览器搜索答案，在浏览器中出现最多的那个基本就可以锁定是答案了（当然还有其他的作弊方法，这里不一一列举），这种作弊方法在初期真是屡试不">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:04.370Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Screenshot">
-<meta name="twitter:description" content="在今年年前的时候，像冲顶大会，芝士超人这样的答题赚钱类应用异常火爆，当然了，聪明的程序猿们也不是吃素的，为了提高答对题目的概率，就写了一些程序（脚本）来自动化答题过程，整个作弊的思路并不难，关键点就在于获取手机的当前截屏，然后通过文字识别来获取题目的信息，最后再调用浏览器搜索答案，在浏览器中出现最多的那个基本就可以锁定是答案了（当然还有其他的作弊方法，这里不一一列举），这种作弊方法在初期真是屡试不">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Screenshot"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Screenshot
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-02T12:29:04.000Z" itemprop="datePublished">
-        May 2, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在今年年前的时候，像冲顶大会，芝士超人这样的答题赚钱类应用异常火爆，当然了，聪明的程序猿们也不是吃素的，为了提高答对题目的概率，就写了一些程序（脚本）来自动化答题过程，整个作弊的思路并不难，关键点就在于获取手机的当前截屏，然后通过文字识别来获取题目的信息，最后再调用浏览器搜索答案，在浏览器中出现最多的那个基本就可以锁定是答案了（当然还有其他的作弊方法，这里不一一列举），这种作弊方法在初期真是屡试不爽，所以今天就让我们来看一下整个作弊流程的关键环节——自动获取手机截屏的代码实现吧。</p>
-<p>因为手机分为 <code>Android</code> 阵营和 <code>iOS</code> 阵营，而且两者实现截屏的方法也稍有不同，所以我们先定义一个 <code>Screenshot</code> interface对两种平台进行抽象，之后会分别定义 <code>iOS</code> 和 <code>Android</code> 这两个结构体来实现这个接口（有没有慢慢开始体会到 <code>interface</code> 的好处呢），下面的代码中我们也利用了工厂模式来返回 <code>Screenshot</code> 实例。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Screenshot <span class="keyword">interface</span> &#123;</span><br><span class="line">    GetImage() (image.Image. error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewScreenshot</span><span class="params">(cfg *Config)</span> <span class="title">Screenshot</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> cfg.Device == <span class="string">"iOS"</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> NewIOS(cfg)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> NewAndroid(cfg)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Config &#123;</span><br><span class="line">    Device     <span class="keyword">string</span></span><br><span class="line">    WdaAddress <span class="keyword">string</span></span><br><span class="line">    .....</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Android-实现"><a href="#Android-实现" class="headerlink" title="Android 实现"></a>Android 实现</h2><p>我们先定义个 <code>Android</code> 结构体，这个结构体实现了 <code>GetImage</code> 方法，所以可以在上面的工厂方法中作为 <code>Screenshot</code> 接口返回。而在真正运行我们的代码之前，我们需要确保安卓机已经正确地连接至电脑，并且要确保电脑上已经安装过 <code>adb</code> 这个命令行工具。这里实现截屏主要靠调用 <code>adb</code> 的 <code>screencap</code> 和 <code>pull</code> 这两个子命令，<code>screencap</code> 对当前手机进行截屏并保存到手机本地，<code>pull</code> 命令将手机上的截图传到电脑本地（然后就可以接着一通骚操作了），我们通过 <code>exec.Command</code> 接口对 <code>adb</code> 进行调用，整体思路比较清晰，难点应该就在我们不熟悉 <code>adb</code> 命令的使用。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Android <span class="keyword">struct</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewAndroid</span><span class="params">(cfg *Config)</span> *<span class="title">Android</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">new</span>(Android)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(android *Android)</span> <span class="title">GetImage</span><span class="params">()</span> <span class="params">(img image.Image, err error)</span></span> &#123;</span><br><span class="line">    err := exec.Command(<span class="string">"adb"</span>, <span class="string">"shell"</span>, <span class="string">"screencap"</span>, <span class="string">"-p"</span>. <span class="string">"/sdcard/screenshot.png"</span>).Run()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    dstImagePath := <span class="string">"/Desktop"</span> + <span class="string">"origin.png"</span></span><br><span class="line">    err = exec.Command(<span class="string">"adb"</span>, <span class="string">"pull"</span>, <span class="string">"/sdcard/screenshot.png"</span>, dstImgPath).Run()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    f, err := os.Open(dstImagePath)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> f.Close()</span><br><span class="line">    <span class="keyword">return</span> png.Decode(f)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="iOS-实现"><a href="#iOS-实现" class="headerlink" title="iOS 实现"></a>iOS 实现</h2><p>依葫芦画瓢，同样定义一个 <code>IOS</code> 结构体，来实现 <code>GetImage</code> 方法，在具体截屏的实现中，由于 <code>iOS</code> 系统的封闭性，所以自然没有像 <code>Android</code> 的 <code>adb</code> 那样的命令行调试工具，不过也不是说啥事也做不了，在 <code>iOS</code> 中，我们可以向特定接口地址 <code>wdaAddress</code> 发送 <code>http</code> 的<code>GET</code> 请求，然后通过解析返回的 <code>json</code> 数据，这个 <code>json</code> 数据中就编码了我们的图片信息，然后再利用 <code>base64</code> 进行解码获得一个字节数组，再对该字节数组进行 <code>png</code> 解码，最终就可以获得我们想要的 <code>image</code> 了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> IOS <span class="keyword">struct</span> &#123;</span><br><span class="line">    wdaAddress <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> screenshotRes &#123;</span><br><span class="line">    Value     <span class="keyword">string</span> <span class="string">`json:"value"`</span></span><br><span class="line">    SessionID <span class="keyword">string</span> <span class="string">`json:"sessionId"`</span></span><br><span class="line">    Status    <span class="keyword">int</span>    <span class="string">`json:"status"`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewIOS</span><span class="params">(cfg *Config)</span> *<span class="title">IOS</span></span> &#123;</span><br><span class="line">    ios := <span class="built_in">new</span>(IOS)</span><br><span class="line">    ios.wdaAddress = cfg.WdaAddress</span><br><span class="line">    <span class="keyword">if</span> ios.wdaAddress == <span class="string">""</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"Please specify the wda address"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ios</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(ios *IOS)</span> <span class="title">GetImage</span><span class="params">()</span> <span class="params">(img image.Image, err error)</span></span> &#123;</span><br><span class="line">    body, err := util.HTTPGet(ios.wdaAddress)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">         <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    res := <span class="built_in">new</span>(screenshotRes)</span><br><span class="line">    err = json.Unmarshal(body, res)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    pngValue, err := base64.stdEncoding.DecodeString(res.Value)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    src, err := png.Decode(bytes.NewReader(pngValue))</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    img = src</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在本篇博客中，我们看到了工厂模式在具体程序设计中的应用，灵活使用工厂模式可以提供我们工程代码的水平，也见识到了如何利用 <code>adb</code> 工具对 <code>Android</code> 机器进行调试，当然了 <code>adb</code> 的功能不仅仅局限于上述两点，它还可以干非常多的事情，有兴趣的小伙伴可以自己研究一下，最后还有就是因为 <code>iOS</code> 系统本身的封闭性，我们只能通过调用web接口来获取其截图信息。</p>
-<p>最后，作为程序员圈子里的一员，在日常生活中还是要多思考，啥东西要是可以用代码实现自动化，就马上动手去实现它吧。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/02/TLS/index.html b/2018/05/02/TLS/index.html
deleted file mode 100644
index 9bc97a8..0000000
--- a/2018/05/02/TLS/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>TLS | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在之前的博客中涉及到的 TCP 网络编程都是非常不安全的，因为它将我们的数据直接以明文的形式在公网上面传输，如果有恶意第三方的存在，我们传输的数据就可以被捕捉监听甚至修改，从而导致各种各样无法预测的结果，所以，考虑到安全性，我们还是要学一学如果用 TLS 进行网络编程，以提高我们的客户端和服务器之前传输数据的安全性。 TLS 即 Transport Layer Security ，就是为了保证传输">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="TLS">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/02/TLS/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在之前的博客中涉及到的 TCP 网络编程都是非常不安全的，因为它将我们的数据直接以明文的形式在公网上面传输，如果有恶意第三方的存在，我们传输的数据就可以被捕捉监听甚至修改，从而导致各种各样无法预测的结果，所以，考虑到安全性，我们还是要学一学如果用 TLS 进行网络编程，以提高我们的客户端和服务器之前传输数据的安全性。 TLS 即 Transport Layer Security ，就是为了保证传输">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:37.253Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="TLS">
-<meta name="twitter:description" content="在之前的博客中涉及到的 TCP 网络编程都是非常不安全的，因为它将我们的数据直接以明文的形式在公网上面传输，如果有恶意第三方的存在，我们传输的数据就可以被捕捉监听甚至修改，从而导致各种各样无法预测的结果，所以，考虑到安全性，我们还是要学一学如果用 TLS 进行网络编程，以提高我们的客户端和服务器之前传输数据的安全性。 TLS 即 Transport Layer Security ，就是为了保证传输">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TLS"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      TLS
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-02T04:40:04.000Z" itemprop="datePublished">
-        May 2, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在之前的博客中涉及到的 <code>TCP</code> 网络编程都是非常不安全的，因为它将我们的数据直接以明文的形式在公网上面传输，如果有恶意第三方的存在，我们传输的数据就可以被捕捉监听甚至修改，从而导致各种各样无法预测的结果，所以，考虑到安全性，我们还是要学一学如果用 <code>TLS</code> 进行网络编程，以提高我们的客户端和服务器之前传输数据的安全性。</p>
-<p><code>TLS</code> 即 <code>Transport Layer Security</code> ，就是为了保证传输层上的数据安全，服务器和客户端会在 <code>handshake</code> 阶段协商出只有两者知晓的一个对称密钥，然后之后的通信就利用这个对称密钥将数据进行加密后进行传输，很幸运的是，在我们使用 <code>TLS</code> 进行网络编程的时候，并不用去关注这些繁杂的细节，因为golang的标准库都已经帮我们封装好了（hooray！）。</p>
-<h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><p>使用 <code>TLS</code> 进行网络编程的时候，我们需要在服务器上放一个证书，证书的话可以使用 <code>openssl</code> 工具来生成，这里作为例子就先生成一个自签名的证书吧。</p>
-<p>要生成一个证书，第一步当然就是生成一个私钥了，这里我们指定使用 <code>RSA</code> 算法生成一个 <code>2048bit</code> 的私钥。</p>
-<p><code>$ openssl genrsa -out server.key 2048</code></p>
-<p>计算私钥是比较耗时的一个过程，无论多好的电脑，都需要在毫秒级别才能生成一个RSA私钥，这里输出的 <code>server.key</code> 就是我们要的私钥，生成的私钥是经过 <code>pem</code> 格式编码的，也就是类似如下的格式：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-----BEGIN RSA PRIVATE KEY-----</span><br><span class="line">MIIEowIBAAKCAQEA1DYBcVnQFyFEW9AhHY+6+Shp7LIT5ZtjbFfu2ZQgg3aTsXVF..........</span><br><span class="line">-----END RSA PRIVATE KEY-----</span><br></pre></td></tr></table></figure>
-<p>当拥有了私钥之后，为了得到对应的证书，我们还需要有一个 <code>Certificate Signing Request</code> ，简称为 <code>CSR</code> ，也就是证书签名请求。</p>
-<p><code>$ openssl req -new -sha256 -key server.key -out server.csr</code></p>
-<p>这个命令会要求你输入相关的信息，填入相关信息后就会得到一个 <code>server.csr</code> 文件，这个文件也是用<code>pem</code> 格式编码的，类似如下：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-----BEGIN CERTIFICATE REQUEST-----</span><br><span class="line">MIIC0jCCAboCAQAwbjELMAkGA1UEBhMCQ04xETAPBgNVBAcMCEhhbmd6aG91MQww..........</span><br><span class="line">-----END CERTIFICATE REQUEST-----</span><br></pre></td></tr></table></figure>
-<p>最后一步就是利用上面步骤中得到的私钥和证书签名请求来最终获得一个自签名的证书。</p>
-<p><code>$ openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt</code></p>
-<p>最终获得的证书 <code>server.crt</code> 也是 <code>pem</code> 格式编码的，类似如下：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-----BEGIN CERTIFICATE-----</span><br><span class="line">MIIDWDCCAkACCQCFvy51fQRGMTANBgkqhkiG9w0BAQUFADBuMQswCQYDVQQGEwJD..........</span><br><span class="line">-----END CERTIFICATE-----</span><br></pre></td></tr></table></figure>
-<p>利用下面的命令我们可以查看我们刚刚生成的符合 <code>x509</code> 标准的证书的具体信息，里面包含了两个比较重要的信息就是公钥（public key）和签名（signature）。</p>
-<p><code>$ openssl x509 -in server.crt -noout -text</code></p>
-<p>上面这么多命令必须按顺序执行，也就是说第一步生成私钥，第二步生成证书签名请求，最后才能生成我们的证书。</p>
-<h2 id="TLS-server"><a href="#TLS-server" class="headerlink" title="TLS server"></a>TLS server</h2><p>在 <code>TLS</code> 编程中，服务器端需要得到私钥和证书的信息。我们使用 <code>tls.LoadX509KeyPair</code> 来获得我们之前生成证书和私钥信息，然后在监听时作为参数导入。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"crypto/tls"</span></span><br><span class="line">    <span class="string">"net"</span></span><br><span class="line">    <span class="string">"log"</span></span><br><span class="line">    <span class="string">"bufio"</span></span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    cert, err := tls.LoadX509KeyPair(<span class="string">"server.crt"</span>, <span class="string">"server.key"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    config := &amp;tls.Config&#123;Certificates: []tls.Certificate&#123;cert&#125;&#125;</span><br><span class="line">    listener, err := tls.Listen(<span class="string">"tcp"</span>, <span class="string">":443"</span>, config)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> listener.Close()</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        conn, err := listener.Accept()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(err)</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">go</span> handleConnection(conn)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handleConnection</span><span class="params">(conn net.Conn)</span></span> &#123;</span><br><span class="line">    <span class="keyword">defer</span> conn.Close()</span><br><span class="line">    r := bufio.NewReader(conn)</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        msg, err := r.ReadString(<span class="string">'\n'</span>)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        fmt.Println(msg)</span><br><span class="line"></span><br><span class="line">        n, err := conn.Write([]<span class="keyword">byte</span>(<span class="string">"world\n"</span>))</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(n, err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="TLS-client"><a href="#TLS-client" class="headerlink" title="TLS client"></a>TLS client</h2><p>与一般的TCP网络编程类似，作为客户端我们调用 <code>tls.Dial</code> 而非 <code>net.Dial</code> 来与服务器建立连接，但与 <code>net.Dial</code> 不同的是，我们还需要多传递一个 <code>tls.Config</code> 参数，来指定 <code>TLS</code> 连接时的各种参数。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">    <span class="string">"log"</span></span><br><span class="line">    <span class="string">"crypto/tls"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    conf := &amp;tls.Config&#123;</span><br><span class="line">        InsecureSkipVerify: <span class="literal">true</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    conn, err := tls.Dial(<span class="string">"tcp"</span>, <span class="string">"127.0.0.1:443"</span>, conf)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> conn.Close()</span><br><span class="line"></span><br><span class="line">    n, err := conn.Write([]<span class="keyword">byte</span>(<span class="string">"hello\n"</span>))</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    buf := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">100</span>)</span><br><span class="line">    n , err := conn.Read(buf)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(n, err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fmt.Println(<span class="keyword">string</span>(buf[:n]))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="抓取tcp包进行验证"><a href="#抓取tcp包进行验证" class="headerlink" title="抓取tcp包进行验证"></a>抓取tcp包进行验证</h2><p><code>$ tcpdump host 127.0.0.1 port 433</code></p>
-<p>当我们这时候使用类似 <code>tcpdump</code> 这样的抓包工具进行网络抓包时，我们不再能看到明文了，看到的只能是一堆乱七八糟的东西，因为客户端和服务器已经将数据经过加密处理了。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/04/Docker/index.html b/2018/05/04/Docker/index.html
deleted file mode 100644
index da8c4a1..0000000
--- a/2018/05/04/Docker/index.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Docker &amp; Golang | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="还记得 java 当初响遍大江南北的口号吗，Write one，run anywhere ，到了互联网时代，Docker 这家公司打出了更为牛逼的口号，Build，Ship，and Run Any App，Anywhere ，它们两者有类似的地方，都是为了追求各种平台的兼容性和通用性。java 的跨平台是因为它在不同平台下有不同的 jvm 实现，不过它仅仅局限于 java 这个生态系统里面，相比之">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Docker &amp; Golang">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/04/Docker/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="还记得 java 当初响遍大江南北的口号吗，Write one，run anywhere ，到了互联网时代，Docker 这家公司打出了更为牛逼的口号，Build，Ship，and Run Any App，Anywhere ，它们两者有类似的地方，都是为了追求各种平台的兼容性和通用性。java 的跨平台是因为它在不同平台下有不同的 jvm 实现，不过它仅仅局限于 java 这个生态系统里面，相比之">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:02.382Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Docker &amp; Golang">
-<meta name="twitter:description" content="还记得 java 当初响遍大江南北的口号吗，Write one，run anywhere ，到了互联网时代，Docker 这家公司打出了更为牛逼的口号，Build，Ship，and Run Any App，Anywhere ，它们两者有类似的地方，都是为了追求各种平台的兼容性和通用性。java 的跨平台是因为它在不同平台下有不同的 jvm 实现，不过它仅仅局限于 java 这个生态系统里面，相比之">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Docker"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Docker &amp; Golang
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-04T09:01:24.000Z" itemprop="datePublished">
-        May 4, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>还记得 <code>java</code> 当初响遍大江南北的口号吗，<code>Write one，run anywhere</code> ，到了互联网时代，<code>Docker</code> 这家公司打出了更为牛逼的口号，<code>Build，Ship，and Run Any App，Anywhere</code> ，它们两者有类似的地方，都是为了追求各种平台的兼容性和通用性。<code>java</code> 的跨平台是因为它在不同平台下有不同的 <code>jvm</code> 实现，不过它仅仅局限于 <code>java</code> 这个生态系统里面，相比之下，<code>Docker</code> 的野心就更大了，它并没有给我们把编程语言给限定死了，它提供了一个与操作系统隔离的环境，可以让我们写任何应用，而且可以在几乎所有平台下跑。</p>
-<p>具体 <code>Docker</code> 的细节这里就不具体探讨了，网上也有一堆文章，今天我们主要看一下如何使用它，也就是如何将我们的应用打包成一个 <code>Docker</code> 镜像。</p>
-<p>下面我们要实现的是一个用 <code>golang</code> 写的 <code>http</code> 服务器，但是这个服务器并不是跑在裸机上，而是跑在 <code>Docker</code> 容器中的。顺便一提，<code>Docker</code> 也是用 <code>golang</code> 写的哦，是不是感觉很厉害呢。</p>
-<h2 id="书写自己的应用逻辑"><a href="#书写自己的应用逻辑" class="headerlink" title="书写自己的应用逻辑"></a>书写自己的应用逻辑</h2><p>下面定义了我们要实现的 <code>http</code> 服务器的前端，无奈直男不会写 <code>CSS</code> ，就用 <code>HTML</code> 写了一下最基本的提交 <code>FORM</code> 表单的功能。</p>
-<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">title</span>&gt;</span><span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">"/hash"</span> <span class="attr">method</span>=<span class="string">"post"</span>&gt;</span></span><br><span class="line">            interface: <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"interface"</span>&gt;</span></span><br><span class="line">            method: <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"method"</span>&gt;</span></span><br><span class="line">            parameterTypesString: <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"parameterTypesString"</span>&gt;</span></span><br><span class="line">            parameter: <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">name</span>=<span class="string">"parameter"</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"submit"</span> <span class="attr">value</span>=<span class="string">"hash"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>
-<p>下面使用了golang中的标准库 <code>net/http</code> 和 <code>html/template</code> 起一个服务器，我们自己定义的 <code>hashHandler</code> 会根据请求的类型分别进行处理，如果是 <code>GET</code> 请求则展示我们的前端界面，如果是 <code>POST</code> 请求则处理我们浏览器提交的表单并将表单输出到命令行中。到这里，一个非常简单的 <code>http</code> 服务器就写好了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"fmt"</span></span><br><span class="line">    <span class="string">"html/template"</span></span><br><span class="line">    <span class="string">"log"</span></span><br><span class="line">    <span class="string">"net/http"</span></span><br><span class="line">    <span class="string">"strings"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">hashHandler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    fmt.Println(<span class="string">"method: "</span>, r.Method)</span><br><span class="line">    <span class="keyword">if</span> r.Method == <span class="string">"GET"</span> &#123;</span><br><span class="line">        t, _ := template.ParseFiles(<span class="string">"hash.tpl"</span>)</span><br><span class="line">        t.Execute(w, <span class="literal">nil</span>)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        r.ParseForm()</span><br><span class="line">        <span class="keyword">for</span> k, v := <span class="keyword">range</span> r.Form &#123;</span><br><span class="line">            fmt.Printf(<span class="string">"key: %s, value: %s\n"</span>, k, v)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    http.HandleFunc(<span class="string">"/hash"</span>, hashHandler)</span><br><span class="line">    err := http.ListenAndServe(<span class="string">":8080"</span>, <span class="literal">nil</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(<span class="string">"ListenAndServe: "</span>, err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Dockerfile的撰写"><a href="#Dockerfile的撰写" class="headerlink" title="Dockerfile的撰写"></a>Dockerfile的撰写</h2><p>到现在，就没我们 <code>golang</code> 什么事情了，有请我们今天的主角 <code>Docker</code> 登场了。为了能让我们的 <code>http</code> 服务器在容器中运行，我们需要写一个 <code>Dockerfile</code> ，<code>Dockerfile</code> 的作用就是让 <code>Docker</code> 知道该如何构建镜像，当然平时大部分时候我们都可以直接用别人打包好的镜像，但是自己会写 <code>Dockerfile</code> 也是一个非常重要的能力哦。</p>
-<p><code>FROM</code> 指令指定了我们的基础镜像是什么，也就是说我们构建的镜像是基于哪个镜像的基础之上的，这里 <code>golang:alpine</code> 作为我们的基础镜像。而<code>COPY</code> 指令则将我们的文件从操作系统中拷贝到容器环境中。<code>WORKDIR</code> 命令则制定了在 <code>Docker</code> 内部的工作目录，类似于 <code>cd</code> 命令，<code>RUN</code> 命令在容器中执行指令，这里我们把go源文件编译成二进制。<code>CMD</code> 指令指定了启动该容器时内部应该执行的命令。当然 <code>Dockerfile</code> 的命令还有很多，具体还是参考官方的文档吧。</p>
-<figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">FROM</span> golang:alpine</span><br><span class="line"><span class="keyword">COPY</span> . /home</span><br><span class="line">WORKDIR /home</span><br><span class="line">RUN go build -o server ./server.go</span><br><span class="line">CMD /home/server</span><br></pre></td></tr></table></figure>
-<p>写完了 <code>Dockerfile</code> ，就可以构建镜像了，不过构建镜像的事情我可干不来，还是交给 <code>Docker</code> 去做吧。下面的命令就帮助我们构建一个名为 <code>oceanoverflow/server</code> 的 <code>golang</code> 服务器镜像。构建镜像的过程可能会比较花时间，需要耐心等待。</p>
-<p><code>$ docker build -t oceanoverflow/server .</code></p>
-<h2 id="运行Docker容器"><a href="#运行Docker容器" class="headerlink" title="运行Docker容器"></a>运行Docker容器</h2><p>构建完了我们使用 <code>docker image ls</code> 就可以看到我们新构建的镜像啦，最后一步就是起容器服务了。</p>
-<p><code>-p</code> 命令这里将容器内的端口8080映射到操作系统的端口8080上去，如果不指定8080，那我们在自己的操作系统上就无法获取到它提供的服务，所以 <code>-p</code> 还是非常重要的。</p>
-<p><code>$ docker run -p 8080:8080 --rm -it go-server</code></p>
-<p>如果一切无误，到浏览器中输入 <code>localhost:8080/hash</code> 就可以看到我们跑在 <code>Docker</code> 里面的 <code>http</code> 服务器已经成功地跑起来啦。</p>
-<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>让自己的应用跑在 <code>Docker</code> 容器中非常简单，第一步就是构建自己的应用程序的源码，第二步正确编写适应自己业务场景的 <code>Dockerfile</code> 然后利用 <code>Docker</code> 自带的功能打包成一个镜像，最后一步就是运行容器了。就这么三步走，可谓是 <code>Docker</code>在手，天下我有了。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/05/Crawler/index.html b/2018/05/05/Crawler/index.html
deleted file mode 100644
index 0bb7f7e..0000000
--- a/2018/05/05/Crawler/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Crawler | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="爬虫算是练习并发编程的一个非常好的例子了，因为它既不枯燥，难度也不大，而且能在短时间内产出一个有趣的结果。爬虫一般通过某种搜索算法（深度优先搜索或者广度优先搜索）在互联网这个海量数据库中去寻找我们感兴趣的东西，如果使用得当的话，爬虫可以极大地提高我们的工作效率。 那么接下去我们从一个单线程的爬虫程序出发，然后慢慢将它改造成一个并发的爬虫程序。在这里，我们并不关心究竟如何去匹配我们感兴趣的元素(例如">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Crawler">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/05/Crawler/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="爬虫算是练习并发编程的一个非常好的例子了，因为它既不枯燥，难度也不大，而且能在短时间内产出一个有趣的结果。爬虫一般通过某种搜索算法（深度优先搜索或者广度优先搜索）在互联网这个海量数据库中去寻找我们感兴趣的东西，如果使用得当的话，爬虫可以极大地提高我们的工作效率。 那么接下去我们从一个单线程的爬虫程序出发，然后慢慢将它改造成一个并发的爬虫程序。在这里，我们并不关心究竟如何去匹配我们感兴趣的元素(例如">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:44:30.135Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Crawler">
-<meta name="twitter:description" content="爬虫算是练习并发编程的一个非常好的例子了，因为它既不枯燥，难度也不大，而且能在短时间内产出一个有趣的结果。爬虫一般通过某种搜索算法（深度优先搜索或者广度优先搜索）在互联网这个海量数据库中去寻找我们感兴趣的东西，如果使用得当的话，爬虫可以极大地提高我们的工作效率。 那么接下去我们从一个单线程的爬虫程序出发，然后慢慢将它改造成一个并发的爬虫程序。在这里，我们并不关心究竟如何去匹配我们感兴趣的元素(例如">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Crawler"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Crawler
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-05T02:05:24.000Z" itemprop="datePublished">
-        May 5, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>爬虫算是练习并发编程的一个非常好的例子了，因为它既不枯燥，难度也不大，而且能在短时间内产出一个有趣的结果。爬虫一般通过某种搜索算法（深度优先搜索或者广度优先搜索）在互联网这个海量数据库中去寻找我们感兴趣的东西，如果使用得当的话，爬虫可以极大地提高我们的工作效率。</p>
-<p>那么接下去我们从一个单线程的爬虫程序出发，然后慢慢将它改造成一个并发的爬虫程序。在这里，我们并不关心究竟如何去匹配我们感兴趣的元素(例如使用CSS进行元素匹配)，而是给出一个爬虫的基本思路。</p>
-<p>首先，爬虫中非常重要的一个步骤就是匹配当前搜索的网页中的元素，并将符合我们要求的东西下载或保存起来，并且还会记录当前网页中的超链接地址，以便于我们继续进行深度优先搜索或者广度优先搜索。一般来说，我们感兴趣的东西都是符合特定规则的，而具体的规则我们可以在单个网页上进行正则匹配来获取，但是，由于不同网页的匹配规则并不相同，所以我们定义一个interface来抽象该行为。在这之后无论我们想要爬豆瓣还是新浪微博亦或是其他自己感兴趣的网站，只要重新定义一个结构体实现该方法就可以。</p>
-<p><code>Fetcher</code> 这个 <code>interface</code> 定义了如下行为，从一个特定的url去取我们感兴趣的内容以及这个网页上的所有的url链接。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Fetcher <span class="keyword">interface</span> &#123;</span><br><span class="line">    Fetch(url <span class="keyword">string</span>) (body <span class="keyword">string</span>, urls []<span class="keyword">string</span>, err error)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>例如我们要爬豆瓣网上的东西，我们只要定义好一个结构体，并且实现上述<code>Fetch</code> 方法就可以了。所以无论以后你决定改爬别的网站了，再定义如下的结构体并实现相应的方法就可以了，这就是为什么上面我们定义了一个 <code>Fetcher</code> interface 来抽象这个行为的原因了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Result <span class="keyword">struct</span> &#123;</span><br><span class="line">    body <span class="keyword">string</span></span><br><span class="line">    urls []<span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> doubanFetcher <span class="keyword">struct</span> &#123;</span><br><span class="line">    <span class="keyword">map</span>[<span class="keyword">string</span>]*Result</span><br><span class="line">    sync.RWMutex</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *doubanFetcher)</span> <span class="title">Fetch</span><span class="params">(url <span class="keyword">string</span>)</span> <span class="params">(body <span class="keyword">string</span>, urls []<span class="keyword">string</span>, err error)</span></span> &#123;</span><br><span class="line">     <span class="comment">// 这里写具体的匹配逻辑</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>爬虫还有一个重点就是搜索的策略，应该是广度优先还是深度优先，但是所有的链接形成为拓扑图并不一定是一个有向无环图，所以我们的爬虫在爬取的过程中可能会遇到相同的链接，但是注意这个逻辑同样应在在 <code>Fetch</code> 函数中实现。</p>
-<h2 id="单线程版本实现"><a href="#单线程版本实现" class="headerlink" title="单线程版本实现"></a>单线程版本实现</h2><p>下面我们来看一下单线程深度优先的爬虫应该怎么写。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Crawl</span><span class="params">(url <span class="keyword">string</span>, depth <span class="keyword">int</span>, fetcher Fetcher)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> depth &lt;= <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    body, urls, err := fetcher.Fetch(url)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Printf(<span class="string">"Founf: %s %q\n"</span>, url, body)</span><br><span class="line">    <span class="keyword">for</span> _, u := <span class="keyword">range</span> urls &#123;</span><br><span class="line">        Crawl(u, depth<span class="number">-1</span>, fetcher)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>由于是深度优先搜索，所以我们用递归的策略来进行搜索，递归最重要的一点就是递归条件的出口条件，如果递归函数没有出口，那么就是死循环了。这里我们在函数的参数中引入一个深度的变量来控制是否应该继续进行递归，如果当前深度小于等于0，则退出。然后用 <code>fether</code>  来 <code>Fetch</code> 对应的 <code>url</code>上的内容，由于使用了接口，所以让我们这个函数的实现变得非常的灵活，而不是局限于哪个具体的实现，这就是接口的好处。然后根据当前网页中的链接进行深度优先搜索，<code>Crawl(u, depth-1, fetcher)</code> ，每搜索一层，深度减一，直到条件不再满足就可以退出了。</p>
-<p>不过上述的爬虫还是单线程的，单线程的效率肯定不高，因为程序大部分时间都是在等待 <code>I/O</code>，<code>CPU</code> 大部分时间都是空闲的，所以，为了提高 <code>CPU</code>的占用率，我们应该考虑使用并发。</p>
-<h2 id="并发版本实现"><a href="#并发版本实现" class="headerlink" title="并发版本实现"></a>并发版本实现</h2><p>在 <code>golang</code> 里面写并发程序是相对比较简单的，但是也没有那么简单，下面的实现就是比较tricky的。这里为什么叫它并发而不是多线程呢，是因为<code>golang</code> 中的 <code>go</code> 机制并不是以线程作为基本单位的。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Crawl</span><span class="params">(url <span class="keyword">string</span>, depth <span class="keyword">int</span>, fetcher Fetcher, ret <span class="keyword">chan</span> <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">defer</span> <span class="built_in">close</span>(ret)</span><br><span class="line">    <span class="keyword">if</span> depth &lt;= <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    body, urls, err := fetcher.Fetch(url) </span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        ret &lt;- err.Error()</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">     </span><br><span class="line">    ret &lt;- fmt.Sprintf(<span class="string">"Found: %s %q"</span>, url, body)</span><br><span class="line"></span><br><span class="line">    result := <span class="built_in">make</span>([]<span class="keyword">chan</span> <span class="keyword">string</span>, <span class="built_in">len</span>(urls))</span><br><span class="line">    <span class="keyword">for</span> i, u := <span class="keyword">range</span> urls &#123;</span><br><span class="line">        result := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">string</span>)</span><br><span class="line">        <span class="keyword">go</span> Crawl(u, depth<span class="number">-1</span>, fetcher, result)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> result &#123;</span><br><span class="line">        <span class="keyword">for</span> s := <span class="keyword">range</span> result[i] &#123;</span><br><span class="line">            ret &lt;- s</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>并发版本和单线程版本的基本框架是一样的，有下面几个区别。</p>
-<p>首先我们定义个一个 <code>chan string</code> 也就是一个通道，一般来说，<code>go</code> 和<code>chan</code> 都是手拉手用在一起的。这个通道用于接受我们爬虫的结果。</p>
-<p>这个通道在整个函数返回时会关闭，也就是函数最初用的 <code>defer close(ret)</code> 。</p>
-<p>当 <code>fetch.Fetch(url)</code> 方法返回时，也就是这个网页中的内容已经检索完毕了，我们将结果放到刚才的通道中等待其他地方的程序读取该通道中的内容。</p>
-<p>下面就是函数的精髓了，由于上面通过 <code>fetch.Fetch(url)</code> 获得了一个<code>urls</code> 数组，因为要进行深度优先搜索，我们为这个 <code>urls</code> 中的 <code>url</code> 也准备一个 <code>chan string</code> 用于存储它们抓取的内容，然后调用 <code>go Crawl(u, depth-1, fetcher, result)</code> 来并发爬取。</p>
-<p>也就是说下面这段函数很快就返回了，但是它们并不一定都已经拿到相应的内容了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> i, u := <span class="keyword">range</span> urls &#123;</span><br><span class="line">    result := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">string</span>)</span><br><span class="line">    <span class="keyword">go</span> Crawl(u, depth<span class="number">-1</span>, fetcher, result)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>所以，我们要等待它们拿回内容，下面代码的意思就是子任务完成后，将它拿到的内容传给上一层的通道中。这个就好比在一个公司中，<code>CEO</code> 将任务分别分配给下面各个部门的 <code>Manager</code> ，然后各个部门的 <code>Manager</code> 又细分任务后将任务分给部门下面的各个 <code>Worker</code> ，<code>Worker</code> 完成自己的任务后，将任务结果传给负责自己的 <code>Manager</code> ，然后由 <code>Manager</code> 再汇报给 <code>CEO</code> 。<code>CEO</code> 是总任务的分配者同时也是所有结果的收集者。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> i := <span class="keyword">range</span> result &#123;</span><br><span class="line">    <span class="keyword">for</span> s := <span class="keyword">range</span> result[i] &#123;</span><br><span class="line">        ret &lt;- s</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>并发程序能充分利用现在 <code>CPU</code> 的所有核心，它利用单线程程序运行中部分代码段会因为等待 <code>I/O</code>（例如发送http请求和等待http答复）而占用 <code>CPU</code> 时间的特点，同时启动多个 <code>goroutine</code> 来最大程度上占用 <code>CPU</code> 时间，从而提高程序的运行效率。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/05/WebSocket/index.html b/2018/05/05/WebSocket/index.html
deleted file mode 100644
index 69e0ed7..0000000
--- a/2018/05/05/WebSocket/index.html
+++ /dev/null
@@ -1,262 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>WebSocket | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="如果服务器会定期地更新消息，但是具体的时间间隔并不确定，客户端为了能够及时拿取最新的消息，就得不断的发送 HTTP 请求来轮询服务器，也就是说为了能够及时获取最新资讯，由于 HTTP 本身的特点，服务请求的发起方只能是客户端，服务器本身并没有消息推送的功能，这样就导致了资源浪费的问题，很多客户端发送的请求都是无效的，当客户端和服务器一对一交流时倒还好，如果很多客户端向服务器以这样的形式咨询，服务器">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="WebSocket">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/05/WebSocket/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="如果服务器会定期地更新消息，但是具体的时间间隔并不确定，客户端为了能够及时拿取最新的消息，就得不断的发送 HTTP 请求来轮询服务器，也就是说为了能够及时获取最新资讯，由于 HTTP 本身的特点，服务请求的发起方只能是客户端，服务器本身并没有消息推送的功能，这样就导致了资源浪费的问题，很多客户端发送的请求都是无效的，当客户端和服务器一对一交流时倒还好，如果很多客户端向服务器以这样的形式咨询，服务器">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="http://www.cuelogic.com/blog/wp-content/uploads/2013/11/websocketlifecycle_30624_l.png">
-<meta property="og:updated_time" content="2018-06-26T08:47:23.129Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="WebSocket">
-<meta name="twitter:description" content="如果服务器会定期地更新消息，但是具体的时间间隔并不确定，客户端为了能够及时拿取最新的消息，就得不断的发送 HTTP 请求来轮询服务器，也就是说为了能够及时获取最新资讯，由于 HTTP 本身的特点，服务请求的发起方只能是客户端，服务器本身并没有消息推送的功能，这样就导致了资源浪费的问题，很多客户端发送的请求都是无效的，当客户端和服务器一对一交流时倒还好，如果很多客户端向服务器以这样的形式咨询，服务器">
-<meta name="twitter:image" content="http://www.cuelogic.com/blog/wp-content/uploads/2013/11/websocketlifecycle_30624_l.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-WebSocket"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      WebSocket
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-05T02:52:04.000Z" itemprop="datePublished">
-        May 5, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>如果服务器会定期地更新消息，但是具体的时间间隔并不确定，客户端为了能够及时拿取最新的消息，就得不断的发送 <code>HTTP</code> 请求来轮询服务器，也就是说为了能够及时获取最新资讯，由于 <code>HTTP</code> 本身的特点，服务请求的发起方只能是客户端，服务器本身并没有消息推送的功能，这样就导致了资源浪费的问题，很多客户端发送的请求都是无效的，当客户端和服务器一对一交流时倒还好，如果很多客户端向服务器以这样的形式咨询，服务器将会承受非常大的压力了。</p>
-<p>所以，为了避免资源浪费，我们来引入 <code>WebSocket</code> 解决上述问题，<code>WebSocket</code> 可以说是 <code>HTTP</code> 协议的一个升级，它同样基于 <code>TCP</code> 之上，但与传输层的 <code>socket</code> 不同，它的 <code>socket</code> 是应用层的概念。要想使用 <code>WebSocket</code> ，客户端和服务器必须同时支持才可以使用。</p>
-<p><code>WebSocket</code> 中比较重要的一个阶段就是握手阶段了，如下图所示，客户端向服务器发送一个协议升级的 <code>HTTP</code> 请求，并且附带上一些其他的元信息用于握手。</p>
-<p><img src="http://www.cuelogic.com/blog/wp-content/uploads/2013/11/websocketlifecycle_30624_l.png" alt="WebSocket"></p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Request headers from client</span><br><span class="line"></span><br><span class="line">GET /mychat HTTP/1.1</span><br><span class="line">Host: server.example.com</span><br><span class="line">Upgrade: websocket</span><br><span class="line">Connection: Upgrade</span><br><span class="line">Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==</span><br><span class="line">Sec-WebSocket-Protocol: chat</span><br><span class="line">Sec-WebSocket-Version: 13</span><br><span class="line">Origin: http://example.com</span><br></pre></td></tr></table></figure>
-<p>服务器收到该协议升级的 <code>HTTP</code> 请求后，会返回一个 <code>HTTP</code> 答复，向客户端确认同意建立 <code>WebSocket</code> 连接，从此之后，它们之间就不再用 <code>HTTP</code> 的形式交流了，而是直接改用 <code>WebSocket</code> 格式的报文进行交流，服务器也具备了相应推送消息的能力了。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Response headers from server</span><br><span class="line"></span><br><span class="line">HTTP/1.1 101 Switching Protocols</span><br><span class="line">Upgrade: websocket</span><br><span class="line">Connection: Upgrade</span><br><span class="line">Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=</span><br><span class="line">Sec-WebSocket-Protocol: chat</span><br></pre></td></tr></table></figure>
-<p>下面我们来看一下使用 <code>&quot;github.com/gorilla/websocket&quot;</code> 时各个步骤对应的代码吧。</p>
-<p>客户端代码的风格和使用 <code>TCP</code> 进行编程非常类似，第一步，客户端向服务器发送协议升级请求，对应<br><code>websocket.DefaultDialer.Dial(u.string(), nil)</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> addr = flag.String(<span class="string">"addr"</span>, <span class="string">"localhost:8080"</span>, <span class="string">"http service addr"</span>)</span><br><span class="line">u := url.URL&#123;Scheme: <span class="string">"ws"</span>, Host: *addr, Path: <span class="string">"/echo"</span>&#125;</span><br><span class="line">log.Printf(<span class="string">"connecting to %s"</span>, u.String())</span><br><span class="line"></span><br><span class="line">c, _, err := websocket.DefaultDialer.Dial(u.<span class="keyword">string</span>(), <span class="literal">nil</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    log.Fatal(<span class="string">"dial:"</span>, err)</span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">defer</span> c.Close()</span><br></pre></td></tr></table></figure>
-<p>在服务端处理 <code>WebSocket</code> 请求与处理 <code>HTTP</code> 请求类似，我们同样需要定义一个 <code>handler</code> ，但与普通处理 <code>HTTP</code> 请求不同的是，此 <code>handler</code> 会对协议进行升级，也就是 <code>upgrader.Upgrade(w, r, nil)</code> ，这段代码相当于服务端向客户端发送一个协议升级的确认消息。在这之后，服务器就可以一直读取客户端发来的请求和向客户端返回答复了（代码的逻辑在 <code>for</code> 循环之中），也就是说服务器只起了一个 <code>handler</code> 来处理这段 <code>session</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">echo</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    c, err := upgrader.Upgrade(w, r, <span class="literal">nil</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Print(<span class="string">"upgrade:"</span>, err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> c.Close()</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        mt, message, err := c.ReadMessage()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(<span class="string">"read:"</span>, err)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">        log.Printf(<span class="string">"recv: %s"</span>, message)</span><br><span class="line">        err = c.WriteMessage(mt, message)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(<span class="string">"write:"</span>, err)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    http.HandleFunc(<span class="string">"echo"</span>, echo)</span><br><span class="line">    log.Fatal(http.ListenAndServe(*addr, <span class="literal">nil</span>))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>客户端在握手之后就可以读取和发送数据，在这里，由于在 <code>WebSocket</code> 中服务器可以主动向客户端推送数据，所以我们起一个 <code>goroutine</code> 专门用于接受服务器主动推送的数据（ <code>c.ReadMessage()</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">done := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line"></span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">defer</span> <span class="built_in">close</span>(done)</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        _, message, err := c.ReadMessage()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(<span class="string">"read:"</span>, err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        log.Printf(<span class="string">"recv:"</span>, message)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面是客户端发送数据的逻辑，这里我们每隔一秒钟向服务器发送当前的时间，<code>c.WriteMessage(websocket.TextMessage, []byte(t.string()))</code> ，这里我们注意到，<code>WebSocket</code> 中的消息是有类型的，这个函数的第一个参数就是指明该消息的类型，这里我们使用 <code>websocket.TextMessage</code> 。</p>
-<p>那么如何让这段 <code>session</code> 结束呢，结束会话一般来说都是客户端主动发起的，客户端主要发送一个结束对话的消息类型就可以了，<br><code>c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, &quot;&quot;))</code> ，这里注意该结束对话的消息类型为 <code>websocket.CloseMessage</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">ticker := time.NewTicker(time.Second)</span><br><span class="line"><span class="keyword">defer</span> ticker.Stop()</span><br><span class="line"></span><br><span class="line">interrupt := <span class="built_in">make</span>(<span class="keyword">chan</span> os.Signal, <span class="number">1</span>)</span><br><span class="line">signal.Notify(interrupt, os.Interrupt)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> &#123;</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> &lt;-done:</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    <span class="keyword">case</span> t := &lt;-ticker.C:</span><br><span class="line">        err := c.WriteMessage(websocket.TextMessage, []<span class="keyword">byte</span>(t.String()))</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(<span class="string">"write:"</span>, err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    <span class="keyword">case</span> &lt;-interrupt:</span><br><span class="line">        log.Println(<span class="string">"interrupt"</span>)</span><br><span class="line">        </span><br><span class="line">        err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, <span class="string">""</span>))</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(<span class="string">"write close:"</span>, err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> &lt;-done:</span><br><span class="line">        <span class="keyword">case</span> &lt;-time.After(time.Second)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/05/dep/index.html b/2018/05/05/dep/index.html
deleted file mode 100644
index 8b8f1c8..0000000
--- a/2018/05/05/dep/index.html
+++ /dev/null
@@ -1,263 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>dep | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在写大型工程项目的时候，难免会依赖第三方的库（自己重复造轮子肯定不现实），如果依赖的库数量非常多时，自己去手动管理肯定是不现实的，所以我们需要一个依赖管理工具帮助我们管理依赖的库。就像 node 有 npm ，java 有 maven 。而 golang 之前一直没有一个官方推荐的依赖管理工具，所以第三方的依赖管理工具 glide ，govendor 之类的就应运而生，但由于不是官方出品的，自己用">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="dep">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/05/dep/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在写大型工程项目的时候，难免会依赖第三方的库（自己重复造轮子肯定不现实），如果依赖的库数量非常多时，自己去手动管理肯定是不现实的，所以我们需要一个依赖管理工具帮助我们管理依赖的库。就像 node 有 npm ，java 有 maven 。而 golang 之前一直没有一个官方推荐的依赖管理工具，所以第三方的依赖管理工具 glide ，govendor 之类的就应运而生，但由于不是官方出品的，自己用">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://github.com/golang/dep/raw/master/docs/assets/DigbyShadows.png">
-<meta property="og:updated_time" content="2018-06-26T08:44:58.241Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="dep">
-<meta name="twitter:description" content="在写大型工程项目的时候，难免会依赖第三方的库（自己重复造轮子肯定不现实），如果依赖的库数量非常多时，自己去手动管理肯定是不现实的，所以我们需要一个依赖管理工具帮助我们管理依赖的库。就像 node 有 npm ，java 有 maven 。而 golang 之前一直没有一个官方推荐的依赖管理工具，所以第三方的依赖管理工具 glide ，govendor 之类的就应运而生，但由于不是官方出品的，自己用">
-<meta name="twitter:image" content="https://github.com/golang/dep/raw/master/docs/assets/DigbyShadows.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-dep"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      dep
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-05T02:47:24.000Z" itemprop="datePublished">
-        May 5, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在写大型工程项目的时候，难免会依赖第三方的库（自己重复造轮子肯定不现实），如果依赖的库数量非常多时，自己去手动管理肯定是不现实的，所以我们需要一个依赖管理工具帮助我们管理依赖的库。就像 <code>node</code> 有 <code>npm</code> ，<code>java</code> 有 <code>maven</code> 。而 <code>golang</code> 之前一直没有一个官方推荐的依赖管理工具，所以第三方的依赖管理工具 <code>glide</code> ，<code>govendor</code> 之类的就应运而生，但由于不是官方出品的，自己用起来心里总有些毛毛的，后来，<code>golang</code> 官方终于推出了 <code>dep</code> 这个依赖管理工具，终于给我们这些强迫症患者安了一个心。下面我们就以一个demo为例子，看看<code>dep</code> 如何使用吧。</p>
-<p><img src="https://github.com/golang/dep/raw/master/docs/assets/DigbyShadows.png" alt="godep"></p>
-<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>由于 <code>dep</code> 是一个命令行工具，安装起来也非常的方便，下面给出两种安装方式。</p>
-<h4 id="二进制安装"><a href="#二进制安装" class="headerlink" title="二进制安装"></a>二进制安装</h4><p>这种安装方法通用型比较强，下面的命令会根据你的操作系统直接安装相应的二进制。</p>
-<p><code>$ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh</code></p>
-<h4 id="macOS-安装"><a href="#macOS-安装" class="headerlink" title="macOS 安装"></a>macOS 安装</h4><p>但是 <code>macOS</code> 用户一般还是比较习惯于使用<code>brew</code> 的，使用 <code>brew</code> 也是<code>no-brainer</code> 。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ brew install dep</span><br><span class="line">$ brew upgrade dep</span><br></pre></td></tr></table></figure>
-<h2 id="vendor-机制"><a href="#vendor-机制" class="headerlink" title="vendor 机制"></a>vendor 机制</h2><p>要了解 <code>dep</code> 存在的必要性就不得不提 <code>vendor</code> 机制了，我们都知道如果我们在 <code>go</code> 文件中导入一个非标准库，在编译时 <code>go</code> 会在 <code>$GOPATH</code> 下面去寻找它，但是这就导致一个问题，如果两个项目A和B同时用到了这个库，但是A和B对这个库的版本需求是不同的，这样就很难办了，毕竟在 <code>$GOPATH</code> 下面只能存在一个版本的库，所以为了解决这种情况，在<code>Go1.5</code>的时候，就出现 <code>vendor</code> 文件夹这个机制，也就是说，<code>go</code> 在编译项目的时候，会去这个项目目录下面寻找是否存在 <code>vendor</code> 这个文件夹，并且 <code>vendor</code> 下面是否存在我们需要的库，如果有则使用它，如果没有则去 <code>$GOPATH</code> 下去寻找。</p>
-<p>例如项目C依赖 <code>github.com/aaa/bbb</code> 这个库，那么 <code>go</code> 在编译时回去查看当前项目目录下有没有<code>vendor/github.com/aaa/bbb</code> 这个文件夹目录，如果有则使用这个版本，如果没有再去 <code>$GOPATH</code> 下面去找。而 <code>dep</code> 就是为了帮我们管理 <code>vendor</code> 这个目录下面的依赖而存在的。</p>
-<h2 id="新建项目"><a href="#新建项目" class="headerlink" title="新建项目"></a>新建项目</h2><p>例如我们要写一个与 <code>WebSocket</code> 相关的项目，无奈 <code>golang</code> 的标准库里实现的 <code>WebSocket</code> 我们并不是非常满意，所以我们去 <code>github</code> 上面搜了一下，最后发现 <code>girilla</code> 家的 <code>websocket</code> 库还是比较符合我们项目的需求的，所以决定使用它。</p>
-<p>第一步就是新建一个 <code>dep</code> 项目，使用 <code>dep init</code> 命令，会帮我们生成两个文件和一个空的 <code>vendor</code> 文件夹。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ dep init</span><br><span class="line">$ ls</span><br><span class="line">Gopkg.toml Gopkg.lock vendor/</span><br></pre></td></tr></table></figure>
-<p>然后我们写了一个 <code>main.go</code> 文件用于存放我们项目的所有逻辑（bad practice），这个文件除了标准库之外当然还导入了我们需要的 <code>websocket</code> 依赖。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> (</span><br><span class="line">    <span class="string">"flag"</span></span><br><span class="line">    <span class="string">"html/template"</span></span><br><span class="line">    <span class="string">"io/ioutil"</span></span><br><span class="line">    <span class="string">"log"</span></span><br><span class="line">    <span class="string">"net/http"</span></span><br><span class="line">    <span class="string">"os"</span></span><br><span class="line">    <span class="string">"strconv"</span></span><br><span class="line">    <span class="string">"time"</span></span><br><span class="line">    </span><br><span class="line">    <span class="string">"github.com/gorilla/websocket"</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure>
-<p>编辑完之后，在命令行中输入 <code>dep ensure</code> ，<code>dep</code> 会扫描我们当前项目中所有的依赖，并找出我们依赖的三方库，然后更新相应的文件（Gopkg.toml 和 Gopkg.lock），并更新我们的 <code>vendor</code> 文件夹，如下所示。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">.</span><br><span class="line">├── Gopkg.lock</span><br><span class="line">├── Gopkg.toml</span><br><span class="line">├── main.go</span><br><span class="line">└── vendor</span><br><span class="line">    └── github.com</span><br><span class="line">        └── gorilla</span><br><span class="line">            └── websocket</span><br><span class="line">                ├── AUTHORS</span><br><span class="line">                ├── LICENSE</span><br><span class="line">                ├── README.md</span><br><span class="line">                ├── client.go</span><br><span class="line">                ├── client_clone.go</span><br><span class="line">                ├── client_clone_legacy.go</span><br><span class="line">                ├── compression.go</span><br><span class="line">                ├── conn.go</span><br><span class="line">                ├── conn_read.go</span><br><span class="line">                ├── conn_read_legacy.go</span><br><span class="line">                ├── doc.go</span><br><span class="line">                ├── json.go</span><br><span class="line">                ├── mask.go</span><br><span class="line">                ├── mask_safe.go</span><br><span class="line">                ├── prepared.go</span><br><span class="line">                ├── server.go</span><br><span class="line">                └── util.go</span><br></pre></td></tr></table></figure>
-<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>反正以后用 <code>dep</code> 作为go项目的依赖管理工具准没错的，如果你用 <code>glide</code> 或者 <code>govendor</code> 之类的还是趁早投靠 <code>dep</code> 吧。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/06/PubSub/index.html b/2018/05/06/PubSub/index.html
deleted file mode 100644
index 94e37c0..0000000
--- a/2018/05/06/PubSub/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>PubSub | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="消息的发布和订阅这种设计模式在大型开源项目中还是会经常被使用到的，它的要点是一堆消息订阅者（ Subscriber ）会订阅某个自己感兴趣的 topic ，一旦发布者（ Publisher ）向这个 topic 发布消息，消息的订阅者就能收到该消息。 这种设计模式的灵感其实就来自于现实生活之中，我们（ Subscriber ）向我们感兴趣的杂志社订阅想要阅读的月刊，那么我们订阅的消息（算一个 su">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="PubSub">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/06/PubSub/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="消息的发布和订阅这种设计模式在大型开源项目中还是会经常被使用到的，它的要点是一堆消息订阅者（ Subscriber ）会订阅某个自己感兴趣的 topic ，一旦发布者（ Publisher ）向这个 topic 发布消息，消息的订阅者就能收到该消息。 这种设计模式的灵感其实就来自于现实生活之中，我们（ Subscriber ）向我们感兴趣的杂志社订阅想要阅读的月刊，那么我们订阅的消息（算一个 su">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://docs.oracle.com/cd/E19575-01/819-3669/images/jms-publishSubscribe.gif">
-<meta property="og:updated_time" content="2018-06-26T08:48:18.224Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="PubSub">
-<meta name="twitter:description" content="消息的发布和订阅这种设计模式在大型开源项目中还是会经常被使用到的，它的要点是一堆消息订阅者（ Subscriber ）会订阅某个自己感兴趣的 topic ，一旦发布者（ Publisher ）向这个 topic 发布消息，消息的订阅者就能收到该消息。 这种设计模式的灵感其实就来自于现实生活之中，我们（ Subscriber ）向我们感兴趣的杂志社订阅想要阅读的月刊，那么我们订阅的消息（算一个 su">
-<meta name="twitter:image" content="https://docs.oracle.com/cd/E19575-01/819-3669/images/jms-publishSubscribe.gif">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-PubSub"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      PubSub
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-06T11:08:04.000Z" itemprop="datePublished">
-        May 6, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>消息的发布和订阅这种设计模式在大型开源项目中还是会经常被使用到的，它的要点是一堆消息订阅者（ <code>Subscriber</code> ）会订阅某个自己感兴趣的 <code>topic</code> ，一旦发布者（ <code>Publisher</code> ）向这个 <code>topic</code> 发布消息，消息的订阅者就能收到该消息。</p>
-<p>这种设计模式的灵感其实就来自于现实生活之中，我们（ <code>Subscriber</code> ）向我们感兴趣的杂志社订阅想要阅读的月刊，那么我们订阅的消息（算一个 <code>subscription</code> ）就会被杂志社（ <code>Publisher</code> ）记录下来，一旦杂志可以上市发行了，杂志社就会主动向我们推送（ <code>Publish</code> ）杂志消息。</p>
-<p><img src="https://docs.oracle.com/cd/E19575-01/819-3669/images/jms-publishSubscribe.gif" alt="PubSub"></p>
-<p>下面我们来实现一个简单的发布者订阅者模型吧。</p>
-<p>由于这个模型的核心就在于很多 <code>subscriber</code> 会向某一个 <code>topic</code> 订阅消息，所以需要一个结构体来记录特定的 <code>topic</code> 对应的所有 <code>subscriber</code> ，这里 <code>subscriber</code> 用一个集合（ <code>Set</code> ）来表示。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> PubSub <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.RWMutex</span><br><span class="line">    subscriptions <span class="keyword">map</span>[<span class="keyword">string</span>]*Set</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Set <span class="keyword">struct</span> &#123;</span><br><span class="line">    items <span class="keyword">map</span>[<span class="keyword">interface</span>&#123;&#125;]<span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    lock *sync.RWMutex</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewPubSub</span><span class="params">()</span> *<span class="title">PubSub</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;PubSub&#123;</span><br><span class="line">        subscriptions: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]*Set),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Subscription</code> 应该具有监听行为，通过 <code>Listen</code> 来获取 <code>Publisher</code> 发布的消息。而结构体 <code>subscription</code> 则相当于一个订阅的注册信息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Subscription <span class="keyword">interface</span> &#123;</span><br><span class="line">    Listen() (<span class="keyword">interface</span>&#123;&#125;, error)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> subscription <span class="keyword">struct</span> &#123;</span><br><span class="line">    topic <span class="keyword">string</span></span><br><span class="line">    ttl   time.Duration</span><br><span class="line">    c     <span class="keyword">chan</span> <span class="keyword">interface</span>&#123;&#125;    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> (s *subscription) Listen() (<span class="keyword">interface</span>&#123;&#125;, error) &#123;</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> &lt;-time.After(s.ttl):</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, errors.New(<span class="string">"timed out"</span>)</span><br><span class="line">    <span class="keyword">case</span> iterm := &lt;-s.c:</span><br><span class="line">        <span class="keyword">return</span> item, <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>其实订阅和取消订阅的本质就是将自己从订阅名单（ <code>subscriptions map[string]*Set</code> ）里面进行增加或删除的操作，因为我们向杂志社订阅了某本杂志，那么关于我们的订阅信息一定会在杂志出版商那里存在。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(ps *PubSub)</span> <span class="title">Subscribe</span><span class="params">(topic <span class="keyword">string</span>, ttl time.Duration)</span> <span class="title">Subscription</span></span> &#123;</span><br><span class="line">    sub := &amp;subscription&#123;</span><br><span class="line">        topic: topic.</span><br><span class="line">        ttl:   ttl,</span><br><span class="line">        c:     <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">interface</span>&#123;&#125;, subscriptionBuffSize),</span><br><span class="line">    &#125;</span><br><span class="line">    ps.Lock()</span><br><span class="line">    s, exists := ps.subscriptions[topic]</span><br><span class="line">    <span class="keyword">if</span> !exists &#123;</span><br><span class="line">        s = NewSet()</span><br><span class="line">        ps.subscriptions[topic] = s</span><br><span class="line">    &#125;</span><br><span class="line">    ps.Unlock()</span><br><span class="line"></span><br><span class="line">    s.Add(sub)</span><br><span class="line">    time.AfterFunc(ttl, <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        ps.unSubscribe(sub)</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(ps *PubSub)</span> <span class="title">unSubscribe</span><span class="params">(sub *subscription)</span></span> &#123;</span><br><span class="line">    ps.Lock()</span><br><span class="line">    <span class="keyword">defer</span> ps.Unlock()</span><br><span class="line">    ps.subscriptions[sub.topic].Remove(sub)</span><br><span class="line">    <span class="keyword">if</span> ps.subscriptions[sub.topic].Size() != <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">delete</span>(ps.subscriptions, sub.topic)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>最后我们订阅的杂志终于要发布了，杂志的出版社会根据自己手中的订阅名单，逐一向订阅该 <code>topic</code> 的订阅者发送杂志，当然只有订阅了的人才能收到。但是由于订阅者可能出去旅游了，也就是说他最近并没有调用 <code>Listen</code> 将收到的订阅消息拿出，而我们接受订阅消息的邮箱大小是有上限的（ <code>c: make(chan interface{}, subscriptionBuffSize)</code> ，我们设置了<code>subscriptionBuffSize</code> 来表示一个通道中最多可以存放的消息数量），如果该邮箱内已有的消息超出这个限制，则选择不将消息放入邮箱中，否则则将消息放入这个邮箱中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(ps *PubSub)</span> <span class="title">Publish</span><span class="params">(topic <span class="keyword">string</span>, item <span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    ps.RLock()</span><br><span class="line">    <span class="keyword">defer</span> ps.RUnlock()</span><br><span class="line">    s, subscribed := ps.subscriptions[topic]</span><br><span class="line">    <span class="keyword">if</span> !subscribed &#123;</span><br><span class="line">        <span class="keyword">return</span> errors.New(<span class="string">"no subscribers"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> _, sub := <span class="keyword">range</span> s.ToArray() &#123;</span><br><span class="line">        c := sub.(*subscription).c</span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(c) == subscriptionBuffSize &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125;</span><br><span class="line">        c &lt;- item</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Publish-subscribe-server"><a href="#Publish-subscribe-server" class="headerlink" title="Publish/subscribe server"></a>Publish/subscribe server</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Server <span class="keyword">struct</span> &#123;</span><br><span class="line">    publish   <span class="keyword">chan</span> Event</span><br><span class="line">    subscribe <span class="keyword">chan</span> subReq</span><br><span class="line">    cancel    <span class="keyword">chan</span> subaReq</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> subReq <span class="keyword">struct</span> &#123;</span><br><span class="line">    c  <span class="keyword">chan</span>&lt;- Event</span><br><span class="line">    ok <span class="keyword">chan</span> <span class="keyword">bool</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Server)</span> <span class="title">Init</span><span class="params">()</span></span> &#123;</span><br><span class="line">    s.publish = <span class="built_in">make</span>(<span class="keyword">chan</span> Event)</span><br><span class="line">    s.subscribe = <span class="built_in">make</span>(<span class="keyword">chan</span> subReq)</span><br><span class="line">    s.cancel = <span class="built_in">make</span>(<span class="keyword">chan</span> subReq)</span><br><span class="line">    <span class="keyword">go</span> s.loop()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Server)</span> <span class="title">Publish</span><span class="params">(e Event)</span></span> &#123;</span><br><span class="line">    s.publish &lt;- e</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Server)</span> <span class="title">Subscribe</span><span class="params">(c <span class="keyword">chan</span>&lt;- Event)</span></span> &#123;</span><br><span class="line">    r := subReq&#123;c: c, ok: <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)&#125;</span><br><span class="line">    s.subscribe &lt;- r</span><br><span class="line">    <span class="keyword">if</span> !&lt;-r.ok &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"pubsub: already subscribed"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Server)</span> <span class="title">Cancel</span><span class="params">(c <span class="keyword">chan</span>&lt;- Event)</span></span> &#123;</span><br><span class="line">    r := subReq&#123;c: c, ok: <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)&#125;</span><br><span class="line">    s.cancel &lt;- r</span><br><span class="line">    <span class="keyword">if</span> !&lt;-r.ok &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"pubsub: not subscribed"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Server)</span> <span class="title">loop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    sub := <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">chan</span>&lt;- Event]<span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> e := &lt;-s.publish:</span><br><span class="line">            <span class="keyword">for</span> c := <span class="keyword">range</span> sub &#123;</span><br><span class="line">                c &lt;- e      </span><br><span class="line">            &#125;</span><br><span class="line">        <span class="keyword">case</span> r := &lt;-s.subscribe:</span><br><span class="line">            <span class="keyword">if</span> sub[r.c] &#123;</span><br><span class="line">                r.ok &lt;- <span class="literal">false</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            &#125;</span><br><span class="line">            sub[r.c] = <span class="literal">true</span></span><br><span class="line">            r.ok &lt;- <span class="literal">true</span></span><br><span class="line">        <span class="keyword">case</span> r := &lt;-s.cancel:</span><br><span class="line">            <span class="keyword">if</span> !sub[r.c] &#123;</span><br><span class="line">                r.ok &lt;- <span class="literal">false</span></span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in">close</span>(r.c)</span><br><span class="line">            <span class="built_in">delete</span>(sub, r.c)</span><br><span class="line">            r.ok &lt;- <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/07/MagnetLink/index.html b/2018/05/07/MagnetLink/index.html
deleted file mode 100644
index acf897e..0000000
--- a/2018/05/07/MagnetLink/index.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Magnet Link | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="相信大部分人都使用过磁力链接来下载过网上的文件吧，但是估计很少人会去关心那稀奇古怪的磁力链接究竟是什么鬼，今天就让我们来解析一下磁力链接，看一下它里面隐藏的信息吧。 其实类似下面这种看似复杂的链接地址也就是由几个部分组成，开头的 magnet 我们把它称为 scheme 或者说是协议名，就像一般的 http 地址一样，http 也算是一种协议名，紧接着 magnet:? 后面就是几对键值对了，一般">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Magnet Link">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/07/MagnetLink/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="相信大部分人都使用过磁力链接来下载过网上的文件吧，但是估计很少人会去关心那稀奇古怪的磁力链接究竟是什么鬼，今天就让我们来解析一下磁力链接，看一下它里面隐藏的信息吧。 其实类似下面这种看似复杂的链接地址也就是由几个部分组成，开头的 magnet 我们把它称为 scheme 或者说是协议名，就像一般的 http 地址一样，http 也算是一种协议名，紧接着 magnet:? 后面就是几对键值对了，一般">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:51.394Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Magnet Link">
-<meta name="twitter:description" content="相信大部分人都使用过磁力链接来下载过网上的文件吧，但是估计很少人会去关心那稀奇古怪的磁力链接究竟是什么鬼，今天就让我们来解析一下磁力链接，看一下它里面隐藏的信息吧。 其实类似下面这种看似复杂的链接地址也就是由几个部分组成，开头的 magnet 我们把它称为 scheme 或者说是协议名，就像一般的 http 地址一样，http 也算是一种协议名，紧接着 magnet:? 后面就是几对键值对了，一般">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-MagnetLink"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Magnet Link
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-07T07:15:24.000Z" itemprop="datePublished">
-        May 7, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>相信大部分人都使用过磁力链接来下载过网上的文件吧，但是估计很少人会去关心那稀奇古怪的磁力链接究竟是什么鬼，今天就让我们来解析一下磁力链接，看一下它里面隐藏的信息吧。</p>
-<p>其实类似下面这种看似复杂的链接地址也就是由几个部分组成，开头的 <code>magnet</code> 我们把它称为 <code>scheme</code> 或者说是协议名，就像一般的 <code>http</code> 地址一样，<code>http</code> 也算是一种协议名，紧接着 <code>magnet:?</code> 后面就是几对键值对了，一般键值对之间以 <code>&amp;</code> 符号划分，常见的键有：</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">magnet:?xt=urn:btih:0FF55426B9713084FF5229A16D21712B1E6C1625&amp;dn=%e5%8d%97%e5%be%81%e5%8c%97%e6%88%98%20-%206415&amp;tr=http%3a%2f%2ftracker.nexushd.org%2fannounce.php%3fpasskey%3d346ae8170f8427b078512150f3683285</span><br></pre></td></tr></table></figure>
-<ul>
-<li><code>xt</code> ：eXact Topic 的缩写，其实本质上就是一个文件的哈希值，用于唯一标示这个文件而存在的，这是整个磁力链接中不可或缺的一部分，少了它，基本上链接地址就无法解析了。</li>
-<li><code>dn</code> ：Display Name 的缩写，这个是用于向用户展示的文件的名称，这一项可以没有。</li>
-<li><code>tr</code> ： Tracker 的缩写，表示Tracker服务器的地址，取决于使用的技术，这一项也是选填的。</li>
-<li><code>ws</code> ： Web Seed 的缩写，表示网络种子，选填。</li>
-<li><code>urn</code> ：Uniform Resource Name 的缩写，也就是统一资源名称。</li>
-<li><code>btih</code> ： BitTorrent Info Hash 的缩写，表示种子的散列函数。</li>
-</ul>
-<p>知道了磁力链接地址中的关键信息，也就基本可以看懂链接地址中的各个部分分别代表什么含义了，但是由于其中一些信息还是经过特殊编码的，人类读起来还是比较费劲<br>的，所以我们还是实现代码来解析它吧。</p>
-<p>首先，来定义一个结构体来定义一下磁力链接中的组成部分，这里只选了几个重要的，<code>InfoHash</code> 代表的就是 <code>&quot;urn:btih:&quot;</code> 后面那一部分玩意儿，<code>Trackers</code> 数组代表的就是 <code>Tracker</code> 服务器的地址，<code>DisplayName</code> 就对应磁力链接中的 <code>dn</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Magnet <span class="keyword">struct</span> &#123;</span><br><span class="line">    InfoHash Hash</span><br><span class="line">    Trackers []<span class="keyword">string</span></span><br><span class="line">    DisplayName <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> xtPrefix = <span class="string">"urn:btih:"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m Magnet)</span> <span class="title">String</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    ret : = <span class="string">"magnet:?xt="</span></span><br><span class="line">    ret += xtPrefix + hex.EncodeToString(m.InfoHash[:])</span><br><span class="line">    <span class="keyword">if</span> m.DisplayName != <span class="string">""</span> &#123;</span><br><span class="line">        ret += <span class="string">"&amp;dn="</span> + url.QueryEscape(m.DisplayName)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> _, tr := <span class="keyword">range</span> m.Trackers &#123;</span><br><span class="line">        ret += <span class="string">"&amp;tr="</span> + url.QueryEscape(tr)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ret</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>解析磁力链接的过程和解析一般的 <code>url</code> 的过程非常类似，关键的部分是哈希值部分的解析，由于 <code>BTIH</code> 这个部分的哈希值可能用 <code>Hex</code> 编码也可能用 <code>Base32</code> 编码，所以我们要根据其哈希长度选择解码的方式，这里定义了一个函数变量 <code>var decode func(dst, src []byte) (int, error)</code> 用于接受我们具体的解码函数。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ParseMagnetURI</span><span class="params">(uri <span class="keyword">string</span>)</span> <span class="params">(m Magnet, err eror)</span></span> &#123;</span><br><span class="line">    u, err := url.Parse(uri)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        err = fmt.Errorf(<span class="string">"error parsing uri : %s"</span>, err) </span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> u.Scheme != <span class="string">"magnet"</span> &#123;</span><br><span class="line">        err = fmt.Errorf(<span class="string">"unexpected scheme: %q"</span>, u.Scheme)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    xt := u.Query().Get(<span class="string">"xt"</span>)</span><br><span class="line">    <span class="keyword">if</span> !strings.HasPrefix(xtPrefix) &#123;</span><br><span class="line">        err = fmt.Errorf(<span class="string">"bad xt parameter"</span>)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    infoHash := xt[<span class="built_in">len</span>(xtPrefix):]</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> decode <span class="function"><span class="keyword">func</span><span class="params">(dst, src []<span class="keyword">byte</span>)</span> <span class="params">(<span class="keyword">int</span>, error)</span></span></span><br><span class="line"><span class="function">    <span class="title">switch</span> <span class="title">len</span><span class="params">(infoHash)</span></span> &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">40</span>:</span><br><span class="line">        decode = hex.Decode</span><br><span class="line">    <span class="keyword">case</span> <span class="number">32</span>:</span><br><span class="line">        decode = base32.StdEncoding.Decode</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> decode == <span class="literal">nil</span> &#123;</span><br><span class="line">        err = fmt.Errorf(<span class="string">"unhandled xt parameter encoding: encoded lenght"</span>, <span class="built_in">len</span>(infoHash))</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    n, err := decode(m.InfoHash[:], []<span class="keyword">byte</span>(infoHash))</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        err = fmt.Errorf(<span class="string">"error decoding xt: %s"</span>, err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> n != <span class="number">20</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(n)</span><br><span class="line">    &#125;</span><br><span class="line">    m.DisplayName = u.Query().Get(<span class="string">"dn"</span>)</span><br><span class="line">    m.Trackers = u.Query()[<span class="string">"tr"</span>]</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/08/ColorfulPrinting/index.html b/2018/05/08/ColorfulPrinting/index.html
deleted file mode 100644
index 8673d99..0000000
--- a/2018/05/08/ColorfulPrinting/index.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Colorful Printing | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="平时在使用一些命令行工具时，是否经常注意到彩色的 log 打出来呢，然而自己写的命令行工具永远都是清一色白底黑字（或者黑底白字）的输出，是不是会怀疑别人施了黑魔法才让输出变得五彩斑斓，其实要让命令行输出彩色字体并没有那么难，关键就在对其规则的把握。 为了让字符变色，我们需要规定其伴随的属性，一般来说属性有以下几类。  基本属性，例如字体粗细，是否为斜体等等 前景字体颜色 前景字体颜色（强烈版） 背">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Colorful Printing">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/08/ColorfulPrinting/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="平时在使用一些命令行工具时，是否经常注意到彩色的 log 打出来呢，然而自己写的命令行工具永远都是清一色白底黑字（或者黑底白字）的输出，是不是会怀疑别人施了黑魔法才让输出变得五彩斑斓，其实要让命令行输出彩色字体并没有那么难，关键就在对其规则的把握。 为了让字符变色，我们需要规定其伴随的属性，一般来说属性有以下几类。  基本属性，例如字体粗细，是否为斜体等等 前景字体颜色 前景字体颜色（强烈版） 背">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:44:13.937Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Colorful Printing">
-<meta name="twitter:description" content="平时在使用一些命令行工具时，是否经常注意到彩色的 log 打出来呢，然而自己写的命令行工具永远都是清一色白底黑字（或者黑底白字）的输出，是不是会怀疑别人施了黑魔法才让输出变得五彩斑斓，其实要让命令行输出彩色字体并没有那么难，关键就在对其规则的把握。 为了让字符变色，我们需要规定其伴随的属性，一般来说属性有以下几类。  基本属性，例如字体粗细，是否为斜体等等 前景字体颜色 前景字体颜色（强烈版） 背">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ColorfulPrinting"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Colorful Printing
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-08T11:48:24.000Z" itemprop="datePublished">
-        May 8, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>平时在使用一些命令行工具时，是否经常注意到彩色的 <code>log</code> 打出来呢，然而自己写的命令行工具永远都是清一色白底黑字（或者黑底白字）的输出，是不是会怀疑别人施了黑魔法才让输出变得五彩斑斓，其实要让命令行输出彩色字体并没有那么难，关键就在对其规则的把握。</p>
-<p>为了让字符变色，我们需要规定其伴随的属性，一般来说属性有以下几类。</p>
-<ul>
-<li>基本属性，例如字体粗细，是否为斜体等等</li>
-<li>前景字体颜色</li>
-<li>前景字体颜色（强烈版）</li>
-<li>背景字体颜色</li>
-<li>背景字体颜色（强烈版）</li>
-</ul>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Base attributes</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    Reset Attribute = <span class="literal">iota</span></span><br><span class="line">    Bold</span><br><span class="line">    Faint</span><br><span class="line">    Italic</span><br><span class="line">    Underline</span><br><span class="line">    BlinkSlow</span><br><span class="line">    BlinkRapid</span><br><span class="line">    ReverseVideo</span><br><span class="line">    Concealed</span><br><span class="line">    CrossedOut</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Foreground text colors</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    FgBlack Attribute = <span class="literal">iota</span> + <span class="number">30</span></span><br><span class="line">    FgRed</span><br><span class="line">    FgGreen</span><br><span class="line">    FgYellow</span><br><span class="line">    FgBlue</span><br><span class="line">    FgMagenta</span><br><span class="line">    FgCyan</span><br><span class="line">    FgWhite</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Foreground Hi-Intensity text colors</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    FgHiBlack Attribute = <span class="literal">iota</span> + <span class="number">90</span></span><br><span class="line">    FgHiRed</span><br><span class="line">    FgHiGreen</span><br><span class="line">    FgHiYellow</span><br><span class="line">    FgHiBlue</span><br><span class="line">    FgHiMagenta</span><br><span class="line">    FgHiCyan</span><br><span class="line">    FgHiWhite</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Background text colors</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    BgBlack Attribute = <span class="literal">iota</span> + <span class="number">40</span></span><br><span class="line">    BgRed</span><br><span class="line">    BgGreen</span><br><span class="line">    BgYellow</span><br><span class="line">    BgBlue</span><br><span class="line">    BgMagenta</span><br><span class="line">    BgCyan</span><br><span class="line">    BgWhite</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment">// Background Hi-Intensity text colors</span></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    BgHiBlack Attribute = <span class="literal">iota</span> + <span class="number">100</span></span><br><span class="line">    BgHiRed</span><br><span class="line">    BgHiGreen</span><br><span class="line">    BgHiYellow</span><br><span class="line">    BgHiBlue</span><br><span class="line">    BgHiMagenta</span><br><span class="line">    BgHiCyan</span><br><span class="line">    BgHiWhite</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
-<p>让字符变色的关键在于转义字符的使用，转义字符对每个程序员来说肯定都不陌生，它的作用就是让紧随其后的字符变成其他含义，所谓转义转义就是这个意思，我们这里要使用的转义字符是 <code>\x1b</code> ，或者写作  <code>\033</code> ，二者都是可以的，因为十六进制的 <code>1b</code> 和八进制的 <code>33</code> 相等。</p>
-<p>下面我们定义一个 <code>Color</code> 结构体，里面包含一个属性数组，规定了我们的文字会变化成什么样。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> escape = <span class="string">"\x1b"</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Attribute <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Color <span class="keyword">struct</span> &#123;</span><br><span class="line">    params []Attribute</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(value ...Attribute)</span> *<span class="title">Color</span></span> &#123;</span><br><span class="line">    c := &amp;Color&#123;params: <span class="built_in">make</span>([]Attribute, <span class="number">0</span>)&#125;</span><br><span class="line">    c.params = <span class="built_in">append</span>(c.params, value...)</span><br><span class="line">    <span class="keyword">return</span> c</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>例如一段文字 <code>how are you?</code> ，我们想要把把中间的 <code>are</code> 变为绿色，我们应该怎么办呢，其实就是分别在 <code>are</code> 的前后加上一些修饰符。</p>
-<p>在 <code>are</code> 的前面加上 <code>\x1b[32m</code> 表示从这之后将后面的字变为绿色。<br>而在 <code>are</code> 的后面加上 <code>\x1b[0m</code> 则表示结束属性变化。</p>
-<p>所以我们在开始变化的时候加上 <code>fmt.Sprintf(&quot;%s[%sm&quot;, escape, c.sequence())</code> ，这里的 <code>escape</code> 就是我们之前提过的转义字符，而 <code>c.sequence()</code> 就是我们规定的属性。</p>
-<p>在变化结束的时候加上 <code>fmt.Sprintf(&quot;%s[%dm&quot;, escape, Reset)</code> ，这里 <code>Reset</code> 就表示重置变化，其值为0。</p>
-<p>注意如果有多个属性，我们使用 <code>;</code> 连接就可以了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">sequence</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    format := <span class="built_in">make</span>([]<span class="keyword">string</span>, <span class="built_in">len</span>(c.params))</span><br><span class="line">    <span class="keyword">for</span> i, v := <span class="keyword">range</span> c.params &#123;</span><br><span class="line">        format[i] = strconv.Itoa(<span class="keyword">int</span>(v))</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> strings.Join(format, <span class="string">";"</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">format</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"%s[%sm"</span>, escape, c.sequence())</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">unformat</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"%s[%dm"</span>, escape, Reset)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">wrap</span><span class="params">(s <span class="keyword">string</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> c.format() + s + c.unformat() </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面我们对常见的几个函数作一层封装。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">Sprint</span><span class="params">(a ...<span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> c.wrap(fmt.Sprint(a...))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">Sprintln</span><span class="params">(a ...<span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> c.wrap(fmt.Sprintln(a...))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Color)</span> <span class="title">Sprintf</span><span class="params">(format <span class="keyword">string</span>, a ...<span class="keyword">interface</span>&#123;&#125;)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> c.wrap(fmt.Sprintf(format, a...))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>理清了基本思路，使用它就变的非常简单了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    c := New(Bold, FgGreen)</span><br><span class="line">    fmt.Println(c.Sprintln(<span class="string">"hello world"</span>))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/08/SmoothWeightedRoundRobin/index.html b/2018/05/08/SmoothWeightedRoundRobin/index.html
deleted file mode 100644
index 512917f..0000000
--- a/2018/05/08/SmoothWeightedRoundRobin/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Weighted Round Robin | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="我们在之前的文章中就讲过负载均衡，但是那篇文章中的例子比较简单，仅仅是利用随机算法来进行负载均衡，并没有考虑服务器的实际情况，在很多情况下，服务器的性能可能存在显著差异，这时候如果采用随机算法，那么性能较差的服务器会承受过多的压力，而性能较好的服务器则大部分时间处于空闲状态，系统整体的吞吐量就无法上来。 例如服务器的性能比例如下：{a:3, b: 2, c:1} ，一般来说可以使用加权的轮询算法（">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Weighted Round Robin">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/08/SmoothWeightedRoundRobin/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="我们在之前的文章中就讲过负载均衡，但是那篇文章中的例子比较简单，仅仅是利用随机算法来进行负载均衡，并没有考虑服务器的实际情况，在很多情况下，服务器的性能可能存在显著差异，这时候如果采用随机算法，那么性能较差的服务器会承受过多的压力，而性能较好的服务器则大部分时间处于空闲状态，系统整体的吞吐量就无法上来。 例如服务器的性能比例如下：{a:3, b: 2, c:1} ，一般来说可以使用加权的轮询算法（">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:51.690Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Weighted Round Robin">
-<meta name="twitter:description" content="我们在之前的文章中就讲过负载均衡，但是那篇文章中的例子比较简单，仅仅是利用随机算法来进行负载均衡，并没有考虑服务器的实际情况，在很多情况下，服务器的性能可能存在显著差异，这时候如果采用随机算法，那么性能较差的服务器会承受过多的压力，而性能较好的服务器则大部分时间处于空闲状态，系统整体的吞吐量就无法上来。 例如服务器的性能比例如下：{a:3, b: 2, c:1} ，一般来说可以使用加权的轮询算法（">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-SmoothWeightedRoundRobin"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Weighted Round Robin
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-08T02:29:04.000Z" itemprop="datePublished">
-        May 8, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>我们在之前的文章中就讲过负载均衡，但是那篇文章中的例子比较简单，仅仅是利用随机算法来进行负载均衡，并没有考虑服务器的实际情况，在很多情况下，服务器的性能可能存在显著差异，这时候如果采用随机算法，那么性能较差的服务器会承受过多的压力，而性能较好的服务器则大部分时间处于空闲状态，系统整体的吞吐量就无法上来。</p>
-<p>例如服务器的性能比例如下：<code>{a:3, b: 2, c:1}</code> ，一般来说可以使用加权的轮询算法（ <code>Weighted Round Robin</code> ）进行负载均衡，但是普通的加权轮询会得出类似这样的序列， <code>a a a b b c</code> ，这样的序列有一个问题，就是它并不够平滑，我们更希望得到像这样的序列 <code>a b a c b a</code> 。也就是说一般的轮询调度在调度的过程中并没有考虑瞬时的情况，所以会导致对某一台服务器的瞬时访问。</p>
-<p>下面我们就来介绍一下平滑版本的加权轮询算法，来解决上述瞬时访问可能出现的问题。我们对每个节点赋予两个权重， <code>Weight</code> ，这是一个较为固定的值，就是前面给出的 <code>{a:3, b: 2, c:1}</code> ，还需要一个 <code>CurrentWeight</code> 来记录当前的权重，初始时均为0，这个权重是在每次选择节点时动态变化的。</p>
-<p>例如现在有三台服务器，其权重比值为 <code>{a:3, b: 2, c:1}</code> ，刚开始时它们的 <code>CurrentWeight</code> 均为0，按照下面的算法，每一回合中各个节点的 <code>CurrentWeight</code> 都会加上它相应的的 <code>Weight</code> ，<code>total</code> 变量则用于记录每一个节点增加的 <code>Weight</code> 的总和，并记录当前权重最高的那一个节点，也就是我们的 <code>best</code> ，在一轮计算之后，再让 <code>best</code> 节点的 <code>CurrentWeight</code> 减去 <code>total</code> 值。</p>
-<p>也就是说开始时每台服务器的 <code>CurrentWeight</code> 为 <code>{a:0, b: 0, c:0}</code> ，在选择节点的过程中，每个节点均会加上自己对应的 <code>Weight</code> ，这样就变成 <code>{a:3, b: 2, c:1}</code> ， 此时 <code>best=a</code> ， 最后 a 对应的 <code>CurrentWeight</code> 要减去 <code>total</code> ，也就是 <code>{a:-3, b: 2, c:1}</code>  。</p>
-<p>然后 <code>{a:-3, b: 2, c:1}</code> 作为下一轮挑选节点时的初始状态，以此类推，最后可以得到下面这样的序列  <code>a b a c b a</code> ，这样就不会导致对服务器 <code>a</code> 集中访问的情况，也就是说访问序列更加平滑了。</p>
-<p>整个周期计算的流程如下所示。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">a   b   c</span><br><span class="line">0   0   0</span><br><span class="line"></span><br><span class="line">3   2   1   Next() : a</span><br><span class="line">-3  2   1</span><br><span class="line"></span><br><span class="line">0   4   2   Next() : b</span><br><span class="line">0  -2   2</span><br><span class="line"></span><br><span class="line">3   0   3   Next() : a</span><br><span class="line">-3  0   3</span><br><span class="line"></span><br><span class="line">0   2   4   Next() : c</span><br><span class="line">0   2   -2 </span><br><span class="line"></span><br><span class="line">3   4   -1  Next() : b</span><br><span class="line">3  -2   -1</span><br><span class="line"></span><br><span class="line">6   0   0   Next() : a</span><br><span class="line">0   0   0</span><br></pre></td></tr></table></figure>
-<h2 id="普通版本平滑轮询调度算法"><a href="#普通版本平滑轮询调度算法" class="headerlink" title="普通版本平滑轮询调度算法"></a>普通版本平滑轮询调度算法</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Weighted <span class="keyword">struct</span> &#123;</span><br><span class="line">    Server <span class="keyword">string</span></span><br><span class="line">    Weight <span class="keyword">int</span></span><br><span class="line">    CurrentWeight <span class="keyword">int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>普通版本的算法，每次选择结点的时候，我们为每个候选结点的 <code>CurrentWeight</code> 增加 <code>Weight</code> ，选取 <code>CurrentWeight</code> 最大的节点作为我们最后返回的结果，然后将该节点减去所有节点增加的 <code>Weight</code> 之和。 </p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Next</span><span class="params">(servers []*Weighted)</span> <span class="params">(best *Weight)</span></span> &#123;</span><br><span class="line">    total := <span class="number">0</span> </span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(servers); i++ &#123;</span><br><span class="line">        w := servers[i]</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span> w == <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        w.CurrentWeight += w.Weight</span><br><span class="line">        total += w.CurrentWeight </span><br><span class="line">        <span class="keyword">if</span> best == <span class="literal">nil</span> || w.CurrentWeight &gt; best.CurrentWeight &#123;</span><br><span class="line">            best = w</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> best == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    best.CurrentWeight -= total</span><br><span class="line">    <span class="keyword">return</span> best</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="考虑节点失效情况时的算法"><a href="#考虑节点失效情况时的算法" class="headerlink" title="考虑节点失效情况时的算法"></a>考虑节点失效情况时的算法</h2><p>上面那种算法不能很好的应对节点失效的情况，为了解决节点失效时的这种突发情况，我们多引入一个权重也就是 <code>EffectiveWeight</code> ，该权重初始时与 <code>Weight</code> 的值相同，例如上述的例子中都是  <code>{a:3, b: 2, c:1}</code> ，但是 <code>EffectiveWeight</code> 会在节点失败的时候清0，当节点恢复正常时再慢慢递增直到达到原本的 <code>Weight</code> ，这样就能很好地考虑了节点失效再重启时的真实情况。因为引入了 <code>EffectiveWeight</code> ， 我们在相应计算的时候就不直接采用 <code>Weight</code> 而是直接使用<code>EffectiveWeight</code> 来代替计算。 </p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Weighted <span class="keyword">struct</span> &#123;</span><br><span class="line">    Server <span class="keyword">string</span></span><br><span class="line">    Weight <span class="keyword">int</span></span><br><span class="line">    CurrentWeight <span class="keyword">int</span></span><br><span class="line">    EffectiveWeight <span class="keyword">int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *Weighted)</span> <span class="title">fail</span><span class="params">()</span></span> &#123;</span><br><span class="line">    w.EffetiveWeight -= w.Weight</span><br><span class="line">    <span class="keyword">if</span> w.EffectiveWeight &lt; <span class="number">0</span> &#123;</span><br><span class="line">        w.EffectiveWeight = <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Next</span><span class="params">(servers []*Weighted)</span> <span class="params">(best *Weight)</span></span> &#123;</span><br><span class="line">    total := <span class="number">0</span></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(servers); i++ &#123;</span><br><span class="line">        w := servers[i]</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> w == <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        w.CurrentWeight += w.EffectiveWeight</span><br><span class="line">        total += w.EffectiveWeight</span><br><span class="line">        <span class="keyword">if</span> w.EffectiveWeight &lt; w.Weight &#123;</span><br><span class="line">            w.EffectiveWeight++</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> best == <span class="literal">nil</span> || w.CurrentWeight &gt; best.CurrentWeight &#123;</span><br><span class="line">            best = w</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> best == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    best.CurrentWeight -= total</span><br><span class="line">    <span class="keyword">return</span> best</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/09/CircuitBreaker/index.html b/2018/05/09/CircuitBreaker/index.html
deleted file mode 100644
index af7dd7c..0000000
--- a/2018/05/09/CircuitBreaker/index.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Circuit Breaker | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="我们都知道，如果家中因为启动过多大功率电器而导致电流过大，断路开关就会断开以保护这些电路和电器。在分布式系统中，集群中的某些服务器出现异常还是一件非常正常的事情，如果客户端向这些异常的服务器进行 RPC 请求的话，这些服务器会因为异常而无法向客户端返回远程方法调用的结果，因为一般来说 RPC 是阻塞的，客户端会像执行本地方法一样调用 RPC ，也就是说客户端会阻塞在这里无法执行 直到该方法本地超时">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Circuit Breaker">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/09/CircuitBreaker/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="我们都知道，如果家中因为启动过多大功率电器而导致电流过大，断路开关就会断开以保护这些电路和电器。在分布式系统中，集群中的某些服务器出现异常还是一件非常正常的事情，如果客户端向这些异常的服务器进行 RPC 请求的话，这些服务器会因为异常而无法向客户端返回远程方法调用的结果，因为一般来说 RPC 是阻塞的，客户端会像执行本地方法一样调用 RPC ，也就是说客户端会阻塞在这里无法执行 直到该方法本地超时">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://martinfowler.com/bliki/images/circuitBreaker/sketch.png">
-<meta property="og:updated_time" content="2018-06-26T08:44:11.025Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Circuit Breaker">
-<meta name="twitter:description" content="我们都知道，如果家中因为启动过多大功率电器而导致电流过大，断路开关就会断开以保护这些电路和电器。在分布式系统中，集群中的某些服务器出现异常还是一件非常正常的事情，如果客户端向这些异常的服务器进行 RPC 请求的话，这些服务器会因为异常而无法向客户端返回远程方法调用的结果，因为一般来说 RPC 是阻塞的，客户端会像执行本地方法一样调用 RPC ，也就是说客户端会阻塞在这里无法执行 直到该方法本地超时">
-<meta name="twitter:image" content="https://martinfowler.com/bliki/images/circuitBreaker/sketch.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-CircuitBreaker"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Circuit Breaker
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-09T01:17:24.000Z" itemprop="datePublished">
-        May 9, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>我们都知道，如果家中因为启动过多大功率电器而导致电流过大，断路开关就会断开以保护这些电路和电器。在分布式系统中，集群中的某些服务器出现异常还是一件非常正常的事情，如果客户端向这些异常的服务器进行 <code>RPC</code> 请求的话，这些服务器会因为异常而无法向客户端返回远程方法调用的结果，因为一般来说 <code>RPC</code> 是阻塞的，客户端会像执行本地方法一样调用 <code>RPC</code> ，也就是说客户端会阻塞在这里无法执行 直到该方法本地超时，但由于为了得到正确的结果，客户端可能会反复多次调用该 <code>RPC</code> ，由于在这段时间内远程服务器都可能无法恢复正常，所以就会导致客户端一直调用该方法，但却无法得到结果，这样就会导致资源的浪费。</p>
-<p>为了避免上述情况的发生，我们可以在程序设计中借鉴断路开关的模式，也就是允许被保护的函数在规定上限内执行，如果一旦出现错误的次数超过上限，则下次函数再次调用时则直接不让其执行（也就是断路开关直接断开），从而避免系统资源的浪费。但是上述方法存在一个问题，就是一旦总的错误次数超过上限，是不是就说明即使现在远程服务器恢复正常，客户端也无法调用了呢。</p>
-<p>解决上述问题也很简单，通过模仿网络中很常见的 <code>Sliding Window</code> ，也就是移动窗口，允许在一定时间窗口内出现特定上限个错误，如果在该时间窗口内出现错误的次数超过上限，则不再允许该函数执行，直到下一个时间窗口的到来才允许它重新执行。</p>
-<p>下面来设计一个滑动窗口版本的断路开关，我们通过判断一个时间窗口 <code>window</code> 内出现的错误次数 <code>failures</code> 是否超过<code>failureThreshold</code> 来决定断路开关是否应该断开（也就是不让函数继续执行）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> CircuitBreaker <span class="keyword">struct</span> &#123;</span><br><span class="line">    lastFailureTime  time.Time</span><br><span class="line">    failures         <span class="keyword">uint64</span></span><br><span class="line">    failureThreshold <span class="keyword">uint64</span></span><br><span class="line">    window           time.Duration</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewCircuitBreaker</span><span class="params">(failureThreshold <span class="keyword">uint64</span>, window time.Duration)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;CircuitBreaker&#123;</span><br><span class="line">        failureThreshold: failureThreshold,</span><br><span class="line">        window:           window,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>由于是滑动窗口，我们需要观察在现在的窗口出现错误的次数是否超过我们规定的次数，如果超过，则表示该函数还没有 <code>ready</code> ，也就是还不能执行，如果该窗口已经过去，那么我们重置（ <code>reset</code> ）断路开关中记录的出错次数，以让函数可以重新执行。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cb *CircuitBreaker)</span> <span class="title">ready</span><span class="params">()</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> time.Since(cb.lastFailureTIme) &gt; cb.window &#123;</span><br><span class="line">        cb.reset()</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    failures := atomic.LoadUint64(&amp;cb.failures)</span><br><span class="line">    <span class="keyword">return</span> failures &lt; cb.failureThreshold</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cb *CircuitBreaker)</span> <span class="title">success</span><span class="params">()</span></span> &#123;</span><br><span class="line">    cb.reset()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cb *CircuitBreaker)</span> <span class="title">fail</span><span class="params">()</span></span> &#123;</span><br><span class="line">    atomic.AddUint64(&amp;cb.failures, <span class="number">1</span>)</span><br><span class="line">    cb.lastFailureTime = time.Now()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cb *CircuitBreaker)</span> <span class="title">reset</span><span class="params">()</span></span> &#123;</span><br><span class="line">    atomic.StoreUint64(&amp;cb.failures, <span class="number">0</span>)</span><br><span class="line">    cb.lastFailureTime = time.Now()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>也就是说，在 <code>CircuitBreaker</code> 保护下，客户端准备调用函数时，会预先检察其是否具备资格，也就是说过去一个时间窗口没有出现超过上限个错误，如果不具备，就报 <code>ErrBreakerOpen</code> 错误，也就是对应下图中的  <code>circuit open</code> ，因为断路开关断开了，自然没有办法继续执行。</p>
-<p>如果具备，则可以让受保护的函数继续执行，但是钥匙它在规定的时间内还没有返回结果，说明出现超时情况，则报<code>ErrBreakerTimeout</code> 错误，并增加错误次数直到其达到上限为止。</p>
-<p><img src="https://martinfowler.com/bliki/images/circuitBreaker/sketch.png" alt="Circuit Breaker"></p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    ErrBreakerOpen = errors.New(<span class="string">"breaker open"</span>)</span><br><span class="line">    ErrBreakerTimeout = errors.New(<span class="string">"breaker time out"</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cb *CircuitBreaker)</span> <span class="title">Call</span><span class="params">(fn <span class="keyword">func</span>()</span> <span class="title">error</span>, <span class="title">d</span> <span class="title">time</span>.<span class="title">Duration</span>) <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> err error</span><br><span class="line">    <span class="keyword">if</span> !cb.ready() &#123;</span><br><span class="line">        <span class="keyword">return</span> </span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> d == <span class="number">0</span> &#123;</span><br><span class="line">        err = fn()</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        c := <span class="built_in">make</span>(<span class="keyword">chan</span> error, <span class="number">1</span>)</span><br><span class="line">        <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">            c &lt;- fn()</span><br><span class="line">            <span class="built_in">close</span>(c)</span><br><span class="line">        &#125;()</span><br><span class="line"></span><br><span class="line">        t := time.NewTicker(d)</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> e := &lt;-c:</span><br><span class="line">            err = e</span><br><span class="line">        <span class="keyword">case</span> &lt;-t.C:</span><br><span class="line">            err = ErrBreakerTimeout</span><br><span class="line">        &#125;</span><br><span class="line">        t.Stop()</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> err == <span class="literal">nil</span> &#123;</span><br><span class="line">        cb.success()</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        cb.fail()</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/09/MorseCode/index.html b/2018/05/09/MorseCode/index.html
deleted file mode 100644
index 15340d4..0000000
--- a/2018/05/09/MorseCode/index.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Morse Code | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="电影无间道中，陈永仁用摩斯密码向自己老大发送消息那一段真的是精彩，印象非常深刻。其实摩斯密码的本质上就是一种消息编码格式，也就是通信双方用规定好的格式进行交流，由于该编码方式二义性小，所以接受方基本可以准确无误的解析出发送方经过编码的信息。 摩斯密码摩斯密码主要编码英文字母，数字和标点符号，摩斯密码与常用的二进制编码不同，它包含了五个元素， 点、划、点和划之间的停顿、每个词之间中等的停顿以及句子之">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Morse Code">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/09/MorseCode/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="电影无间道中，陈永仁用摩斯密码向自己老大发送消息那一段真的是精彩，印象非常深刻。其实摩斯密码的本质上就是一种消息编码格式，也就是通信双方用规定好的格式进行交流，由于该编码方式二义性小，所以接受方基本可以准确无误的解析出发送方经过编码的信息。 摩斯密码摩斯密码主要编码英文字母，数字和标点符号，摩斯密码与常用的二进制编码不同，它包含了五个元素， 点、划、点和划之间的停顿、每个词之间中等的停顿以及句子之">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://cdn-images-1.medium.com/max/443/1*2WrXJ9lDlC8Q0HCO7H3DBQ.png">
-<meta property="og:updated_time" content="2018-06-26T08:47:03.295Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Morse Code">
-<meta name="twitter:description" content="电影无间道中，陈永仁用摩斯密码向自己老大发送消息那一段真的是精彩，印象非常深刻。其实摩斯密码的本质上就是一种消息编码格式，也就是通信双方用规定好的格式进行交流，由于该编码方式二义性小，所以接受方基本可以准确无误的解析出发送方经过编码的信息。 摩斯密码摩斯密码主要编码英文字母，数字和标点符号，摩斯密码与常用的二进制编码不同，它包含了五个元素， 点、划、点和划之间的停顿、每个词之间中等的停顿以及句子之">
-<meta name="twitter:image" content="https://cdn-images-1.medium.com/max/443/1*2WrXJ9lDlC8Q0HCO7H3DBQ.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-MorseCode"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Morse Code
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-09T09:07:24.000Z" itemprop="datePublished">
-        May 9, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>电影无间道中，陈永仁用摩斯密码向自己老大发送消息那一段真的是精彩，印象非常深刻。其实摩斯密码的本质上就是一种消息编码格式，也就是通信双方用规定好的格式进行交流，由于该编码方式二义性小，所以接受方基本可以准确无误的解析出发送方经过编码的信息。</p>
-<h2 id="摩斯密码"><a href="#摩斯密码" class="headerlink" title="摩斯密码"></a>摩斯密码</h2><p>摩斯密码主要编码英文字母，数字和标点符号，摩斯密码与常用的二进制编码不同，它包含了五个元素， 点、划、点和划之间的停顿、每个词之间中等的停顿以及句子之间长的停顿。</p>
-<p><img src="https://cdn-images-1.medium.com/max/443/1*2WrXJ9lDlC8Q0HCO7H3DBQ.png" alt="Morse Code"></p>
-<p>因为摩斯密码的编码方法不止一种，但其基本原理都是相通的，所以这里我们使用国际电信联盟（International Telecommunication Union）制定的编码标准来书写代码。</p>
-<p>下面使用一个 <code>map</code> 作为字典使用，用于记录英文字母、数字和标点符号到摩斯密码的映射关系，因为文章篇幅原因，这里选择省略对应关系。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    morseITU = <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>&#123;</span><br><span class="line">        <span class="string">"a"</span>: <span class="string">".-"</span>,</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// ...    </span></span><br><span class="line"></span><br><span class="line">        <span class="string">"0"</span>:  <span class="string">"-----"</span>,   </span><br><span class="line"></span><br><span class="line">        <span class="string">"="</span>:  <span class="string">"-...-"</span>,</span><br><span class="line">    &#125;</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
-<h2 id="编码"><a href="#编码" class="headerlink" title="编码"></a>编码</h2><p>编码的过程就是利用字典将我们要映射的字符转为摩斯密码，并且注意每次转换都要附加一个 <code>letterSep</code> ，也就是字符间的分隔符，当遇到原本需要编码的字符串中的空格，则加上 <code>wordSep</code> ，即字分隔符。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">EncodeITU</span><span class="params">(s <span class="keyword">string</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> Encode(s, morseITU, <span class="string">" "</span>, <span class="string">"/"</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Encode</span><span class="params">(s <span class="keyword">string</span>, alphabet <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>, letterSep <span class="keyword">string</span>, wordSep <span class="keyword">string</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    res := <span class="string">""</span></span><br><span class="line">    <span class="keyword">for</span> _, part := <span class="keyword">range</span> s &#123;</span><br><span class="line">        p := <span class="keyword">string</span>(part)</span><br><span class="line">        <span class="keyword">if</span> p == <span class="string">" "</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> wordSep != <span class="string">""</span> &#123;</span><br><span class="line">                res += wordSep + letterSep</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> morseITU[p] != <span class="string">""</span> &#123;</span><br><span class="line">            res += morseITU[p] + letterSep</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> strings.TrimSpace(res)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="解码"><a href="#解码" class="headerlink" title="解码"></a>解码</h2><p>解码是编码的逆过程，因为有字符分隔符（letterSep）的存在，所以我们先用 <code>strings.Split(s, letterSep)</code> 得到一组经过摩斯密码编码的字符数组，然后对于每个经过编码的摩斯密码，我们查询字典中是否有该编码存在，如果存在则与返回结果拼接，如果不存在则检查该元素是否为字分隔符，如果还不是的话则返回错误，最后全部成功返回解码后的结果。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">DecodeITU</span><span class="params">(s <span class="keyword">string</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> Decode(s, morseITU, <span class="string">" "</span>, <span class="string">"/"</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Decode</span><span class="params">(s <span class="keyword">string</span>, alphabet <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>, letterSep <span class="keyword">string</span>, wordSep <span class="keyword">string</span>)</span> <span class="params">(<span class="keyword">string</span>, error)</span></span> &#123;</span><br><span class="line">    res := <span class="string">""</span></span><br><span class="line">    <span class="keyword">for</span> _, part := <span class="keyword">range</span> strings.Split(s, letterSep) &#123;</span><br><span class="line">        found := <span class="literal">false</span></span><br><span class="line">        <span class="keyword">for</span> key, val := <span class="keyword">range</span> alphabet &#123;</span><br><span class="line">            <span class="keyword">if</span> val == part &#123;</span><br><span class="line">                res += key</span><br><span class="line">                found = <span class="literal">true</span></span><br><span class="line">                <span class="keyword">break</span>    </span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> part == wordSep &#123;</span><br><span class="line">            res += <span class="string">" "</span></span><br><span class="line">            found = <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> found == <span class="literal">false</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> res, fmt.Errorf(<span class="string">"unknown character "</span> + part)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/10/ConnectionPool/index.html b/2018/05/10/ConnectionPool/index.html
deleted file mode 100644
index 3a45696..0000000
--- a/2018/05/10/ConnectionPool/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Connection Pool | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="因为 TCP 连接都是客户端主动发起的，也就是说需要经过三次握手才能够进行读写操作，如果客户端需要建立连接的次数较少，那么握手需要的开销倒可以忽略不计，但是如果客户端需要建立成千上万个 TCP 连接，那么就需要成千上万次握手了。如果真是这样，势必会导致系统性能低下，我们引入连接池来解决多次握手的问题。 连接池（ Connection Pool ）在广义上来说算是资源池，我们之前讲过的  Leaky">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Connection Pool">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/10/ConnectionPool/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="因为 TCP 连接都是客户端主动发起的，也就是说需要经过三次握手才能够进行读写操作，如果客户端需要建立连接的次数较少，那么握手需要的开销倒可以忽略不计，但是如果客户端需要建立成千上万个 TCP 连接，那么就需要成千上万次握手了。如果真是这样，势必会导致系统性能低下，我们引入连接池来解决多次握手的问题。 连接池（ Connection Pool ）在广义上来说算是资源池，我们之前讲过的  Leaky">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png">
-<meta property="og:updated_time" content="2018-06-26T08:44:22.657Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Connection Pool">
-<meta name="twitter:description" content="因为 TCP 连接都是客户端主动发起的，也就是说需要经过三次握手才能够进行读写操作，如果客户端需要建立连接的次数较少，那么握手需要的开销倒可以忽略不计，但是如果客户端需要建立成千上万个 TCP 连接，那么就需要成千上万次握手了。如果真是这样，势必会导致系统性能低下，我们引入连接池来解决多次握手的问题。 连接池（ Connection Pool ）在广义上来说算是资源池，我们之前讲过的  Leaky">
-<meta name="twitter:image" content="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ConnectionPool"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Connection Pool
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-10T03:40:24.000Z" itemprop="datePublished">
-        May 10, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>因为 <code>TCP</code> 连接都是客户端主动发起的，也就是说需要经过三次握手才能够进行读写操作，如果客户端需要建立连接的次数较少，那么握手需要的开销倒可以忽略不计，但是如果客户端需要建立成千上万个 <code>TCP</code> 连接，那么就需要成千上万次握手了。如果真是这样，势必会导致系统性能低下，我们引入连接池来解决多次握手的问题。</p>
-<p>连接池（ <code>Connection Pool</code> ）在广义上来说算是资源池，我们之前讲过的  <a href="LeakyBuffer.md">LeakyBuffer</a> 也算是资源池的一种，不过 <code>LeakyBuffer</code> 的目的是反复利用内存资源，减少内存分配的次数。而连接池则是为了减少建立连接的次数，重复利用已有的 <code>TCP</code> 连接。</p>
-<p><img src="https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png" alt="ConnPool"></p>
-<p>例如在上图中，<code>Consumer Agent</code> 不断收到来自 <code>Consumer</code> 的 <code>HTTP</code> 请求，它解析请求的内容后，<code>Consumer Agent</code> 就要利用 <code>TCP</code> 连接给 <code>Provider Agent</code> 发送消息，那么如果按照传统的方法我们就需要每一个 <code>HTTP</code> 请求都要对应一个新的 <code>TCP</code> 连接，也就对应新的三次握手，这样的话系统开销会非常大。你可能会问为什么不直接用一个 <code>TCP</code> 连接来解决传输数据的问题，这样的话甚至不用这么多握手操作了，这问题不错，但是考虑到由于 <code>TCP</code> 传输的是应用层的数据，它并不了解应用层传输的信息究竟是什么意思，如果多个客户端发起的连接共用一个 <code>TCP</code> 连接，那么我们还需要写逻辑去区分收到的消息究竟需要属于哪个 <code>HTTP</code> 请求，另外还需要考虑<code>TCP</code> 发送和接受时读写竞争的问题，操作起来比较混乱，还不如重复利用多个 <code>TCP</code> 连接来发送和接受数据来的干净利落。</p>
-<p>总的来说，连接池是一种利用空间换时间的技术。下面我们来看一下如何设计一个连接池。连接池中最核心的操作就是获取一个空闲的 <code>TCP</code> 连接，另外还要考虑连接池资源释放的问题，否则可能会导致内存泄漏。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> ErrClosed = errors.New(<span class="string">"pool is closed"</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Pool <span class="keyword">interface</span> &#123;</span><br><span class="line">    Get() (net.Conn, error)</span><br><span class="line">    Close()</span><br><span class="line">    Len() <span class="keyword">int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在正常的 <code>TCP</code> 流程中，<code>Close</code> 会关闭本次连接，底层会进行四个挥手操作，但是我们不希望我们调用 <code>Close</code> 时直接关闭这个连接，而是希望能回收这个连接，所以我们对普通的 <code>net.Conn</code> 做了一层封装，来该改变其 <code>Close</code> 行为（其实这就是装饰器模式的应用），我们想要客户端调用 <code>Close</code> 的时候被我们的连接池所回收而非直接关闭，除非该连接被标记为不可用时 <code>unusable</code> （通过 <code>MarkUnusable</code> ）， 我们才决定关闭本次连接。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> PooledConn <span class="keyword">struct</span> &#123;</span><br><span class="line">    net.Conn</span><br><span class="line">    mu  sync.RWMutex</span><br><span class="line">    c   *ConnPool</span><br><span class="line">    unusable <span class="keyword">bool</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *PooledConn)</span> <span class="title">Close</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    p.mu.RLock()</span><br><span class="line">    <span class="keyword">defer</span> p.mu.Runlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> p.unusable &#123;</span><br><span class="line">        <span class="keyword">if</span> p.Conn != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> p.Conn.Close()      </span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> p.c.put(p.Conn)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *PooledConn)</span> <span class="title">MarkUnusable</span><span class="params">()</span></span> &#123;</span><br><span class="line">    p.mu.Lock()</span><br><span class="line">    <span class="keyword">defer</span> p.mu.Unlock()</span><br><span class="line">    p.unusable = <span class="literal">true</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *ConnPool)</span> <span class="title">wrapConn</span><span class="params">(conn net.Conn)</span> <span class="title">net</span>.<span class="title">Conn</span></span> &#123;</span><br><span class="line">    p := &amp;PooledConn&#123;c: c&#125;</span><br><span class="line">    p.Conn = conn</span><br><span class="line">    <span class="keyword">return</span> p</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>连接池的构建需要考虑两个问题，一个就是连接创建问题，第二就是回收连接问题，创建我们用一个 <code>Factory</code> 工厂方法来表示，而回收连接可以利用 <code>golang</code> 中的通道机制（ <code>chan</code> ）来进行储存。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Factory <span class="function"><span class="keyword">func</span><span class="params">()</span> <span class="params">(net.Conn, error)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">type</span> <span class="title">ConnPool</span> <span class="title">struct</span></span> &#123;</span><br><span class="line">    mu sync.RWMutex</span><br><span class="line">    conns <span class="keyword">chan</span> net.Conn</span><br><span class="line">    factroy Factory</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在初始化连接池时，我们先建立 <code>initialCap</code> 个连接用于刚开始时使用，具体创建可以使用 <code>factory</code> 产生 <code>TCP</code> 连接。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewConnPool</span><span class="params">(initialCap, maxCap <span class="keyword">int</span>, factory Factory)</span> <span class="params">(Pool, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> initialCap &lt; <span class="number">0</span> || maxCap &lt;= <span class="number">0</span> || initialCap &gt; maxCap &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span> , errors.New(<span class="string">"invalid capacity settings"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    c := &amp;ConnPool&#123;</span><br><span class="line">        conns: <span class="built_in">make</span>(<span class="keyword">chan</span> net.Conn, maxCap),</span><br><span class="line">        factory: factory,</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; initialCap; i++ &#123;</span><br><span class="line">        conn, err := factory()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            c.Close()</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, fmt.Errorf(<span class="string">"factory is not able to fill the pool: %s"</span>, err)</span><br><span class="line">        &#125;</span><br><span class="line">        c.conns &lt;- conn</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> c, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *ConnPool)</span> <span class="title">getConnsAndFactory</span><span class="params">()</span> <span class="params">(<span class="keyword">chan</span> net.Conn, Factory)</span></span>&#123;</span><br><span class="line">    c.mu.RLock()</span><br><span class="line">    <span class="keyword">defer</span> c.mu.RUnlock()</span><br><span class="line">    conns := c.conns</span><br><span class="line">    factory := c.factory</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当客户端使用完一次 <code>TCP</code> 连接后，会主动调用 <code>Close</code> 来关闭此次连接，由于我们重新定义了 <code>Close</code> 函数，当调用 <code>Close</code> 时，连接不会直接关闭而是会重新放回连接池中供其他部分代码使用，从而达到重复使用的目的，如果此时连接池已满，则直接释放该连接。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *ConnPool)</span> <span class="title">put</span><span class="params">(conn net.Conn)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> conn == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> errors.New(<span class="string">"connection is nil, rejecting"</span>)</span><br><span class="line">    &#125; </span><br><span class="line">    c.mu.Lock()</span><br><span class="line">    <span class="keyword">defer</span> c.mu.RUnlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> c.conns == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> conn.Close()</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> c.conns &lt;- conn:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        <span class="keyword">return</span> conn.Close()</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面的结构体 <code>ConnPool</code> 实现了 <code>Pool</code> 接口。在 <code>Get</code> 方法中我们先得到具体用于存储连接的通道 <code>conns</code> 和用于制造连接的工厂方法 <code>factory</code>，然后试着去通道中拿，和 <code>put</code> 方法类似，如果该通道中还有空闲的 <code>TCP</code> 连接，则直接拿出并经过封装后（ <code>wrapConn</code> ）使用，如果没有则使用工厂方法新建一个 <code>TCP</code> 连接再经过封装后使用。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *ConnPool)</span> <span class="title">Get</span><span class="params">()</span> <span class="params">(net.Conn, error)</span></span> &#123;</span><br><span class="line">    conns, factory := c.getConnsAndFactory()</span><br><span class="line">    <span class="keyword">if</span> conns == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, ErrClosed</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> conn := &lt;- conns:</span><br><span class="line">        <span class="keyword">if</span> conn == <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, ErrClosed</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> c.wrapConn(conn), <span class="literal">nil</span></span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        conn, err := factory()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> c.wrapConn(conn), <span class="literal">nil</span></span><br><span class="line">    &#125;    </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *ConnPool)</span> <span class="title">Close</span><span class="params">()</span></span> &#123;</span><br><span class="line">    c.mu.Lock()</span><br><span class="line">    conns := c.conns</span><br><span class="line">    c.conns. = <span class="literal">nil</span></span><br><span class="line">    c.factory = <span class="literal">nil</span></span><br><span class="line">    c.mu.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> conns == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">close</span>(conns)</span><br><span class="line">    <span class="keyword">for</span> conn := <span class="keyword">range</span> conns &#123;</span><br><span class="line">        conn.Close()</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *ConnPool)</span> <span class="title">Len</span><span class="params">()</span> <span class="title">int</span></span> &#123;</span><br><span class="line">    conns, _ := c.getConnsAndFactory()</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">len</span>(conns)   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="连接池的使用"><a href="#连接池的使用" class="headerlink" title="连接池的使用"></a>连接池的使用</h2><p>由于具体的连接逻辑是由客户端决定的，所以 <code>factory</code> 应该由使用者定义。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">factory := <span class="function"><span class="keyword">func</span><span class="params">()</span> <span class="params">(net.Conn, error)</span></span> &#123;<span class="keyword">return</span> net.Dial(<span class="string">"tcp"</span>, <span class="string">"localhost:8080"</span>)&#125;</span><br></pre></td></tr></table></figure>
-<p>我们通过 <code>pool.NewConnPool</code> 来新建一个连接池，这里我们指定连接池中初始的连接个数为5，而最大的连接个数为30。通过 <code>p.Get</code> 来获得可用的连接，<code>Get</code> 方法会根据当前池中的情况返回连接，如果池中没有可用的连接则用 <code>factory</code> 方法新建一个，此时系统开销较大，但是这种情况并不常见，所以基本可以忽略不计。如果池中有可用连接，则直接返回，此时开销较小。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">p, err := pool.NewConnPool(<span class="number">5</span>, <span class="number">30</span>, factory)</span><br><span class="line"></span><br><span class="line">conn, err := p.Get()</span><br><span class="line"></span><br><span class="line"><span class="keyword">defer</span> conn.Close()</span><br></pre></td></tr></table></figure>
-<p>下面给出真正关闭该连接的方法，因为我们重载了 <code>Close</code> 方法，直接调用 <code>Close</code> 只会将此连接放回连接池中，所以需要在真正关闭前将此连接设为不可用（ <code>MarkUnusable</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> pc, ok := conn.(*pool.PooledConn); ok &#123;</span><br><span class="line">    pc.MarkUnusable()</span><br><span class="line">    pc.Close()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/11/StreamCipher/index.html b/2018/05/11/StreamCipher/index.html
deleted file mode 100644
index 97f6697..0000000
--- a/2018/05/11/StreamCipher/index.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Stream Cipher | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="假如我们有一份很重要的文件想要从本地传输到远程客户端，因为并不想让别人看见我们传输的信息，所以需要使用某种手段将传输的数据保护起来，我们可以选择先将文件加密后再进行传输，别人收到之后再进行相应的解密操作。这种方式对于小文件来说问题倒不是很大，但是如果文件体积非常大，本地对文件进行加密和远程对文件进行解密花费的时间就会很长，这样的话时间效率就非常低了，如果我们可以对该文件边加密边传输，远程客户端也可">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Stream Cipher">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/11/StreamCipher/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="假如我们有一份很重要的文件想要从本地传输到远程客户端，因为并不想让别人看见我们传输的信息，所以需要使用某种手段将传输的数据保护起来，我们可以选择先将文件加密后再进行传输，别人收到之后再进行相应的解密操作。这种方式对于小文件来说问题倒不是很大，但是如果文件体积非常大，本地对文件进行加密和远程对文件进行解密花费的时间就会很长，这样的话时间效率就非常低了，如果我们可以对该文件边加密边传输，远程客户端也可">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:47.387Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Stream Cipher">
-<meta name="twitter:description" content="假如我们有一份很重要的文件想要从本地传输到远程客户端，因为并不想让别人看见我们传输的信息，所以需要使用某种手段将传输的数据保护起来，我们可以选择先将文件加密后再进行传输，别人收到之后再进行相应的解密操作。这种方式对于小文件来说问题倒不是很大，但是如果文件体积非常大，本地对文件进行加密和远程对文件进行解密花费的时间就会很长，这样的话时间效率就非常低了，如果我们可以对该文件边加密边传输，远程客户端也可">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-StreamCipher"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Stream Cipher
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-11T05:10:04.000Z" itemprop="datePublished">
-        May 11, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>假如我们有一份很重要的文件想要从本地传输到远程客户端，因为并不想让别人看见我们传输的信息，所以需要使用某种手段将传输的数据保护起来，我们可以选择先将文件加密后再进行传输，别人收到之后再进行相应的解密操作。这种方式对于小文件来说问题倒不是很大，但是如果文件体积非常大，本地对文件进行加密和远程对文件进行解密花费的时间就会很长，这样的话时间效率就非常低了，如果我们可以对该文件边加密边传输，远程客户端也可以边接收边解密的话，时间效率就可以大幅度提升了。</p>
-<p>下面我们来引入流加密解决上述问题，流加密有很多模式，例如 <code>CFB</code>，<code>CTR</code> ，<code>OFB</code> 等。而流加密的核心就是异或操作，使用 <code>XORKeyStream</code> 就可以进行加解密了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cipher</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Stream <span class="keyword">interface</span> &#123;</span><br><span class="line">    XORKeyStream(dst, src []<span class="keyword">byte</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为加密解密肯定涉及到读写操作，所以我们用一个结构体 <code>writer</code> 实现 <code>io.Writer</code> 这个接口，里面封装了一个 <code>io.Writer</code> 和 <code>cipher.Stream</code> ，基本的思路就是将数据经过 <code>cipher.Stream</code> 的 <code>XORKeyStream</code> 方法写入 <code>io.Writer</code> 中。这里 <code>buf</code> 作为中间读操作和加密操作的缓存。</p>
-<p>考虑到通用性，这里和下面我们使用 <code>io.Writer</code> 和 <code>io.Writer</code> 这样的接口进行抽象操作，而非使用具体的 <code>Writer</code> 或者 <code>Reader</code> 来代替。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> bufSize = <span class="number">32</span> * <span class="number">1024</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> writer <span class="keyword">struct</span> &#123;</span><br><span class="line">    io.Writer</span><br><span class="line">    cipher.Stream</span><br><span class="line">    buf []<span class="keyword">byte</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewWriter</span><span class="params">(w io.Writer, s cipher.Stream)</span> <span class="title">io</span>.<span class="title">Writer</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;writer&#123;Writer: w, Stream: s, buf: <span class="built_in">make</span>([]<span class="keyword">byte</span>, bufSize)&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *writer)</span> <span class="title">Write</span><span class="params">(b []<span class="keyword">byte</span>)</span> <span class="params">(<span class="keyword">int</span>, error)</span></span> &#123;</span><br><span class="line">    n, err := w.ReadFrom(bytes.NewBuffer(b))</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">int</span>(n), err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>ReadFrom</code> 方法使我们的 <code>writer</code> 不断从未加密的 <code>io.Reader</code> 中读取数据到 <code>buf</code> 中，再利用 <code>XORKeyStream</code> 将数据加密后写入自己的 <code>io.Writer</code> 中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *writer)</span> <span class="title">ReadFrom</span><span class="params">(r io.Reader)</span> <span class="params">(n <span class="keyword">int64</span>, err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        buf := w.buf</span><br><span class="line">        nr, er := r.Read(buf)</span><br><span class="line">        <span class="keyword">if</span> nr &gt; <span class="number">0</span> &#123;</span><br><span class="line">            n += <span class="keyword">int64</span>(nr)</span><br><span class="line">            buf = buf[:nr]</span><br><span class="line">            w.XORKeyStream(buf, buf)</span><br><span class="line">            _, ew := w.Writer.Write(buf)</span><br><span class="line">            <span class="keyword">if</span> ew != <span class="literal">nil</span> &#123;</span><br><span class="line">                err = ew</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span> er != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> er != io.EOF &#123;</span><br><span class="line">                err = err</span><br><span class="line">            &#125;  </span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在读方面，和写的时候类似，我们也在自己定义的结构体 <code>reader</code> 中包含一个 <code>io.Reader</code> 和 <code>cipher.Stream</code> ，基本思路也是从 <code>io.Reader</code> 中读取经过加密的数据，然后再用 <code>cipher.Stream</code> 的 <code>XORKeyStream</code> 方法解密。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> reader <span class="keyword">struct</span> &#123;</span><br><span class="line">    io.Reader</span><br><span class="line">    cipher.Stream</span><br><span class="line">    buf []<span class="keyword">byte</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewReader</span><span class="params">(r io.Reader, s cipher.Stream)</span> <span class="title">io</span>.<span class="title">Reader</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;reader&#123;Reader: r, Stream: s, buf: <span class="built_in">make</span>([]<span class="keyword">byte</span>, bufSize)&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面实现的 <code>Read</code> 方法利用 <code>io.Reader</code> 读取经过加密后的数据，再利用<code>XORKeyStream</code> 进行解密。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *reader)</span> <span class="title">Read</span><span class="params">(b []<span class="keyword">byte</span>)</span> <span class="params">(<span class="keyword">int</span>, error)</span></span> &#123;</span><br><span class="line">    n, err := r.Reader.Read(b)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    b = b[:n]</span><br><span class="line">    r.XORKeyStream(b, b)</span><br><span class="line">    <span class="keyword">return</span> n, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>WriteTo</code> 方法反复使用上面的 <code>Read</code> 方法将数据解密后写入 <code>io.Writer</code> 中直到结束。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *reader)</span> <span class="title">WriteTo</span><span class="params">(w io.Writer)</span> <span class="params">(n <span class="keyword">int64</span>, err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        buf := r.buf</span><br><span class="line">        nr, er := r.Read(buf)</span><br><span class="line">        <span class="keyword">if</span> nr &gt; <span class="number">0</span> &#123;</span><br><span class="line">            nw, ew := w.Write(buf[:nr])</span><br><span class="line">            n += <span class="keyword">int64</span>(nw)</span><br><span class="line">   </span><br><span class="line">            <span class="keyword">if</span> ew != <span class="literal">nil</span> &#123;</span><br><span class="line">                err = ew</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> er != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> er != io.EOF &#123;</span><br><span class="line">                err = er</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/11/TokenBucket/index.html b/2018/05/11/TokenBucket/index.html
deleted file mode 100644
index bc67ba3..0000000
--- a/2018/05/11/TokenBucket/index.html
+++ /dev/null
@@ -1,263 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Token Bucket | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="学校里的宽带还是有分三六九等的，如果你钱交的多的，对应带宽自然比较高。但你想过他们是如何限制你的最高带宽的吗？其实用令牌桶（ Token Bucket ）这个算法就可以实现速率限制这个功能。 那么什么又是令牌桶的，简单的说就是假设你有一个专门用于放令牌的桶，桶的最大容量是有上限的，设为C，而该桶自带一个机制就是每隔固定的一段时间会产生一个令牌，一旦令牌充满了桶，桶中的令牌个数就不会再增加了。接下来">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Token Bucket">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/11/TokenBucket/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="学校里的宽带还是有分三六九等的，如果你钱交的多的，对应带宽自然比较高。但你想过他们是如何限制你的最高带宽的吗？其实用令牌桶（ Token Bucket ）这个算法就可以实现速率限制这个功能。 那么什么又是令牌桶的，简单的说就是假设你有一个专门用于放令牌的桶，桶的最大容量是有上限的，设为C，而该桶自带一个机制就是每隔固定的一段时间会产生一个令牌，一旦令牌充满了桶，桶中的令牌个数就不会再增加了。接下来">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://community.cambiumnetworks.com/bstrc49894/attachments/bstrc49894/forums_pmp_450/5991/1/TokenBucket.JPG">
-<meta property="og:updated_time" content="2018-06-26T08:47:33.190Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Token Bucket">
-<meta name="twitter:description" content="学校里的宽带还是有分三六九等的，如果你钱交的多的，对应带宽自然比较高。但你想过他们是如何限制你的最高带宽的吗？其实用令牌桶（ Token Bucket ）这个算法就可以实现速率限制这个功能。 那么什么又是令牌桶的，简单的说就是假设你有一个专门用于放令牌的桶，桶的最大容量是有上限的，设为C，而该桶自带一个机制就是每隔固定的一段时间会产生一个令牌，一旦令牌充满了桶，桶中的令牌个数就不会再增加了。接下来">
-<meta name="twitter:image" content="https://community.cambiumnetworks.com/bstrc49894/attachments/bstrc49894/forums_pmp_450/5991/1/TokenBucket.JPG">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TokenBucket"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Token Bucket
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-11T14:05:04.000Z" itemprop="datePublished">
-        May 11, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>学校里的宽带还是有分三六九等的，如果你钱交的多的，对应带宽自然比较高。但你想过他们是如何限制你的最高带宽的吗？其实用令牌桶（ <code>Token Bucket</code> ）这个算法就可以实现速率限制这个功能。</p>
-<p>那么什么又是令牌桶的，简单的说就是假设你有一个专门用于放令牌的桶，桶的最大容量是有上限的，设为C，而该桶自带一个机制就是每隔固定的一段时间会产生一个令牌，一旦令牌充满了桶，桶中的令牌个数就不会再增加了。接下来是重点，如果你要进行某个需要控制速率的操作，在执行这个操作之前，必须先从桶中拿到这个操作对应的令牌个数，比如规定了操作A需要5个令牌，操作B需要10个令牌，那么如果要执行操作A，则需要从桶中拿出5个令牌，如果桶中的令牌数目不够，就需要等到令牌数量足够时才能进行A操作。由于桶中令牌产生的速率是固定的，而在进行相关操作之前，又必须获得足够数量的令牌，这样就到达了速率限制（ <code>Rate Limiting</code> ）的目的。</p>
-<p>除了速率限制之外，令牌桶算法还具有流量整形（ <code>Traffic Shaping</code> ）的功能，因为令牌桶中的令牌是以恒定的速率产生的，所以一段时间内产生的令牌数量是固定的，如果在某一段时间消耗的令牌数量较多，也就是对应操作的数量很多，那么之后的一段时间的操作数量必定会收到限制，从整体上来看，操作的速率会比较均匀，也就是说流量是以比较均衡的速率向外发送的。</p>
-<p><img src="https://community.cambiumnetworks.com/bstrc49894/attachments/bstrc49894/forums_pmp_450/5991/1/TokenBucket.JPG" alt="Token Bucket"></p>
-<p>下面我们来看一下令牌桶算法的实现，由于令牌桶中非常重要的两个属性就是令牌桶的容量和令牌产生的速率，分别用 <code>capacity</code> 和 <code>rate</code> 来表示，我们使用一个通道来存储令牌，因为我们并不关心令牌的内容，所以我们使用 <code>tokens chan struct{}</code> 来表示这个桶。</p>
-<p>在初始化令牌桶的时候，直接起一个 <code>goroutine</code> 来定时向我们的桶中放入令牌，通过 <code>time.NewTicker</code> 用于定时生产令牌，如果令牌桶满了，则<code>b.tokens &lt;- struct{}{}</code> 操作也会被阻塞。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Bucket <span class="keyword">struct</span> &#123;</span><br><span class="line">    capacity <span class="keyword">int64</span></span><br><span class="line">    tokens <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    rate time.Duration</span><br><span class="line">    sync.Mutex</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewBucket</span><span class="params">(rate time.Duration, capacity <span class="keyword">int64</span>)</span> *<span class="title">Bucket</span></span> &#123;</span><br><span class="line">    tokens := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, capacity)</span><br><span class="line">    b := &amp;Bucket&#123;</span><br><span class="line">        capacity: capacity,</span><br><span class="line">        tokens: tokens,</span><br><span class="line">        rate: rate,</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(b *Bucket)</span></span> &#123;</span><br><span class="line">        ticker := time.NewTicker(rate)</span><br><span class="line">        <span class="keyword">for</span> _ := <span class="keyword">range</span> ticker.C &#123;</span><br><span class="line">            b.tokens &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;(b)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> b</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面给出了设置时间间隔（等效为速率）的方法，时间间隔越短，对应的平均速率就越快，二者成反比关系。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b *Bucket)</span> <span class="title">GetRate</span><span class="params">()</span> <span class="title">time</span>.<span class="title">Duration</span></span> &#123;</span><br><span class="line">    b.Lock()</span><br><span class="line">    tmp := b.rate</span><br><span class="line">    b.Unlock()</span><br><span class="line">    <span class="keyword">return</span> tmp</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b *Bucket)</span> <span class="title">SetRate</span><span class="params">(rate time.Duration)</span></span> &#123;</span><br><span class="line">    b.Lock()</span><br><span class="line">    b.rate = rate</span><br><span class="line">    b.Unlock()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>由于在进行特定操作之前需要取出固定数量的令牌，可以形象的把令牌想象为存在银行里的钱，把令牌桶想象成银行，如果你想要买一台电脑，你就需要从银行拿出足够的钱，如果银行中没有足够的钱，你只能等到你积累了足够的钱才可以买你想要的电脑。也就是说在执行相应操作之前需要有足够多的令牌才能顺利执行。注意到这个函数是阻塞的，只有在 <code>n</code> 次 <code>&lt;-b.tokens</code> 成功之后，该函数才会返回。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b *Bucket)</span> <span class="title">withdrawTokens</span><span class="params">(n <span class="keyword">int64</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">int64</span>(<span class="number">0</span>); i &lt; n; i++ &#123;</span><br><span class="line">        &lt;-b.tokens</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>SpendToken</code> 函数会返回一个通道，其函数内部会起一个 <code>goroutine</code> ，在该 <code>goroutine</code> 里会执行上述 <code>withdrawTokens</code> 方法，由于该函数是阻塞的，所以只有它执行完，才能将返回值放入通道 <code>c</code> 中，然后利用 <code>close(c)</code> 操作将该通道关闭，这样以来别处调用该函数的地方就可以顺利返回了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b *Bucket)</span> <span class="title">SpendToken</span><span class="params">(n <span class="keyword">uint64</span>)</span> &lt;-<span class="title">chan</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n &lt; <span class="number">0</span> &#123;</span><br><span class="line">        n = <span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    c := <span class="built_in">make</span>(<span class="keyword">chan</span> error)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(b *Bucket, n <span class="keyword">uint64</span>, c <span class="keyword">chan</span> error)</span></span> &#123;</span><br><span class="line">        c &lt;- b.withdrawTokens(n)</span><br><span class="line">        <span class="built_in">close</span>(c)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;(b, n, c)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> c</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Drain</code> 方法将桶中的所有令牌一次性放光，具体该在哪里使用它要看具体需求。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b *Bucket)</span> <span class="title">Drain</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> &lt;-b.tokens:</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        <span class="keyword">default</span>:</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="令牌桶的使用"><a href="#令牌桶的使用" class="headerlink" title="令牌桶的使用"></a>令牌桶的使用</h2><p>使用令牌桶之前当然需要新建一个令牌桶，并指定令牌桶的容量及其平均速率。因为使用令牌桶的目的之一就是限制速率，在需要被限速的函数（ <code>RegulatedAction()</code> ）前使用 <code>&lt;-bucket.SpendToken(x)</code> ，该 <code>RegulatedAction</code> 只有等到攒满 <code>x</code> 个令牌才会执行，这样就可以达到限制速率的目的了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">bucket := NewBucket(<span class="number">1</span> * time.Second, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">&lt;-bucket.SpendToken(<span class="number">10</span>)</span><br><span class="line">RegulatedAction()</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/12/AdvisoryLock/index.html b/2018/05/12/AdvisoryLock/index.html
deleted file mode 100644
index 04d0a1a..0000000
--- a/2018/05/12/AdvisoryLock/index.html
+++ /dev/null
@@ -1,260 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Advisory Lock | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="很多时候，在操作系统中，对于特定应用，我们只希望起一个进程实例，但是操作系统并没有限制同一个应用进程的个数，也就是说，在每个应用运行前，我们需要检测进程是否存在。 那么如何检测进程是否已经存在了呢，我们可以在进程启动时，生成一个以 .pid 结尾的文件，并向这个文件上加一个建议性锁（ advisory lock ），这样如果有第二个这个的进程起来，它会试着去打开这个 .pid 文件，并试着向这个文">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Advisory Lock">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/12/AdvisoryLock/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="很多时候，在操作系统中，对于特定应用，我们只希望起一个进程实例，但是操作系统并没有限制同一个应用进程的个数，也就是说，在每个应用运行前，我们需要检测进程是否存在。 那么如何检测进程是否已经存在了呢，我们可以在进程启动时，生成一个以 .pid 结尾的文件，并向这个文件上加一个建议性锁（ advisory lock ），这样如果有第二个这个的进程起来，它会试着去打开这个 .pid 文件，并试着向这个文">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:43:48.448Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Advisory Lock">
-<meta name="twitter:description" content="很多时候，在操作系统中，对于特定应用，我们只希望起一个进程实例，但是操作系统并没有限制同一个应用进程的个数，也就是说，在每个应用运行前，我们需要检测进程是否存在。 那么如何检测进程是否已经存在了呢，我们可以在进程启动时，生成一个以 .pid 结尾的文件，并向这个文件上加一个建议性锁（ advisory lock ），这样如果有第二个这个的进程起来，它会试着去打开这个 .pid 文件，并试着向这个文">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-AdvisoryLock"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Advisory Lock
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-12T05:26:04.000Z" itemprop="datePublished">
-        May 12, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>很多时候，在操作系统中，对于特定应用，我们只希望起一个进程实例，但是操作系统并没有限制同一个应用进程的个数，也就是说，在每个应用运行前，我们需要检测进程是否存在。</p>
-<p>那么如何检测进程是否已经存在了呢，我们可以在进程启动时，生成一个以 <code>.pid</code> 结尾的文件，并向这个文件上加一个建议性锁（ <code>advisory lock</code> ），这样如果有第二个这个的进程起来，它会试着去打开这个 <code>.pid</code> 文件，并试着向这个文件加建议性锁，但由于先起来的进程已经加过锁了，所以第二个进程就没有办法再加锁了，第二个进程知道自己不是第一个起起来的，所以就选择退出。</p>
-<p>等等，刚才说的建议性锁又是什么呢，建议性锁就好像人们指定的一系列规则， 例如交通法规建议人们红灯停，绿灯行，这里的红绿灯就是一个建议性锁，但是总有不听话的人不遵守这些规则，也就是说无视建议性锁的存在。建议性锁并不是强制性的，进程可以选择不去遵守它。</p>
-<p>上面进程的例子就是这样，第二个进程如果观测到文件已经上锁了，如果它不是恶意进程，那么它会选择尊重规则选择退出。</p>
-<h2 id="文件锁"><a href="#文件锁" class="headerlink" title="文件锁"></a>文件锁</h2><p>下面我们来实现一个文件锁，文件锁的本质就是文件，所以我们选择对 <code>os.File</code> 做一层封装，然后对它添加额外的行为使其成为一个真正的文件锁。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> LockFile <span class="keyword">struct</span> &#123;</span><br><span class="line">    *os.File</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewLockFile</span><span class="params">(file *os.File)</span> *<span class="title">LockFile</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;LockFile&#123;file&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>对文件上锁和解锁的过程其实就是利用系统调用 <code>syscall.Flock</code>，下面是c语言中的系统调用。</p>
-<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/file.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOCK_SH 1 <span class="comment">/* shared lock */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOCK_EX 2 <span class="comment">/* exclusive lock */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOCK_NB 4 <span class="comment">/* don't block when locking */</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LOCK_UN 8 <span class="comment">/* unlock */</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span></span><br><span class="line">flock(<span class="keyword">int</span> fd, <span class="keyword">int</span> operation)</span><br></pre></td></tr></table></figure>
-<p>建议性锁分为两大类：共享锁（ <code>SH</code> ）和专有锁（ <code>EX</code> ），这里我们采用专有锁，也就是利用 <code>LOCK_EX</code> 选项，如果文件已经上过锁了，再次尝试对该文件上锁时，操作会被阻塞，为了避免调用此系统调用的进程被阻塞，我们在系统调用时增加一个 <code>LOCK_NB</code> 选项，也就是非阻塞（ <code>non blocking</code> ）的意思，指定该选项后如果尝试上锁时，文件已经上过锁了，此时则则不会发生阻塞而是返回一个 <code>EWOULDBLOCK</code> 错误，当对文件解锁时，只需要在系统调用时指定 <code>LOCK_UN</code> 选项就可以了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">ErrWouldBlock = errors.New(<span class="string">"Resource temporarily unavailable"</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(file *LockFile)</span> <span class="title">Lock</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> lockFile(file.Fd())</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">lockFile</span><span class="params">(fd <span class="keyword">uintptr</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    err := syscall.Flock(<span class="keyword">int</span>(fd), syscall.LOCK_EX|syscall.LOCK_NB)</span><br><span class="line">    <span class="keyword">if</span> err == syscall.EWOULDBLOCK &#123;</span><br><span class="line">        err = ERRWouldBlock</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(file *LockFile)</span> <span class="title">Unlock</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> unlockFile(file.Fd())</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">unlockFile</span><span class="params">(fd <span class="keyword">uintptr</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    err := syscall.Flock(<span class="keyword">int</span>(fd), syscall.LOCK_UN)</span><br><span class="line">    <span class="keyword">if</span> err == syscall.EWouldBLOCK &#123;</span><br><span class="line">        err = ErrWouldBlock</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>OpenLockFile</code> 方法很简单，就是对 <code>os.OpenFile</code> 方法进行了一层封装，将此方法返回的 <code>file</code> 封装为<code>LockFile</code> 返回供接下去使用。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">OpenLockFile</span><span class="params">(name <span class="keyword">string</span>, perm os.FileMode)</span> <span class="params">(lock *LockFile, err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> file *os.File</span><br><span class="line">    <span class="keyword">if</span> file, err = os.OpenFile(name, os.O_RWWR|os.O_CREATE, perm); err == <span class="literal">nil</span> &#123;</span><br><span class="line">        lock = &amp;LockFile&#123;file&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="进程存在性检测"><a href="#进程存在性检测" class="headerlink" title="进程存在性检测"></a>进程存在性检测</h2><p>文件上锁可以用作进程存在性检测，我们在进程创建时生成一个以 <code>.pid</code> 结尾的文件，并向该文件中写入当前进程的进程号，下面的 <code>WritePid</code> 方法就将当前进程的进程号写入文件起始位置，而 <code>ReadPid</code> 则将此文件中存储的 <code>pid</code> 读取出来，注意这里无论是读操作还是写操作都会先将文件的指针定位到最开始的位置（通过 <code>file.Seek(0, os.SEEK_SET)</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(file *LockFile)</span> <span class="title">WritePid</span><span class="params">()</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> _, err = file.Seek(<span class="number">0</span>, os.SEEK_SET); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> fileLen <span class="keyword">int</span></span><br><span class="line">    <span class="keyword">if</span> fileLen, err = fmt.Fprint(file, os.Getpid()); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> err = file.Truncate(<span class="keyword">int64</span>(fileLen)); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    err = file.Sync()</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(file *LockFile)</span> <span class="title">ReadPid</span><span class="params">()</span> <span class="params">(pid <span class="keyword">int</span>, err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> _, err = file.Seek(<span class="number">0</span>, os.SEEK_SET); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    _, err = fmt.Fscan(file, &amp;pid)</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(file *LockFile)</span> <span class="title">Remove</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">defer</span> file.Close()</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> err := file.Unlock(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> os.Remove(file.Name())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>当我们创建一个 <code>pid</code> 文件时候，我们需要检测其他进程是否已经存在，<code>CreatePidFile</code> 方法会使用 <code>Lock</code> 方法尝试对文件上锁，如果上锁失败，则说明已经有进程对该文件上过锁，此时则应该选择退出，如果上锁成功，则说明自己是第一个进程，并将自己的进程号写入该文件中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CreatePidFile</span><span class="params">(name <span class="keyword">string</span>, perm os.FileMode)</span> <span class="params">(lock *LockFile, err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> lock, err = OpenLockFile(name, perm); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> err = lock.Lock(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        lock.Remove()</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> err = lock.WritePid(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        lock.Remove()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ReadPidFile</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(pid <span class="keyword">int</span>, err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> file *os.File</span><br><span class="line">    <span class="keyword">if</span> file, err = os.OpenFile(name, os.O_RDONLY, <span class="number">0640</span>); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> file.Close()</span><br><span class="line">    lock := &amp;LockFile&#123;file&#125;</span><br><span class="line">    pid, err = lock.ReadPid()</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/12/ReverseProxy/index.html b/2018/05/12/ReverseProxy/index.html
deleted file mode 100644
index d1e5cd3..0000000
--- a/2018/05/12/ReverseProxy/index.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Reverse Proxy | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在正常的 HTTP 服务流程中，客户端向服务器发送 HTTP 请求，服务器收到后会向客户端返回一个 HTTP 答复。但在实际生产环境中，真正处理请求的服务器和客户端之间通常还会引入一个中介，也就是反向代理服务器，在引入了反向代理服务器之后，客户端会先将请求发送给反向代理服务器，反向代理收到该 HTTP 请求后，并不会自己亲自处理该请求，而是将请求转发给真正的处理业务逻辑的服务器，让它去处理，业务逻">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Reverse Proxy">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/12/ReverseProxy/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在正常的 HTTP 服务流程中，客户端向服务器发送 HTTP 请求，服务器收到后会向客户端返回一个 HTTP 答复。但在实际生产环境中，真正处理请求的服务器和客户端之间通常还会引入一个中介，也就是反向代理服务器，在引入了反向代理服务器之后，客户端会先将请求发送给反向代理服务器，反向代理收到该 HTTP 请求后，并不会自己亲自处理该请求，而是将请求转发给真正的处理业务逻辑的服务器，让它去处理，业务逻">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Reverse_proxy_h2g2bob.svg/1200px-Reverse_proxy_h2g2bob.svg.png">
-<meta property="og:updated_time" content="2018-06-26T08:48:11.658Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Reverse Proxy">
-<meta name="twitter:description" content="在正常的 HTTP 服务流程中，客户端向服务器发送 HTTP 请求，服务器收到后会向客户端返回一个 HTTP 答复。但在实际生产环境中，真正处理请求的服务器和客户端之间通常还会引入一个中介，也就是反向代理服务器，在引入了反向代理服务器之后，客户端会先将请求发送给反向代理服务器，反向代理收到该 HTTP 请求后，并不会自己亲自处理该请求，而是将请求转发给真正的处理业务逻辑的服务器，让它去处理，业务逻">
-<meta name="twitter:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Reverse_proxy_h2g2bob.svg/1200px-Reverse_proxy_h2g2bob.svg.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ReverseProxy"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Reverse Proxy
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-12T13:30:04.000Z" itemprop="datePublished">
-        May 12, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在正常的 <code>HTTP</code> 服务流程中，客户端向服务器发送 <code>HTTP</code> 请求，服务器收到后会向客户端返回一个 <code>HTTP</code> 答复。但在实际生产环境中，真正处理请求的服务器和客户端之间通常还会引入一个中介，也就是反向代理服务器，在引入了反向代理服务器之后，客户端会先将请求发送给反向代理服务器，反向代理收到该 <code>HTTP</code> 请求后，并不会自己亲自处理该请求，而是将请求转发给真正的处理业务逻辑的服务器，让它去处理，业务逻辑服务器处理完之后，会先将答复返回给反向代理服务器，再由反向代理服务器返回给客户端。</p>
-<p>生活中常见的 <code>NGINX</code> 就常常作为反向代理服务器来使用。那么你可能会问，传统 <code>C/S</code> 模型难道不够好吗，还非要引入一个不知道什么鬼的反向代理来捣乱，引入之后只会把架构变得更复杂，有啥好处？（傲娇状）其实原因很简单，第一反向代理服务器可以当作防火墙来用，它为真正的业务逻辑服务器与外界可能的恶意攻击之间提供了一个屏障，尤其是像银行这种对安全性要求极高的金融机构无论加几个这样的防火墙都不会嫌多。第二点就是它可以提供负载均衡功能，通过使用不同的策略将请求转发给不同的服务器，以达到负载均衡的目的。</p>
-<p>幸运的是，引入反向代理，并不会改变传统的 <code>C/S</code> 编程模型，因为客户端无法感知反向代理服务器的存在，他们只会觉得反向代理服务器就是真正处理业务逻辑的服务器。</p>
-<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Reverse_proxy_h2g2bob.svg/1200px-Reverse_proxy_h2g2bob.svg.png" alt="Reverse Proxy"></p>
-<p>下面我们来实现一个简单的反向代理服务器吧，虽然听着很恐怖，但是不用慌，强大的 <code>Golang</code> 标准库已经实现了反向代理的功能了。<code>httputil</code> 中提供的 <code>ReverseProxy</code> 结构体具有将请求重定向的能力（ <code>Director</code> ），也具有将答复修改的能力（ <code>ModifyResponse</code> ），最重要的是，可以通过 <code>Transport</code> 这个 <code>http.RoundTripper</code> 将我们的代理请求发送出去。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ReverseProxy <span class="keyword">struct</span> &#123;</span><br><span class="line">    Director      <span class="function"><span class="keyword">func</span><span class="params">(*http.Request)</span></span></span><br><span class="line"><span class="function">    <span class="title">Transport</span>     <span class="title">http</span>.<span class="title">RoundTripper</span></span></span><br><span class="line"><span class="function">    <span class="title">FlushInterval</span> <span class="title">time</span>.<span class="title">Duration</span></span></span><br><span class="line"><span class="function">    <span class="title">ErrorLog</span>      *<span class="title">log</span>.<span class="title">Logger</span></span></span><br><span class="line"><span class="function">    <span class="title">BufferPool</span>    <span class="title">BufferPool</span></span></span><br><span class="line"><span class="function">    <span class="title">ModifyReponse</span> <span class="title">func</span><span class="params">(*http.Response)</span> <span class="title">error</span></span></span><br><span class="line"><span class="function">&#125;</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">type</span> <span class="title">RoundTripper</span> <span class="title">interface</span></span> &#123;</span><br><span class="line">    RoundTrip(*http.Request) (*http.Response, error)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>作为一个代理服务器，虽然不直接处理业务逻辑，但是最基本的对请求的处理和答复的功能还是要有的，与一般的 <code>HTTP</code> 服务器类似，我们的反向代理服务器 <code>ReverseProxy</code> 也需要有 <code>ServeHTTP(http.ResponseWriter, *http.Request)</code> 这样的方法。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Handler <span class="keyword">interface</span> &#123;</span><br><span class="line">    ServeHTTP(http.ResponseWriter, *http.Request)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>所以为了实现代理请求的功能，我们需要定义一个结构体 <code>handler</code> ，使其实现 <code>ServeHTTP(http.ResponseWriter, *http.Request)</code> 方法，在该方法中我们通过 <code>httputil.NewSingleHostReverseProxy</code> 来构造一个反向代理，并将请求通过 <code>proxy.ServeHTTP(w, r)</code> 方法将请求代理到随机的（随机是为了实现负载均衡）服务器上。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">servers := []<span class="keyword">string</span>&#123;</span><br><span class="line">     <span class="string">"111.222.111.222"</span>,</span><br><span class="line">     <span class="string">"222.111.222.111"</span>,</span><br><span class="line">     <span class="string">"111.233.111.233"</span>,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> handler <span class="keyword">struct</span> &#123;</span><br><span class="line">    reverseProxy <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(this *handler)</span> <span class="title">ServeHTTP</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    addr := servers[rand.Intn(<span class="built_in">len</span>(servers))]</span><br><span class="line">    remote, err := url.Parse(<span class="string">"http://"</span> + addr)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    proxy := httputil.NewSingleHostReverseProxy(remote)</span><br><span class="line">    proxy.ServeHTTP(w, r)   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面我们申明一个 <code>http.Server</code> ，在 <code>StartServer</code> 中我们监听指定的端口（ <code>bind</code> ），其对应的 <code>Handler</code> 就是我们之前实现的 <code>handler</code> 结构体，用于把请求代理到 <code>remote</code> 上去，这样以来一个基本的反向代理服务器就实现好了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> srv http.Server</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">StartServer</span><span class="params">(bind <span class="keyword">string</span>, remote <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    log.Printf(<span class="string">"Listening on %s, forwarding to %s"</span>, bind, remote)</span><br><span class="line">    h := &amp;handler&#123;reverseProxy: remote&#125;</span><br><span class="line">    srv.Addr = bind</span><br><span class="line">    srv.Handler = h</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> err := srv.ListenAndServe(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatalln(<span class="string">"ListenAndServe:"</span> err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">StopServer</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> err := srv.Shutdown(<span class="literal">nil</span>); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    StartServer(<span class="string">":8080"</span>, <span class="string">"remote:8080"</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上述例子中的采用的负载均衡算法只用了非常简单的随机选取策略，这只适合每台服务器性能差别不大的情况，如果服务器之间性能差距较大，我们可以使用 <code>Weighted Round Robin</code> 这样的负载均衡算法。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/13/JobDispatcher/index.html b/2018/05/13/JobDispatcher/index.html
deleted file mode 100644
index 516ab50..0000000
--- a/2018/05/13/JobDispatcher/index.html
+++ /dev/null
@@ -1,270 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Job Dispatcher | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="当处理大量计算密集型任务时，为了提高工作效率，常常会引入多台服务器同时进行处理，但是不同的服务器之间并不清楚自己该处理哪个任务，也就是说服务器自己并不能保证自己处理的任务和别人的任务是不一样的。为了解决上述问题，我们引入 Job Dispatcher 模型。 我们把处理任务的服务器称为 Worker ，而把分配任务的服务器称为Dispatcher 或者 Master 。Dispatcher 负责给">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Job Dispatcher">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/13/JobDispatcher/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="当处理大量计算密集型任务时，为了提高工作效率，常常会引入多台服务器同时进行处理，但是不同的服务器之间并不清楚自己该处理哪个任务，也就是说服务器自己并不能保证自己处理的任务和别人的任务是不一样的。为了解决上述问题，我们引入 Job Dispatcher 模型。 我们把处理任务的服务器称为 Worker ，而把分配任务的服务器称为Dispatcher 或者 Master 。Dispatcher 负责给">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:26.597Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Job Dispatcher">
-<meta name="twitter:description" content="当处理大量计算密集型任务时，为了提高工作效率，常常会引入多台服务器同时进行处理，但是不同的服务器之间并不清楚自己该处理哪个任务，也就是说服务器自己并不能保证自己处理的任务和别人的任务是不一样的。为了解决上述问题，我们引入 Job Dispatcher 模型。 我们把处理任务的服务器称为 Worker ，而把分配任务的服务器称为Dispatcher 或者 Master 。Dispatcher 负责给">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-JobDispatcher"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Job Dispatcher
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-13T13:34:24.000Z" itemprop="datePublished">
-        May 13, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>当处理大量计算密集型任务时，为了提高工作效率，常常会引入多台服务器同时进行处理，但是不同的服务器之间并不清楚自己该处理哪个任务，也就是说服务器自己并不能保证自己处理的任务和别人的任务是不一样的。为了解决上述问题，我们引入 <code>Job Dispatcher</code> 模型。</p>
-<p>我们把处理任务的服务器称为 <code>Worker</code> ，而把分配任务的服务器称为<code>Dispatcher</code> 或者 <code>Master</code> 。<code>Dispatcher</code> 负责给当前处于空闲状态的 <code>Worker</code> 分配任务 （ <code>Job</code> ），当其处理完分配的任务之后，为了不让自己的 <code>CPU</code> 闲置，<code>Worker</code> 会通知 <code>Dispather</code> 自己是可用的（ <code>available</code> ） ，然后 <code>Dispatcher</code> 就可以继续向 <code>Worker</code> 分配任务，直到所有任务全都完成。这样的模型非常 <code>scalable</code> ，引入的 <code>Worker</code> 数量越多，任务完成得越快。</p>
-<h2 id="Worker"><a href="#Worker" class="headerlink" title="Worker"></a>Worker</h2><p>一个任务我们用结构体 <code>Job</code> 来表示，现在对于此结构体中有什么我们并不关心，这个需要由业务逻辑具体定义。</p>
-<p> <code>Worker</code> 中有三个 <code>channel</code> ，分别用于暂停，接收任务和通知 <code>Dispatcher</code> 任务完成用的。</p>
-<p><code>Worker</code> 肯定需要某种机制停止退出，我们用一个 <code>exit chan struct{}</code> 通道来接收停止信号，如果该通道中收到了停止信号，也就可以说明今天的任务已经全部完成了，<code>Worker</code> 可以回家休息了。</p>
-<p><code>Jobs chan Job</code> 通道很简单，当然就是用于接受任务的啦，相对来说，任务可是做不完的，一个任务做完下一个任务就马不停蹄的赶来了，所以用通道来表示可以说是再合适不过了。</p>
-<p>最后来看一下最复杂的一个通道 <code>WorkerPool chan chan Job</code> ，这啥玩意啊，通道的通道？想想就头大，外层的通道的中包含了 <code>chan Job</code> ，也就是上面说过的 <code>Jobs</code> 通道，其实就代表 <code>Worker</code> 本身， 如果一个 <code>Job</code> 处理完了， <code>Worker</code> 就会处于空闲状态，所以就可以把它放在 <code>WorkerPool</code> 中等待 <code>Dispatcher</code> 来调度了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Job <span class="keyword">struct</span> &#123;</span><br><span class="line">    Payload <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Worker <span class="keyword">struct</span> &#123;</span><br><span class="line">    WorkerPool <span class="keyword">chan</span> <span class="keyword">chan</span> Job</span><br><span class="line">    Jobs       <span class="keyword">chan</span> Job</span><br><span class="line">    exit       <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewWorker</span><span class="params">(workerPool <span class="keyword">chan</span> <span class="keyword">chan</span> Job)</span> *<span class="title">Worker</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Worker&#123;</span><br><span class="line">        WorkerPool: workerPool,</span><br><span class="line">        Jobs:       <span class="built_in">make</span>(<span class="keyword">chan</span> Job),</span><br><span class="line">        exit:       <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Stop</code> 方法向 <code>exit</code> 通道发送信号，这样一来 <code>Start</code> 方法中的 <code>select</code> 语句的第二个 <code>case</code> 就会被执行，<code>Worker</code> 就可以退出了。在 <code>Start</code> 方法中，<code>w.WorkerPool &lt;- w.Jobs</code> 会向 <code>WorkerPool</code> 中注册它自己，也就相当于向 <code>Dispatcher</code> 申明自己已经处于空闲状态，随时等待被调度。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *Worker)</span> <span class="title">Start</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            w.WorkerPool &lt;- w.Jobs</span><br><span class="line">            <span class="keyword">select</span> &#123;</span><br><span class="line">            <span class="keyword">case</span> job := &lt;- w.Jobs:</span><br><span class="line">                <span class="comment">// do some heavy job here</span></span><br><span class="line">            <span class="keyword">case</span> &lt;-w.exit:</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *Worker)</span> <span class="title">Stop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        w.exit &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Dispatcher"><a href="#Dispatcher" class="headerlink" title="Dispatcher"></a>Dispatcher</h2><p>所有的任务都是从外界来的（此处我们选择从 <code>JobQueue</code> 中读取），任务到来时并不会直接分配给 <code>Worker</code> ，而是先经过 <code>Dispatcher</code> 的魔爪，<code>Dispatcher</code> 会先判断哪个 <code>Worker</code> 处于空闲状态，然后再分配给空闲的 <code>Worker</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> JobQueue <span class="keyword">chan</span> Job</span><br></pre></td></tr></table></figure>
-<p><code>Dispatcher</code> 结构体中的 <code>WorkerPool chan chan Job</code> 是任务调度实现的核心，我们上述 <code>Worker</code> 中的和 <code>Dispatcher</code> 中的其实是一个东西，<code>Worker</code> 中的是对 <code>Dispatcher</code> 中的一个引用而已。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Dispatcher <span class="keyword">struct</span> &#123;</span><br><span class="line">    WorkerPool <span class="keyword">chan</span> <span class="keyword">chan</span> Job</span><br><span class="line">    MaxWorkers <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewDispatcher</span><span class="params">(maxWorkers <span class="keyword">int</span>)</span> *<span class="title">Dispatcher</span></span> &#123;</span><br><span class="line">    pool := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">chan</span> Job, maxWorkers)</span><br><span class="line">    <span class="keyword">return</span> &amp;Dispatcher&#123;</span><br><span class="line">        WorkerPool: pool,</span><br><span class="line">        MaxWorkers: maxWorkers,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Run</code> 方法中起了 <code>MaxWorkers</code> 个 <code>Worker</code> 等待 <code>Dispatcher</code> 给自己分配任务。</p>
-<p>在 <code>dispatch</code> 方法中，<code>Dispatcher</code> 会不断的从 <code>JobQueue</code> 中读取任务，并在 <code>WorkerPool</code> 中选取一个空闲的 <code>Worker</code> （ <code>worker := &lt;-d.WorkerPool</code> ），然后将任务分配给它（ <code>worker &lt;- job</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Dispatcher)</span> <span class="title">Run</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; d.MaxWorkers; i++ &#123;</span><br><span class="line">        worker := NewWorker(d.WorkerPool)</span><br><span class="line">        worker.Start()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">go</span> d.dispatch()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Dispatcher)</span> <span class="title">dispatch</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> job := &lt;- JobQueue:</span><br><span class="line">            <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(job Job)</span></span> &#123;</span><br><span class="line">                worker := &lt;-d.WorkerPool</span><br><span class="line">                worker &lt;- job</span><br><span class="line">            &#125;(job)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Work-scheduler"><a href="#Work-scheduler" class="headerlink" title="Work scheduler"></a>Work scheduler</h2><ul>
-<li>Use a buffered channel as a concurrent blocking queue.</li>
-<li>Use coroutines to let independent concerns run independently </li>
-<li>Use the race detector for development and even production.</li>
-<li>Think carefully before introducing unbounded queuing</li>
-<li>Close a channel to signal that no more values will be sent.</li>
-<li>Know why and when each communication will proceed.</li>
-<li>Make sure you know why and when each goroutine will exit.</li>
-</ul>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Schedule</span><span class="params">(servers []<span class="keyword">string</span>, numTask <span class="keyword">int</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">         call <span class="keyword">func</span>(srv <span class="keyword">string</span>, task <span class="keyword">int</span>)</span> <span class="title">bool</span>)</span> &#123;</span><br><span class="line">    work := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>, numTask)</span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)</span><br><span class="line">    exit := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)</span><br><span class="line">    runTasks := <span class="function"><span class="keyword">func</span><span class="params">(srv <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> task := <span class="keyword">range</span> work &#123;</span><br><span class="line">            <span class="keyword">if</span> call(srv, task) &#123;</span><br><span class="line">                done &lt;- <span class="literal">true</span></span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                work &lt;- task</span><br><span class="line">            &#125;             </span><br><span class="line">        &#125; </span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            <span class="keyword">select</span> &#123;</span><br><span class="line">            <span class="keyword">case</span> srv := &lt;-servers:</span><br><span class="line">                <span class="keyword">go</span> runTasks(srv)</span><br><span class="line">            <span class="keyword">case</span> &lt;-exit:</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">   </span><br><span class="line">    <span class="keyword">for</span> task := <span class="number">0</span>; task &lt; numTask; task++ &#123;</span><br><span class="line">        work &lt;- task</span><br><span class="line">    &#125;    </span><br><span class="line">    </span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; numTask; i++ &#123;</span><br><span class="line">        &lt;-done</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">close</span>(work)</span><br><span class="line">    exit &lt;- <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/14/TerminalUI/index.html b/2018/05/14/TerminalUI/index.html
deleted file mode 100644
index 7d69bc8..0000000
--- a/2018/05/14/TerminalUI/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Terminal UI | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="之前用命令行版本的网易云音乐来听歌（ musicbox ，在 github 上可以搜索到），觉得实在是太 geek 了，但它是用 python 写的，略微容易崩，所以决定试着用 golang 仿造一个，第一步肯定是模仿它的 UI 了，在浏览器中我们用三元老 HTML/CSS/JS 可以很容易撸出一套能看的前端界面来，但估计没几个人知道命令行版本的 UI 应该怎么搞，其实说实话我也不知道，大概搜了一">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Terminal UI">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/14/TerminalUI/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="之前用命令行版本的网易云音乐来听歌（ musicbox ，在 github 上可以搜索到），觉得实在是太 geek 了，但它是用 python 写的，略微容易崩，所以决定试着用 golang 仿造一个，第一步肯定是模仿它的 UI 了，在浏览器中我们用三元老 HTML/CSS/JS 可以很容易撸出一套能看的前端界面来，但估计没几个人知道命令行版本的 UI 应该怎么搞，其实说实话我也不知道，大概搜了一">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:42.103Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Terminal UI">
-<meta name="twitter:description" content="之前用命令行版本的网易云音乐来听歌（ musicbox ，在 github 上可以搜索到），觉得实在是太 geek 了，但它是用 python 写的，略微容易崩，所以决定试着用 golang 仿造一个，第一步肯定是模仿它的 UI 了，在浏览器中我们用三元老 HTML/CSS/JS 可以很容易撸出一套能看的前端界面来，但估计没几个人知道命令行版本的 UI 应该怎么搞，其实说实话我也不知道，大概搜了一">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TerminalUI"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Terminal UI
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-14T14:49:04.000Z" itemprop="datePublished">
-        May 14, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>之前用命令行版本的网易云音乐来听歌（ <code>musicbox</code> ，在 <code>github</code> 上可以搜索到），觉得实在是太 <code>geek</code> 了，但它是用 <code>python</code> 写的，略微容易崩，所以决定试着用 <code>golang</code> 仿造一个，第一步肯定是模仿它的 <code>UI</code> 了，在浏览器中我们用三元老 <code>HTML/CSS/JS</code> 可以很容易撸出一套能看的前端界面来，但估计没几个人知道命令行版本的 <code>UI</code> 应该怎么搞，其实说实话我也不知道，大概搜了一下，发现用 <code>termui</code> 这个库就可以比较轻松撸出一个与 <code>musicbox</code> 类似的界面了，下面我们来看一下如何用代码来实现吧。</p>
-<h2 id="termui-安装"><a href="#termui-安装" class="headerlink" title="termui 安装"></a>termui 安装</h2><p>一般来说我们可以使用 <code>go get</code> 来进行获取安装，但最好使用 <code>dep</code> 来帮助我们管理项目的相关依赖。</p>
-<p><code>go get -u github.com/gizak/termui</code></p>
-<p>然后在代码中 <code>import</code> 就可以了。</p>
-<p><code>import &quot;github.com/gizak/termui&quot;</code></p>
-<h2 id="初始化"><a href="#初始化" class="headerlink" title="初始化"></a>初始化</h2><p>在使用 <code>termui</code> 时需要先进行初始化（ <code>termui.Init()</code> ），并且最后还要释放资源 <code>defer termui.Close()</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">err := termui.Init()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="built_in">panic</span>(err)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">defer</span> termui.Close()</span><br></pre></td></tr></table></figure>
-<h2 id="界面相关数据准备"><a href="#界面相关数据准备" class="headerlink" title="界面相关数据准备"></a>界面相关数据准备</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">strs := []<span class="keyword">string</span>&#123;</span><br><span class="line">    <span class="string">"   0. 排行榜"</span>,</span><br><span class="line">    <span class="string">"   1. 艺术家"</span>,</span><br><span class="line">    <span class="string">"   2. 新碟上架"</span>,</span><br><span class="line">    <span class="string">"   3. 精选歌单"</span>,</span><br><span class="line">    <span class="string">"   4. 我的歌单"</span>,</span><br><span class="line">    <span class="string">"   5. 主播电台"</span>,</span><br><span class="line">    <span class="string">"   6. 每日推荐"</span>,</span><br><span class="line">    <span class="string">"   7. 私人FM"</span>,</span><br><span class="line">    <span class="string">"   8. 搜索"</span>,</span><br><span class="line">    <span class="string">"   9. 帮助"</span>,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">off := []<span class="keyword">string</span>&#123;</span><br><span class="line">    <span class="string">"   0. 排行榜"</span>,</span><br><span class="line">    <span class="string">"   1. 艺术家"</span>,</span><br><span class="line">    <span class="string">"   2. 新碟上架"</span>,</span><br><span class="line">    <span class="string">"   3. 精选歌单"</span>,</span><br><span class="line">    <span class="string">"   4. 我的歌单"</span>,</span><br><span class="line">    <span class="string">"   5. 主播电台"</span>,</span><br><span class="line">    <span class="string">"   6. 每日推荐"</span>,</span><br><span class="line">    <span class="string">"   7. 私人FM"</span>,</span><br><span class="line">    <span class="string">"   8. 搜索"</span>,</span><br><span class="line">    <span class="string">"   9. 帮助"</span>,</span><br><span class="line">&#125;</span><br><span class="line">on := []<span class="keyword">string</span>&#123;</span><br><span class="line">    <span class="string">"[-&gt; 0. 排行榜](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 1. 艺术家](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 2. 新碟上架](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 3. 精选歌单](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 4. 我的歌单](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 5. 主播电台](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 6. 每日推荐](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 7. 私人FM](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 8. 搜索](fg-cyan)"</span>,</span><br><span class="line">    <span class="string">"[-&gt; 9. 帮助](fg-cyan)"</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="定义界面参数"><a href="#定义界面参数" class="headerlink" title="定义界面参数"></a>定义界面参数</h2><p>在使用 <code>termui</code> 时，我们需要确定界面元素及其属性，以及它在命令行中的排版，其实 <code>UI</code> 就是对数据的一种呈现，反正就是你觉得怎么好看就怎么来。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">ls := termui.List()</span><br><span class="line">ls.Items = strs</span><br><span class="line">ls.ItemFgColor = termui.ColorWhite</span><br><span class="line">ls.BorderLabel = <span class="string">"网易云音乐"</span></span><br><span class="line">ls.Height = <span class="number">12</span></span><br><span class="line">ls.Width = <span class="number">20</span></span><br><span class="line">ls.Y = <span class="number">0</span></span><br></pre></td></tr></table></figure>
-<h2 id="termui对事件的处理"><a href="#termui对事件的处理" class="headerlink" title="termui对事件的处理"></a>termui对事件的处理</h2><p><code>termui</code> 对事件的处理和 <code>HTTP</code> 处理事件的做法类似，我们需要对不同的事件注册回调函数，例如检测到用户输入 <code>q</code> ，我们注册一个类似的回调函数就可以了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">termui.Handle(<span class="string">"/sys/kbd/q"</span>, <span class="function"><span class="keyword">func</span><span class="params">(termui.Event)</span></span> &#123;</span><br><span class="line">    termui.StopLoop()</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
-<p>相关事件可以是键盘输入，界面点击，窗口伸缩甚至可以是自定义事件。相关事件触发后，对应的数据可能会发生改变，这样以来用户界面就需要发生改变，我们可以使用 <code>termui.Render</code> 对界面重新进行渲染。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">cursor := <span class="number">0</span></span><br><span class="line">termui.Render(ls)</span><br><span class="line">termui.Handle(<span class="string">"/sys/kbd/j"</span>, <span class="function"><span class="keyword">func</span><span class="params">(termui.Event)</span></span> &#123;</span><br><span class="line">    strs[cursor%<span class="built_in">len</span>(strs)] = off[cursor%<span class="built_in">len</span>(strs)]</span><br><span class="line">    cursor++</span><br><span class="line">    <span class="keyword">if</span> cursor == <span class="built_in">len</span>(strs) &#123;</span><br><span class="line">        cursor = <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">    strs[cursor%<span class="built_in">len</span>(strs)] = on[cursor%<span class="built_in">len</span>(strs)]</span><br><span class="line">    termui.Render(ls)</span><br><span class="line">&#125;)</span><br><span class="line">termui.Handle(<span class="string">"/sys/kbd/k"</span>, <span class="function"><span class="keyword">func</span><span class="params">(termui.Event)</span></span> &#123;</span><br><span class="line">    strs[cursor%<span class="built_in">len</span>(strs)] = off[cursor%<span class="built_in">len</span>(strs)]</span><br><span class="line">    cursor--</span><br><span class="line">    <span class="keyword">if</span> cursor &lt; <span class="number">0</span> &#123;</span><br><span class="line">        cursor = <span class="built_in">len</span>(strs) - <span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line">    strs[cursor%<span class="built_in">len</span>(strs)] = on[cursor%<span class="built_in">len</span>(strs)]</span><br><span class="line">    termui.Render(ls)</span><br><span class="line">&#125;)</span><br><span class="line">termui.Loop()</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/15/ConnectionLimiter/index.html b/2018/05/15/ConnectionLimiter/index.html
deleted file mode 100644
index 9f44e9f..0000000
--- a/2018/05/15/ConnectionLimiter/index.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Connection Limiter | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="作为服务提供商，我们肯定是希望越多客户使用我们的服务越好，为此我们不惜花大价钱雇程序员来搞高并发服务器编程，砸很多的钱买最好的服务器，但是总有些无良用户想要和我们作对，搞很多 HTTP 连接请求恶意占用服务器的资源，导致其他用户的服务体验下降，从而最终导致客户的流失，这种情况我们肯定是希望极力避免的。 一般来说，正常的客户端（人为操作）不会在短时间内对同一服务发送过多的请求，只有想要实施恶意攻击行">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Connection Limiter">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/15/ConnectionLimiter/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="作为服务提供商，我们肯定是希望越多客户使用我们的服务越好，为此我们不惜花大价钱雇程序员来搞高并发服务器编程，砸很多的钱买最好的服务器，但是总有些无良用户想要和我们作对，搞很多 HTTP 连接请求恶意占用服务器的资源，导致其他用户的服务体验下降，从而最终导致客户的流失，这种情况我们肯定是希望极力避免的。 一般来说，正常的客户端（人为操作）不会在短时间内对同一服务发送过多的请求，只有想要实施恶意攻击行">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:44:19.449Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Connection Limiter">
-<meta name="twitter:description" content="作为服务提供商，我们肯定是希望越多客户使用我们的服务越好，为此我们不惜花大价钱雇程序员来搞高并发服务器编程，砸很多的钱买最好的服务器，但是总有些无良用户想要和我们作对，搞很多 HTTP 连接请求恶意占用服务器的资源，导致其他用户的服务体验下降，从而最终导致客户的流失，这种情况我们肯定是希望极力避免的。 一般来说，正常的客户端（人为操作）不会在短时间内对同一服务发送过多的请求，只有想要实施恶意攻击行">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ConnectionLimiter"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Connection Limiter
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-15T02:18:24.000Z" itemprop="datePublished">
-        May 15, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>作为服务提供商，我们肯定是希望越多客户使用我们的服务越好，为此我们不惜花大价钱雇程序员来搞高并发服务器编程，砸很多的钱买最好的服务器，但是总有些无良用户想要和我们作对，搞很多 <code>HTTP</code> 连接请求恶意占用服务器的资源，导致其他用户的服务体验下降，从而最终导致客户的流失，这种情况我们肯定是希望极力避免的。</p>
-<p>一般来说，正常的客户端（人为操作）不会在短时间内对同一服务发送过多的请求，只有想要实施恶意攻击行为的客户端（例如爬虫）才会同时发送很多请求来占用服务器的资源。为了避免这种情况的发生，我们需要限制同一个 <code>IP</code> 地址的请求数量。</p>
-<p>实现连接限制的思路比较简单，我们通过一个 <code>map</code> 来记录来自同一个 <code>IP</code> 地址的 <code>HTTP</code> 请求的个数，如果在正常范围内，则给予该客户端正常的服务，如果超过上限，此时该客户端被怀疑正在进行爬虫之类的非善意行为，对此我们返回一个错误并拒绝服务该请求。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ConnLimiter <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Mutex</span><br><span class="line">    connections      <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int64</span></span><br><span class="line">    maxConnections   <span class="keyword">int64</span></span><br><span class="line">    totalConnections <span class="keyword">int64</span></span><br><span class="line">    next             http.Handler</span><br><span class="line">    errHandler       ErrorHandler</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(next http.Handler, maxConnections <span class="keyword">int64</span>)</span> <span class="params">(*ConnLimiter, error)</span></span> &#123;</span><br><span class="line">    cl := &amp;ConnLimiter &#123;</span><br><span class="line">        maxConnections: maxConnections,</span><br><span class="line">        connections: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">int64</span>),</span><br><span class="line">        next: next,</span><br><span class="line">    &#125;    </span><br><span class="line">    <span class="keyword">if</span> cl.errHandler == <span class="literal">nil</span> &#123;</span><br><span class="line">        cl.errHandler = defaultErrHandler</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> cl, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为我们是对同一个<code>IP</code> 地址设置连接限制，故对于每个请求，通过读取请求 <code>http.Request</code> 中的 <code>RemoteAddr</code> 来获取 <code>IP</code> 地址。但是上有政策，下游对策，很多写爬虫的人通过代理 <code>IP</code> 池来规避这种审查，这里我们先不讨论如何处理这种情况。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">extractClientIP</span><span class="params">(req *http.Request)</span> <span class="params">(<span class="keyword">string</span>, <span class="keyword">int64</span>, error)</span></span> &#123;</span><br><span class="line">    vals := strings.SplitN(req.RemoteAddr, <span class="string">":"</span>, <span class="number">2</span>)</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(vals[<span class="number">0</span>]) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">""</span>, <span class="number">0</span>, fmt.Errorf(<span class="string">"Failed to parse client IP: %v"</span>, req.RemoteAddr)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> vals[<span class="number">0</span>], <span class="number">1</span>, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>我们还需要定义当同一个 <code>IP</code> 地址的连接数量超过最高连接数量的错误 <code>MaxConnError</code> 以及处理该错误的方法。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> MaxConnError <span class="keyword">struct</span> &#123;</span><br><span class="line">    max <span class="keyword">int64</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(e *MaxConnError)</span> <span class="title">Error</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"max connections reached: %d"</span>, m.max)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> ConnErrHandler <span class="keyword">struct</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(h *ConnErrHandler)</span> <span class="title">ServeHTTP</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    statusCode := http.StatusInternalServerError</span><br><span class="line">    w.WriteHeader(statusCode)</span><br><span class="line">    w.Write([]<span class="keyword">byte</span>(http.StatusText(statusCode)))   </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> defaultErrHandler = &amp;ConnErrHandler&#123;&#125;</span><br></pre></td></tr></table></figure>
-<p><code>acquire</code> 和 <code>release</code> 方法在加锁的条件下对 <code>map</code> 进行操作，这是因为在并发情况下对同一个数据进行读写操作时，会发生数据竞争的情况，所以需要使用 <code>sync.Mutex</code> 来对数据读写进行保护。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cl *ConnLimiter)</span> <span class="title">acquire</span><span class="params">(token <span class="keyword">string</span>, amount <span class="keyword">int64</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    cl.Lock()</span><br><span class="line">    <span class="keyword">defer</span> cl.Unlock()</span><br><span class="line"></span><br><span class="line">    connections := cl.connections[token]</span><br><span class="line">    <span class="keyword">if</span> connections &gt;= cl.maxConnections &#123;</span><br><span class="line">        <span class="keyword">return</span> &amp;MaxConnError&#123;max: cl.maxConnections&#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    cl.connections[token] += amount</span><br><span class="line">    cl.totalConnections += amount</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cl *ConnLimiter)</span> <span class="title">release</span><span class="params">(token <span class="keyword">string</span>, amount <span class="keyword">int64</span>)</span></span> &#123;</span><br><span class="line">    cl.Lock()</span><br><span class="line">    <span class="keyword">defer</span> cl.Unlock()</span><br><span class="line"></span><br><span class="line">    cl.connections[token] -= amount</span><br><span class="line">    cl.totalConnections -= amount</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> cl.connections[token] == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="built_in">delete</span>(cl.connections, token)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在提供服务（ <code>ServeHTTP</code> ）之前，我们通过 <code>acquire</code> 判断该客户端是否有资格获得服务，如果有资格则使用正常的 <code>handler</code> 来处理，否则则使用 <code>errHandler</code> 来处理，最后服务完了需要将相关资源释放（ <code>release</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cl *ConnLimiter)</span> <span class="title">ServeHTTP</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    token, amount, err := extractClientIP(r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Errorf(<span class="string">"failed to extract source of the connection: %v"</span>, err)</span><br><span class="line">        cl.errHandler.ServeHTTP(w, r)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> err = cl.acquire(token, amount); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Debugf(<span class="string">"limiting request source %s: %v"</span>, token, err)</span><br><span class="line">        cl.errHandler.ServeHTTP(w, r)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> cl.release(token, amount)</span><br><span class="line"></span><br><span class="line">    cl.next.ServeHTTP(w, r)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(cl *ConnLimiter)</span> <span class="title">Wrap</span><span class="params">(h http.Handler)</span></span> &#123;</span><br><span class="line">    cl.next = h</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/19/ADB/index.html b/2018/05/19/ADB/index.html
deleted file mode 100644
index b7d509c..0000000
--- a/2018/05/19/ADB/index.html
+++ /dev/null
@@ -1,278 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>ADB | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="安卓手机相对 iPhone 来说生态系统更加开放，可以做各种各样酷酷的事情，例如通过自己电脑上的命令行来刷刷朋友圈之类的，下面我们来看看如何通过 adb 这个神器来控制我们的安卓机吧。 adb ，全称是 Android Debug Bridge ，也就是安卓调试桥，实际上就是一个命令行工具（并没有这么简单），通过它，我们就可以使用一系列命令来控制我们的手机了。 adb 架构为了更好的理解，我们先来">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="ADB">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/19/ADB/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="安卓手机相对 iPhone 来说生态系统更加开放，可以做各种各样酷酷的事情，例如通过自己电脑上的命令行来刷刷朋友圈之类的，下面我们来看看如何通过 adb 这个神器来控制我们的安卓机吧。 adb ，全称是 Android Debug Bridge ，也就是安卓调试桥，实际上就是一个命令行工具（并没有这么简单），通过它，我们就可以使用一系列命令来控制我们的手机了。 adb 架构为了更好的理解，我们先来">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://3.bp.blogspot.com/-IWnB96a3IpI/WmYNlJ_lJ5I/AAAAAAAAADg/6CUlgATGJtYVwrJeTq5lzo1PxAQb2oJtQCLcBGAs/s640/android_buffer_adb_command.png">
-<meta property="og:updated_time" content="2018-06-26T08:43:45.931Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="ADB">
-<meta name="twitter:description" content="安卓手机相对 iPhone 来说生态系统更加开放，可以做各种各样酷酷的事情，例如通过自己电脑上的命令行来刷刷朋友圈之类的，下面我们来看看如何通过 adb 这个神器来控制我们的安卓机吧。 adb ，全称是 Android Debug Bridge ，也就是安卓调试桥，实际上就是一个命令行工具（并没有这么简单），通过它，我们就可以使用一系列命令来控制我们的手机了。 adb 架构为了更好的理解，我们先来">
-<meta name="twitter:image" content="https://3.bp.blogspot.com/-IWnB96a3IpI/WmYNlJ_lJ5I/AAAAAAAAADg/6CUlgATGJtYVwrJeTq5lzo1PxAQb2oJtQCLcBGAs/s640/android_buffer_adb_command.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ADB"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      ADB
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-19T07:38:54.000Z" itemprop="datePublished">
-        May 19, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>安卓手机相对 <code>iPhone</code> 来说生态系统更加开放，可以做各种各样酷酷的事情，例如通过自己电脑上的命令行来刷刷朋友圈之类的，下面我们来看看如何通过 <code>adb</code> 这个神器来控制我们的安卓机吧。</p>
-<p><code>adb</code> ，全称是 <code>Android Debug Bridge</code> ，也就是安卓调试桥，实际上就是一个命令行工具（并没有这么简单），通过它，我们就可以使用一系列命令来控制我们的手机了。</p>
-<h2 id="adb-架构"><a href="#adb-架构" class="headerlink" title="adb 架构"></a>adb 架构</h2><p>为了更好的理解，我们先来看一下 <code>adb</code> 的基本架构，在整个架构中存在三个重要的组件，<code>client</code> ，<code>ADB Server</code> 和 <code>ADB Daemon</code> 。各个组件之间通过 <code>TCP/IP</code> 或者 <code>USB</code> 进行通信来交流信息。</p>
-<p><img src="https://3.bp.blogspot.com/-IWnB96a3IpI/WmYNlJ_lJ5I/AAAAAAAAADg/6CUlgATGJtYVwrJeTq5lzo1PxAQb2oJtQCLcBGAs/s640/android_buffer_adb_command.png" alt="ADB"></p>
-<ul>
-<li><p>client<br>客户端，用于向 <code>ADB Server</code> 发送命令的工具，可以是命令行工具（ <code>Terminal</code> ）或者是 <code>Android Studio</code> ，存在于我们自己电脑上。</p>
-</li>
-<li><p>ADB Server<br>电脑上的客户端和手机中守护进程之间的中介，类似一座桥（这就是为什么<code>adb</code> 叫做桥的原因了），主要负责两者之间的通信，在本地计算机上作为后台进程运行。我们可以通过 <code>grep</code>  <code>ps</code> 命令的输出，来发现守护进程 <code>adb</code> 正在监听的 <code>TCP</code> 端口。 </p>
-</li>
-</ul>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ ps -e | grep adb</span><br><span class="line">adb -L tcp:5037 fork-server server --reply-fd 4</span><br></pre></td></tr></table></figure>
-<ul>
-<li>ADB Daemon<br>存在于手机之上的守护进程，负责接受并处理来自 <code>ADB Server</code> 的消息。类似的，我们可以通过 <code>adb shell ps | grep adbd</code> 来寻找手机上的<code>adbd</code> 进程及相应的 <code>pid</code> 。</li>
-</ul>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ adb shell ps | grep adbd</span><br><span class="line">shell        13336     1   14532    812 0     0 S adbd</span><br></pre></td></tr></table></figure>
-<p>也就是说 <code>client</code> 和 <code>adb server</code> 存在于宿主机之上，采用传统的 <code>C/S</code> 模型，而 <code>adb server</code> 通过 <code>TCP</code> 或 <code>USB</code> 来向手机上的 <code>adb daemon</code> 发送消息。</p>
-<h2 id="adb-通信"><a href="#adb-通信" class="headerlink" title="adb 通信"></a>adb 通信</h2><p>通信肯定会涉及到协议，只有通信的双方都遵守协议才能顺利运行，下面是 <code>abd</code> 协议报文的基本结构，与 <code>HTTP</code> 协议类似，<code>abd</code> 协议同样也处于应用层。传输层既可以采用 <code>USB</code> 来传送，也可以使用我们熟悉的 <code>TCP/IP</code> 。 </p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">unsigned command; /* command identifier constant /</span><br><span class="line">unsigned arg1; / first argument /</span><br><span class="line">unsigned arg2; / second argument /</span><br><span class="line">unsigned data_length; / length of payload (0 is allowed) /</span><br><span class="line">unsigned data_crc32; / crc32 of data payload /</span><br><span class="line">unsigned magic; / command ^ 0xffffffff */</span><br></pre></td></tr></table></figure>
-<p>也就是说 <code>adb server</code> 和 <code>adb daemon</code> 之间可以通过两种传输协议来发送 <code>adb</code> 协议报文。</p>
-<h3 id="USB"><a href="#USB" class="headerlink" title="USB"></a>USB</h3><p>采用 <code>USB</code> 进行传输时，我们需要先将手机通过数据线连接到电脑上，注意手机需要进入开发者模式，并且通过相应的权限设置，如果连接成功的话，在命令行中输入 <code>adb devices</code> 就可以看到连接的设备了。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">List of devices attached</span><br><span class="line">988a1b30374e494a52	device</span><br></pre></td></tr></table></figure>
-<h3 id="TCP-IP"><a href="#TCP-IP" class="headerlink" title="TCP/IP"></a>TCP/IP</h3><p>当然除了 <code>USB</code> 这种传统方式的话，我们还可以利用酷酷的 <code>TCP/IP</code> 进行通信，首先也是通过 <code>USB</code> 连接手机和电脑，并确保两者连接到同一个局域网，在命令行中输入 <code>adb tcpip 5555</code> 使得 <code>adb daemon</code> 监听 <code>5555</code> 端口，然后通过 <code>adb connect &lt;IP_OF_YOUR_ANDROID_PHONE&gt;</code> 命令来连接我们的手机，这里 <code>&lt;IP_OF_YOUR_ANDROID_PHONE&gt;</code> 代表手机的 <code>IP</code> 地址。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ adb tcpip 5555</span><br><span class="line">$ adb connect &lt;IP_OF_YOUR_ANDROID_PHONE&gt;</span><br></pre></td></tr></table></figure>
-<p>如果连接成功，再使用 <code>adb devices</code> 命令会获得以下输出，这里的输出和上面有写不同，这里会输出 <code>192.168.1.101:5555</code> ，这样就说明我们已经成功连接，可以拔掉我们的数据线进行通信了。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">List of devices attached</span><br><span class="line">192.168.1.101:5555	device</span><br></pre></td></tr></table></figure>
-<h2 id="adb-常用命令"><a href="#adb-常用命令" class="headerlink" title="adb 常用命令"></a>adb 常用命令</h2><p>正确连接上了我们的手机之后，我们就可以干各种很酷的事情了。</p>
-<h3 id="获取版本信息"><a href="#获取版本信息" class="headerlink" title="获取版本信息"></a>获取版本信息</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ adb shell getprop ro.build.version.release</span><br></pre></td></tr></table></figure>
-<h3 id="拷贝文件"><a href="#拷贝文件" class="headerlink" title="拷贝文件"></a>拷贝文件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ adb push [source] [destination]</span><br><span class="line">$ adb pull [device file location] [location file location]</span><br></pre></td></tr></table></figure>
-<h3 id="screenshot-和-screenrecord"><a href="#screenshot-和-screenrecord" class="headerlink" title="screenshot 和 screenrecord"></a>screenshot 和 screenrecord</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ adb shell screencap -p /sdcard/screenshot.png</span><br></pre></td></tr></table></figure>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ adb shell screenrecord /sdcard/notabletologin.mp4</span><br></pre></td></tr></table></figure>
-<h3 id="手势模拟"><a href="#手势模拟" class="headerlink" title="手势模拟"></a>手势模拟</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ adb shell swipe x1 y1 x2 y2</span><br></pre></td></tr></table></figure>
-<h3 id="模拟基本操作"><a href="#模拟基本操作" class="headerlink" title="模拟基本操作"></a>模拟基本操作</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">// Home btn</span><br><span class="line">$ adb shell input keyevent 3 </span><br><span class="line">// Back btn</span><br><span class="line">$ adb shell input keyevent 4 </span><br><span class="line">// Call</span><br><span class="line">$ adb shell input keyevent 5 </span><br><span class="line">// End call</span><br><span class="line">$ adb shell input keyevent 6 </span><br><span class="line">// Turn Android device ON and OFF. It will toggle device to on/off status.</span><br><span class="line">$ adb shell input keyevent 26  </span><br><span class="line">// Camera</span><br><span class="line">$ adb shell input keyevent 27 </span><br><span class="line">// Open browser</span><br><span class="line">$ adb shell input keyevent 64 </span><br><span class="line">// Enter</span><br><span class="line">$ adb shell input keyevent 66 </span><br><span class="line">// Delete (backspace)</span><br><span class="line">$ adb shell input keyevent 67 </span><br><span class="line">// Contacts</span><br><span class="line">$ adb shell input keyevent 207 </span><br><span class="line">// Brightness down/up</span><br><span class="line">$ adb shell input keyevent 220 / 221 </span><br><span class="line">// Cut/Copy/Paste</span><br><span class="line">$ adb shell input keyevent 277 / 278 /279 </span><br><span class="line">// https://developer.android.com/reference/android/view/KeyEvent.html</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/20/Future/index.html b/2018/05/20/Future/index.html
deleted file mode 100644
index db2efa5..0000000
--- a/2018/05/20/Future/index.html
+++ /dev/null
@@ -1,257 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Future | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Future 是 java 中比较常见的并发编程解决方案，它采用异步的方式，尽可能减少运行时代码阻塞，很大程度上提高了程序的运行效率，在golang 中我们可以利用 goroutine ， chan 机制和 for select 轻松实现类似的功能。 其实 Future 的本质就是异步计算的结果，我们用 item interface{} 来放置 Future 的结果，通过读取 triggered">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Future">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/20/Future/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Future 是 java 中比较常见的并发编程解决方案，它采用异步的方式，尽可能减少运行时代码阻塞，很大程度上提高了程序的运行效率，在golang 中我们可以利用 goroutine ， chan 机制和 for select 轻松实现类似的功能。 其实 Future 的本质就是异步计算的结果，我们用 item interface{} 来放置 Future 的结果，通过读取 triggered">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:44.589Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Future">
-<meta name="twitter:description" content="Future 是 java 中比较常见的并发编程解决方案，它采用异步的方式，尽可能减少运行时代码阻塞，很大程度上提高了程序的运行效率，在golang 中我们可以利用 goroutine ， chan 机制和 for select 轻松实现类似的功能。 其实 Future 的本质就是异步计算的结果，我们用 item interface{} 来放置 Future 的结果，通过读取 triggered">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Future"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Future
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-20T06:04:59.000Z" itemprop="datePublished">
-        May 20, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><code>Future</code> 是 <code>java</code> 中比较常见的并发编程解决方案，它采用异步的方式，尽可能减少运行时代码阻塞，很大程度上提高了程序的运行效率，在<code>golang</code> 中我们可以利用 <code>goroutine</code> ， <code>chan</code> 机制和 <code>for select</code> 轻松实现类似的功能。</p>
-<p>其实 <code>Future</code> 的本质就是异步计算的结果，我们用 <code>item interface{}</code> 来放置 <code>Future</code> 的结果，通过读取 <code>triggered</code> 的值来判断异步计算是否已经返回。</p>
-<p><code>New</code> 方法用于构造 <code>Future</code> 任务，它通过监听 <code>Completer</code> 通道来获取异步执行的结果，如果监听超时，则停止监听，返回错误。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Future <span class="keyword">struct</span> &#123;</span><br><span class="line">    triggered <span class="keyword">bool</span></span><br><span class="line">    item      <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">    err       error</span><br><span class="line">    lock      sync.Mutex</span><br><span class="line">    wg        sync.WaitGroup</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Completer &lt;-<span class="keyword">chan</span> <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(completer Completer, timeout time.Duration)</span> *<span class="title">Future</span></span> &#123;</span><br><span class="line">    f := &amp;Future&#123;&#125;</span><br><span class="line">    f.wg.Add(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> listen(f, completer, timeout)</span><br><span class="line">    <span class="keyword">return</span> f</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>listen</code> 是获得异步计算结果的核心，如果 <code>Completer</code> 通道返回，则通过 <code>set</code> 方法设置计算结果，并标记 <code>triggered</code> 为 <code>true</code> ，如果监听超时，则同样标记 <code>triggered</code> 为 <code>true</code> ，但此时应该返回一个错误而非正确的计算结果。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">listen</span><span class="params">(f *Future, ch Completer, timeout time.Duration)</span></span> &#123;</span><br><span class="line">    t := time.NewTicker(timeout)</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> item := &lt;-ch:</span><br><span class="line">        f.set(item, <span class="literal">nil</span>)</span><br><span class="line">        t.Stop()</span><br><span class="line">    <span class="keyword">case</span> &lt;-t.C:</span><br><span class="line">        f.set(<span class="literal">nil</span>, fmt.Errorf(<span class="string">`timeout after %f seconds`</span>, timeout.Seconds()))</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为 <code>Future</code> 返回结果的时机并不确定， 所以我们需要一种方式得知结果是否已经返回，<code>IsDone</code> 方法通过查询 <code>triggered</code> 是否为 <code>true</code> 来得知结果是否已经返回 ，也就是查询事件是否已经触发，这里结果返回和发生超时都可以触发事件。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *Future)</span> <span class="title">IsDone</span><span class="params">()</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    f.lock.Lock()</span><br><span class="line">    done := f.triggered</span><br><span class="line">    f.lock.Unlock()</span><br><span class="line">    <span class="keyword">return</span> done</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>所以无论是结果返回，还是超时发生，我们都要通过 <code>set</code> 方法对 <code>Future</code> 进行设置，来标记 <code>Future</code> 事件完成。设置完通过 <code>f.wg.Done()</code> 来通知所有等待此结果的监听者。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *Future)</span> <span class="title">set</span><span class="params">(item <span class="keyword">interface</span>&#123;&#125;, err error)</span></span> &#123;</span><br><span class="line">    f.lock.Lock()</span><br><span class="line">    f.triggered = <span class="literal">true</span></span><br><span class="line">    f.item = item</span><br><span class="line">    f.err = err</span><br><span class="line">    f.lock.Unlock()</span><br><span class="line">    f.wg.Done()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p> <code>Get</code> 方法用于获得 <code>Future</code> 执行的结果，如果此时 <code>Future</code> 已经触发，那么可以直接返回结果，但是如果此时 <code>triggered</code> 为 <code>false</code> ，也就是说那两件事件中一件都没有发生，此时我们只能傻傻地等待（ <code>f.wg.Wait()</code> ） ，直到别人广播（ <code>f.wg.Done()</code> ）来告知事件已经发生。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(f *Future)</span> <span class="title">Get</span><span class="params">()</span> <span class="params">(<span class="keyword">interface</span>&#123;&#125;, error)</span></span> &#123;</span><br><span class="line">    f.lock.Lock()</span><br><span class="line">    <span class="keyword">if</span> f.triggered &#123;</span><br><span class="line">        f.lock.Unlock()</span><br><span class="line">        <span class="keyword">return</span> f.item, f.err</span><br><span class="line">    &#125;</span><br><span class="line">    f.lock.Unlock()</span><br><span class="line">    </span><br><span class="line">    f.wg.Wait()</span><br><span class="line">    <span class="keyword">return</span> f.item, f.err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>下面是应用 <code>Future</code> 的简单例子。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">completer := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">interface</span>&#123;&#125;)</span><br><span class="line">f := New(completer, time.Duration(<span class="number">30</span>*time.Minute))</span><br><span class="line"><span class="keyword">var</span> result <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line"><span class="keyword">var</span> err error</span><br><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line">wg.Add(<span class="number">1</span>)</span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">    result, err = f.Get()</span><br><span class="line">    wg.Done()</span><br><span class="line">&#125;()</span><br><span class="line"></span><br><span class="line">completer &lt;- <span class="string">`test`</span></span><br><span class="line">wg.Wait()</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/21/mpg123/index.html b/2018/05/21/mpg123/index.html
deleted file mode 100644
index 009153f..0000000
--- a/2018/05/21/mpg123/index.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>mpg123 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="日常生活中，我们都是使用网易云音乐之类的音乐软件听歌，但是你有没有想过，作为程序员，该如何使用命令行来听（zhuang）歌（bi）呢？今天就让我们来实现这个功能吧。 写代码，一般需要搞清楚三点，输入，输出和算法。如果使用命令行听歌，输入很明确，肯定是音频数据流，数据一般可以通过网上获取，那么输出呢，肯定就是我们耳朵中听到的声音，这两点都比较简单。关键是处理数据和输出数据的算法，之前并没有怎么搞过">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="mpg123">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/21/mpg123/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="日常生活中，我们都是使用网易云音乐之类的音乐软件听歌，但是你有没有想过，作为程序员，该如何使用命令行来听（zhuang）歌（bi）呢？今天就让我们来实现这个功能吧。 写代码，一般需要搞清楚三点，输入，输出和算法。如果使用命令行听歌，输入很明确，肯定是音频数据流，数据一般可以通过网上获取，那么输出呢，肯定就是我们耳朵中听到的声音，这两点都比较简单。关键是处理数据和输出数据的算法，之前并没有怎么搞过">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:08.848Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="mpg123">
-<meta name="twitter:description" content="日常生活中，我们都是使用网易云音乐之类的音乐软件听歌，但是你有没有想过，作为程序员，该如何使用命令行来听（zhuang）歌（bi）呢？今天就让我们来实现这个功能吧。 写代码，一般需要搞清楚三点，输入，输出和算法。如果使用命令行听歌，输入很明确，肯定是音频数据流，数据一般可以通过网上获取，那么输出呢，肯定就是我们耳朵中听到的声音，这两点都比较简单。关键是处理数据和输出数据的算法，之前并没有怎么搞过">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-mpg123"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      mpg123
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-21T11:12:06.000Z" itemprop="datePublished">
-        May 21, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>日常生活中，我们都是使用网易云音乐之类的音乐软件听歌，但是你有没有想过，作为程序员，该如何使用命令行来听（zhuang）歌（bi）呢？今天就让我们来实现这个功能吧。</p>
-<p>写代码，一般需要搞清楚三点，输入，输出和算法。如果使用命令行听歌，输入很明确，肯定是音频数据流，数据一般可以通过网上获取，那么输出呢，肯定就是我们耳朵中听到的声音，这两点都比较简单。关键是处理数据和输出数据的算法，之前并没有怎么搞过音乐格式编码和解码之类的东西，不过不要慌，已经有强大的 <code>mpg123</code> 这个命令行工具帮我们搞定这类事情了。</p>
-<p><code>mpg123</code> 需要额外安装，<code>macOS</code> 用户可以使用 <code>homebrew</code> 进行安装。<code>mpg123</code> 可以帮助我们处理 <code>MPEG 1.0/2.0/2.5</code> 格式的数据流，并使用系统默认的音屏设备播放。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ mpg123 [ options ] file-or-URL...</span><br></pre></td></tr></table></figure>
-<p>上面是它的简单使用，<code>[options]</code> 代表额外选项，真正的参数可以是本地音频文件地址或者 <code>URL</code> 地址。一般来说 <code>file/URL</code> 都需要是 <code>MPEG</code> 格式的音频比特流（ <code>audio bit stream</code> ）。</p>
-<p>问题的关键解决之后，下面就可以利用它写一个简单的音乐播放器了，这里播放器具有两种状态，<code>Stopped</code> 和 <code>Playing</code> ，播放器的核心操作依赖 <code>mpg123</code> 实现，<code>exec.Cmd</code> 用于代表这个命令。除此之外，还需要指定输入和输出，输入（ <code>io.ReadCloser</code> ）可以来自 <code>HTTP</code> 得到的数据流，而输出（ <code>io.WriteCloser</code> ）则是该命令的输入管道。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> State <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    Stopped State = <span class="literal">iota</span></span><br><span class="line">    Playing</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Player <span class="keyword">struct</span> &#123;</span><br><span class="line">    state      State</span><br><span class="line">    currentURL <span class="keyword">string</span></span><br><span class="line">    mpg123     *exec.Cmd</span><br><span class="line">    src        io.ReadCloser</span><br><span class="line">    dst        io.WriteCloser</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为播放音乐需要 <code>mpg123</code> 这个依赖，所以，在程序运行时需要检查其是否存在，<code>exec.LookPath</code> 会在系统路径（ <code>$PATH</code> ）下面寻找，如果不存在，则返回 <code>error</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewPlayer</span><span class="params">()</span> <span class="params">(*Player, error)</span></span> &#123;</span><br><span class="line">    _, err := exec.LookPath(<span class="string">"mpg123"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    p := &amp;Player&#123;&#125;</span><br><span class="line">    <span class="keyword">return</span> p, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>使用命令行听歌的关键还是在于对数据流的处理，通过 <code>io.Copy</code> 方法将数据流进行重定向。 </p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">stream</span><span class="params">(dst io.WriteCloser, src io.ReadCloser)</span></span> &#123;</span><br><span class="line">    <span class="keyword">defer</span> dst.Close()</span><br><span class="line">    <span class="keyword">defer</span> src.Close()</span><br><span class="line">    io.Copy(dst, src)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为 <code>mpg123</code> 需要读取音频数据流，在构造命令时，我们使用 <code>-</code> 来指定<code>mpg123</code> 从标准输入中获取数据（ <code>exec.Command(&quot;mpg123&quot;, &quot;-q&quot;, &quot;-&quot;)</code> ），通过 <code>StdinPipe()</code> 方法可以获得连接到此命令的标准输入管道。输入的数据流可以利用 <code>http.Get</code> 获取，然后再利用上述 <code>stream</code> 方法将数据流重定向到 <code>mpg123</code> 的标准输入（ <code>stdin</code> ）中去，这样就可以实现音乐播放了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Player)</span> <span class="title">Play</span><span class="params">(URL <span class="keyword">string</span>)</span> <span class="params">(err error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> p.state == Playing &#123;</span><br><span class="line">        p.Stop()</span><br><span class="line">        <span class="keyword">return</span> p.Play(URL)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    mpg123 := exec.Command(<span class="string">"mpg123"</span>, <span class="string">"-q"</span>, <span class="string">"-"</span>)</span><br><span class="line">    stdin, err := mpg123.StdinPipe()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        stdin.Close()</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;   </span><br><span class="line"></span><br><span class="line">    err = mpg123.Start()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        stdin.Close()</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    response, err := http.Get(URL)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    p.state = Playing</span><br><span class="line">    p.currentURL = URL</span><br><span class="line">    p.mpg123 = mpg123</span><br><span class="line">    p.src = response.Body</span><br><span class="line">    p.dst = stdin</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">go</span> stream(p.dst, p.src)</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>一个音乐播放器自然少不了暂停操作。因为输入和输出分别是 <code>io.ReadCloser</code> 和 <code>io.WriteCloser</code> 类型，所以都可以调用 <code>Close</code> 方法来将它们关闭。除此之外还需要将对应的 <code>mpg123</code> 的进程停掉（ <code>p.mpg123.Process.Kill()</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Player)</span> <span class="title">Stop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> p.state == Stopped &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    p.state = Stopped</span><br><span class="line">    p.src.Close()</span><br><span class="line">    p.src = <span class="literal">nil</span></span><br><span class="line"></span><br><span class="line">    p.dst.Close()</span><br><span class="line">    p.mpg123.Process.Kill()</span><br><span class="line">    p.mpg123.Wait()</span><br><span class="line">    p.mpg123.Handler = <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>剩下最后一个问题就是如何获取各大平台音乐的链接地址，下面给获取网易云音乐歌曲外链地址的方法，这里的参数 <code>id</code> 表示音乐的 <code>id</code> ，其他平台获取方法也应该类似，感兴趣的读者可以自行寻找。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getMusicLink</span><span class="params">(id <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    s := <span class="string">"http://music.163.com/song/media/outer/url?id=%d.mp3"</span></span><br><span class="line">    addr = fmt.Sprintf(s, id)</span><br><span class="line">    <span class="keyword">return</span> addr</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/22/BitwiseOperation/index.html b/2018/05/22/BitwiseOperation/index.html
deleted file mode 100644
index d033557..0000000
--- a/2018/05/22/BitwiseOperation/index.html
+++ /dev/null
@@ -1,286 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Bitwise Operation | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在计算机刚出现时的远古年代（其实也就几十年）， CPU ，内存和网络带宽都是非常珍贵的资源，在处理或者发送数据时，为了尽可能地节约资源，程序员都需要尽可能控制数据的大小，例如布尔值能用一个比特表示就绝不使用一个字节。 一般网络协议的头部通过指定特定比特来表示特定的意思，还有在很多 low-level 的系统编程中，位运算也非常常见。所以，位运算可以说是程序员的必备技能了，下面让我们来看几种基本的位">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Bitwise Operation">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/22/BitwiseOperation/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在计算机刚出现时的远古年代（其实也就几十年）， CPU ，内存和网络带宽都是非常珍贵的资源，在处理或者发送数据时，为了尽可能地节约资源，程序员都需要尽可能控制数据的大小，例如布尔值能用一个比特表示就绝不使用一个字节。 一般网络协议的头部通过指定特定比特来表示特定的意思，还有在很多 low-level 的系统编程中，位运算也非常常见。所以，位运算可以说是程序员的必备技能了，下面让我们来看几种基本的位">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:43:55.749Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Bitwise Operation">
-<meta name="twitter:description" content="在计算机刚出现时的远古年代（其实也就几十年）， CPU ，内存和网络带宽都是非常珍贵的资源，在处理或者发送数据时，为了尽可能地节约资源，程序员都需要尽可能控制数据的大小，例如布尔值能用一个比特表示就绝不使用一个字节。 一般网络协议的头部通过指定特定比特来表示特定的意思，还有在很多 low-level 的系统编程中，位运算也非常常见。所以，位运算可以说是程序员的必备技能了，下面让我们来看几种基本的位">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-BitwiseOperation"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Bitwise Operation
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-22T11:28:38.000Z" itemprop="datePublished">
-        May 22, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在计算机刚出现时的远古年代（其实也就几十年）， CPU ，内存和网络带宽都是非常珍贵的资源，在处理或者发送数据时，为了尽可能地节约资源，程序员都需要尽可能控制数据的大小，例如布尔值能用一个比特表示就绝不使用一个字节。</p>
-<p>一般网络协议的头部通过指定特定比特来表示特定的意思，还有在很多 <code>low-level</code> 的系统编程中，位运算也非常常见。所以，位运算可以说是程序员的必备技能了，下面让我们来看几种基本的位运算吧。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> op <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> BitwiseOperation <span class="keyword">interface</span> &#123;</span><br><span class="line">    AND(<span class="keyword">byte</span>, <span class="keyword">byte</span>) <span class="keyword">byte</span></span><br><span class="line">    ANDNOT(<span class="keyword">byte</span>, <span class="keyword">byte</span>) <span class="keyword">byte</span></span><br><span class="line">    OR(<span class="keyword">byte</span>, <span class="keyword">byte</span>) <span class="keyword">byte</span></span><br><span class="line">    XOR(<span class="keyword">byte</span>. <span class="keyword">byte</span>) <span class="keyword">byte</span> </span><br><span class="line">    NOT(<span class="keyword">byte</span>) <span class="keyword">byte</span>  </span><br><span class="line">    SHIFT_LEFT(<span class="keyword">byte</span>, <span class="keyword">uint</span>) <span class="keyword">byte</span></span><br><span class="line">    SHIFT_RIGHT(<span class="keyword">byte</span>, <span class="keyword">uint</span>) <span class="keyword">byte</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="amp-AND"><a href="#amp-AND" class="headerlink" title="&amp; (AND)"></a>&amp; (AND)</h2><p><code>AND</code> 运算符可以有选择性地将数的某位清零，除此之外，还可以检测数的奇偶性（1 &amp; a == 1）。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  0xAC // 10101100</span><br><span class="line">&amp; 0xF0 // 11110000</span><br><span class="line">= 0xA0 // 10100000</span><br><span class="line">          ^ ^</span><br></pre></td></tr></table></figure>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">func (op *bitwiseOp) AND(x byte, y byte) byte &#123;</span><br><span class="line">    return x &amp; y</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="amp-AND-NOT"><a href="#amp-AND-NOT" class="headerlink" title="&amp;^ (AND NOT)"></a>&amp;^ (AND NOT)</h2><p>与 <code>AND</code> 类似，<code>AND NOT</code> 也可以将特定的位清0，但是 <code>AND NOT</code> 的语义更加符合正常思维，写起来也更加直观。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">   0xAB // 10101011</span><br><span class="line">&amp;^ 0x03 // 00000011</span><br><span class="line">=  0xA8 // 10101000</span><br><span class="line">           ^ ^ ^</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(op *op)</span> <span class="title">ANDNOT</span><span class="params">(x <span class="keyword">byte</span>, y <span class="keyword">byte</span>)</span> <span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> x &amp;^ y</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="OR"><a href="#OR" class="headerlink" title="| (OR)"></a>| (OR)</h2><p><code>OR</code> 操作可以有选择性地将一个字节的某几个比特设为1。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  0x00 // 00000000</span><br><span class="line">| 0xC4 // 11000100</span><br><span class="line">= 0xC4 // 11000100</span><br><span class="line">          ^^   ^</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(op *op)</span> <span class="title">OR</span><span class="params">(x <span class="keyword">byte</span>, y <span class="keyword">byte</span>)</span> <span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> x | y</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="（XOR-NOT）"><a href="#（XOR-NOT）" class="headerlink" title="^ （XOR | NOT）"></a>^ （XOR | NOT）</h2><h3 id="Binary-XOR"><a href="#Binary-XOR" class="headerlink" title="Binary ^ (XOR)"></a>Binary ^ (XOR)</h3><p>使用 <code>XOR</code> 可以将位从一个值切换到另一个（toggle），除此之外，<code>XOR</code> 还可以用于比较两个数的符号是否相同。当 <code>(a ^ b) ≥ 0</code> 时，表示两个整数a，b具有相同的符号（或当 <code>(a ^ b) &lt; 0</code> 时表示符号相反）。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">  0xCEFF // 1100111011111111</span><br><span class="line">^ 0xFF00 // 1111111100000000</span><br><span class="line">= 0x31FF // 0011000111111111</span><br><span class="line">              ^^   ^^^^^^^^^</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(op *op)</span> <span class="title">XOR</span><span class="params">(x <span class="keyword">byte</span>, y <span class="keyword">byte</span>)</span> <span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> x ^ y</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="Unary-NOT"><a href="#Unary-NOT" class="headerlink" title="Unary ^ (NOT)"></a>Unary ^ (NOT)</h3><p>与其他语言（c / c ++，Java，Python，Javascript等）不同，Go没有专门的取反位运算符，但它可以用 <code>^</code> 来表示 <code>NOT</code>， 也就是按位取反。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">^ 0x0F // 00001111</span><br><span class="line">= 0xF0 // 11110000</span><br><span class="line">          ^^^^</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(op *op)</span> <span class="title">NOT</span><span class="params">(x <span class="keyword">byte</span>)</span> <span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> ^x</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="SHIFT"><a href="#SHIFT" class="headerlink" title="SHIFT"></a>SHIFT</h2><p><code>Shift</code> 操作可以和 <code>&amp;</code>  <code>|</code>  <code>&amp;^</code> 这三个操作符组合起来使用。</p>
-<ul>
-<li><code>a | ( 1&lt;&lt; 2)</code></li>
-</ul>
-<p><code>|</code> 与 <code>&lt;&lt;</code> 运算符组合可以用于设置a中的第n位。</p>
-<ul>
-<li><code>a &amp; (1 &lt;&lt; 2)</code></li>
-</ul>
-<p>或者将 <code>＆</code> 和 <code>&lt;&lt;</code> 运算符组合来测试第n位是否被设置。</p>
-<ul>
-<li><code>a &amp;^ (1 &lt;&lt; 2)</code></li>
-</ul>
-<p>使用 <code>＆^</code> 和 <code>&lt;&lt;</code>，我们可以取消设置值的第n位。</p>
-<p>使用左右移位运算符还可以完成效率更高的乘法和除法。</p>
-<h3 id="gt-gt-Shift-Right"><a href="#gt-gt-Shift-Right" class="headerlink" title="&gt;&gt; (Shift Right)"></a>&gt;&gt; (Shift Right)</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">     0x78 // 01111000</span><br><span class="line">              ^^^^</span><br><span class="line">&gt;&gt; 1 0x3C // 00111100  </span><br><span class="line">               ^^^^</span><br><span class="line">&gt;&gt; 2 0x1E // 00011110</span><br><span class="line">                ^^^^</span><br><span class="line">&gt;&gt; 3 0x0F // 00001111</span><br><span class="line">                 ^^^^</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(op *op)</span> <span class="title">SHIFT_RIGHT</span><span class="params">(x <span class="keyword">byte</span>, n <span class="keyword">uint</span>)</span> <span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> x &gt;&gt; n</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="lt-lt-Shift-Left"><a href="#lt-lt-Shift-Left" class="headerlink" title="&lt;&lt; (Shift Left)"></a>&lt;&lt; (Shift Left)</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">     0x03 // 00000011</span><br><span class="line">                   ^^</span><br><span class="line">&lt;&lt; 1 0x60 // 00000110</span><br><span class="line">                  ^^</span><br><span class="line">&lt;&lt; 2 0xC0 // 00001100</span><br><span class="line">                 ^^</span><br><span class="line">&lt;&lt; 3 0x18 // 00011000</span><br><span class="line">                ^^</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(op *op)</span> <span class="title">SHIFT_LEFT</span><span class="params">(x <span class="keyword">byte</span>, n <span class="keyword">uint</span>)</span> <span class="title">byte</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> x &lt;&lt; n</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="bitset"><a href="#bitset" class="headerlink" title="bitset"></a>bitset</h2><p>了解了基本的位操作后，我们可以用它来实现  <code>bitset</code> ，使用 <code>bitset</code> 存储布尔值相对 <code>map[uint]bool</code> 来说更加高效。 <code>bitset</code> 可以在很多场景下使用，比方说你是一个旅店老板，就可以使用 <code>bitset</code> 来存储每个房间的状态，如果房间被占用了，则将相应的比特位设置为1，如果房间为空，则相应的比特位设置为0。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">uint64</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">|................x................................x..............|</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">uint64</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">|...................................x............................|</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">uint64</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">|...............x................................................|</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">uint64</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">|...................x..........x..........x......................|</span><br><span class="line">+----------------------------------------------------------------+</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> bitset []<span class="keyword">uint64</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">newBitset</span><span class="params">(bits <span class="keyword">uint</span>)</span> <span class="title">bitset</span></span> &#123;</span><br><span class="line">    extra := <span class="keyword">uint</span>(<span class="number">0</span>)</span><br><span class="line">    <span class="keyword">if</span> bits % <span class="number">64</span> != <span class="number">0</span> &#123;</span><br><span class="line">        extra = <span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line">    chunks := bits/<span class="number">64</span> + extra</span><br><span class="line">    <span class="keyword">return</span> bitset(<span class="built_in">make</span>([]<span class="keyword">uint64</span>, chunks))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">bitsetIndex</span><span class="params">(pos <span class="keyword">uint</span>)</span> <span class="params">(<span class="keyword">uint</span>, <span class="keyword">uint</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> pos / <span class="number">64</span>, pos % <span class="number">64</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">set</span><span class="params">(pos <span class="keyword">uint</span>)</span> <span class="title">bitset</span></span> &#123;</span><br><span class="line">    major, minor := bitsetIndex(pos)</span><br><span class="line">    b[major] |= (<span class="number">1</span> &lt;&lt; minor)</span><br><span class="line">    <span class="keyword">return</span> b</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">clear</span><span class="params">(pos <span class="keyword">uint</span>)</span> <span class="title">bitset</span></span> &#123;</span><br><span class="line">    major, minor := bitsetIndex(pos)</span><br><span class="line">    b[major] &amp;^= (<span class="number">1</span> &lt;&lt; minor)</span><br><span class="line">    <span class="keyword">return</span> b</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">get</span><span class="params">(pos <span class="keyword">uint</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    major, minor := bitsetIndex(pos)</span><br><span class="line">    <span class="keyword">return</span> b[major] &amp; (<span class="number">1</span> &lt;&lt; minor) != <span class="number">0</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">popcnt</span><span class="params">()</span> <span class="title">uint</span></span> &#123;</span><br><span class="line">    total := <span class="keyword">uint</span>(<span class="number">0</span>)</span><br><span class="line">    <span class="keyword">for</span> _, v := <span class="keyword">range</span> b &#123;</span><br><span class="line">        v = (v&amp;<span class="number">0x5555555555555555</span>) + ((v&amp;<span class="number">0xAAAAAAAAAAAAAAAA</span>) &gt;&gt; <span class="number">1</span>)</span><br><span class="line">        v = (v&amp;<span class="number">0x3333333333333333</span>) + ((v&amp;<span class="number">0xCCCCCCCCCCCCCCCC</span>) &gt;&gt; <span class="number">2</span>)</span><br><span class="line">        v = (v&amp;<span class="number">0x0F0F0F0F0F0F0F0F</span>) + ((v&amp;<span class="number">0xF0F0F0F0F0F0F0F0</span>) &gt;&gt; <span class="number">4</span>)</span><br><span class="line">        v *= <span class="number">0x0101010101010101</span></span><br><span class="line">        total += <span class="keyword">uint</span>((v &gt;&gt; <span class="number">56</span>) &amp; <span class="number">0xFF</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> total</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">clone</span><span class="params">()</span> <span class="title">bitset</span></span> &#123;</span><br><span class="line">    dataCopy := <span class="built_in">make</span>([]<span class="keyword">uint64</span>, <span class="built_in">len</span>(b))</span><br><span class="line">    <span class="built_in">copy</span>(dataCopy, b)</span><br><span class="line">    <span class="keyword">return</span> bitset(dataCopy)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">hash</span><span class="params">()</span> <span class="title">uint64</span></span> &#123;</span><br><span class="line">    hash := <span class="keyword">uint64</span>(b.popcnt())</span><br><span class="line">    <span class="keyword">for</span> _, v := <span class="keyword">range</span> b &#123;</span><br><span class="line">        hash ^= v</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> hash</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(b bitset)</span> <span class="title">equals</span><span class="params">(b2 bitset)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(b) != <span class="built_in">len</span>(b2) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> b &#123;</span><br><span class="line">        <span class="keyword">if</span> b[i] != b2[i] &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/22/GUID/index.html b/2018/05/22/GUID/index.html
deleted file mode 100644
index 063cce3..0000000
--- a/2018/05/22/GUID/index.html
+++ /dev/null
@@ -1,254 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>GUID | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在点外卖或者网上购物的时候，每个订单中都会有一串独一无二的数字，但是处理订单的服务器肯定不止一台，如何保证多台服务器，也就是说一个计算机集群中，在相互独立的情况下（不沟通自己生成的订单号的信息）不生成相同的订单号码呢，下面我们就来介绍一种全球唯一标识符（ GUID ）的生成算法。 这里我们的 GUID 共64比特。sequence 部分占12比特，nodeID 占10比特，偏移10比特，时间戳">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="GUID">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/22/GUID/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在点外卖或者网上购物的时候，每个订单中都会有一串独一无二的数字，但是处理订单的服务器肯定不止一台，如何保证多台服务器，也就是说一个计算机集群中，在相互独立的情况下（不沟通自己生成的订单号的信息）不生成相同的订单号码呢，下面我们就来介绍一种全球唯一标识符（ GUID ）的生成算法。 这里我们的 GUID 共64比特。sequence 部分占12比特，nodeID 占10比特，偏移10比特，时间戳">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:04.624Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="GUID">
-<meta name="twitter:description" content="在点外卖或者网上购物的时候，每个订单中都会有一串独一无二的数字，但是处理订单的服务器肯定不止一台，如何保证多台服务器，也就是说一个计算机集群中，在相互独立的情况下（不沟通自己生成的订单号的信息）不生成相同的订单号码呢，下面我们就来介绍一种全球唯一标识符（ GUID ）的生成算法。 这里我们的 GUID 共64比特。sequence 部分占12比特，nodeID 占10比特，偏移10比特，时间戳">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-GUID"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      GUID
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-22T03:49:08.000Z" itemprop="datePublished">
-        May 22, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在点外卖或者网上购物的时候，每个订单中都会有一串独一无二的数字，但是处理订单的服务器肯定不止一台，如何保证多台服务器，也就是说一个计算机集群中，在相互独立的情况下（不沟通自己生成的订单号的信息）不生成相同的订单号码呢，下面我们就来介绍一种全球唯一标识符（ <code>GUID</code> ）的生成算法。</p>
-<p>这里我们的 <code>GUID</code> 共64比特。<code>sequence</code> 部分占12比特，<code>nodeID</code> 占10比特，偏移10比特，时间戳 <code>timestamp</code> 占剩余的42比特，偏移22比特。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">+-------------------------------------------+----------+------------+</span><br><span class="line">|                timestamp                  |nodeIDBits|sequenceBits|</span><br><span class="line">+-------------------------------------------+----------+------------+</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    nodeIDBits = <span class="keyword">uint64</span>(<span class="number">10</span>)</span><br><span class="line">    sequenceBits = <span class="keyword">uint64</span>(<span class="number">12</span>)</span><br><span class="line">    nodeIDShift = sequenceBits</span><br><span class="line">    timestampShift = sequenceBits + nodeIDBits</span><br><span class="line">    sequenceMask   = <span class="keyword">int64</span>(<span class="number">-1</span>) ^ (<span class="keyword">int64</span>(<span class="number">-1</span>) &lt;&lt; sequenceBits)</span><br><span class="line"></span><br><span class="line">    twepoch = <span class="keyword">int64</span>(<span class="number">1288834974288</span>)</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    ErrIDBackwards = errors.New(<span class="string">"ID went backward"</span>)</span><br><span class="line">    ErrTimeBackwards = errors.New(<span class="string">"time has gone backwards"</span>)</span><br><span class="line">    ErrSequenceExpired = errors.New(<span class="string">"sequence expired"</span>)</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
-<p>下面我们定义一个生成 <code>guid</code> 的工厂， <code>guid</code> 由 <code>timestamp</code>  ，<code>nodeID</code> 和 <code>sequence</code> 这三个部分构成，每个工厂有自己的 <code>nodeID</code>。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> guid <span class="keyword">int64</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> guidFactory <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Metex</span><br><span class="line">    nodeID        <span class="keyword">int64</span></span><br><span class="line">    sequence      <span class="keyword">int64</span></span><br><span class="line">    lastTimestamp <span class="keyword">int64</span></span><br><span class="line">    lastID        guid</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewGUIDFactory</span><span class="params">(nodeID <span class="keyword">int64</span>)</span> *<span class="title">guidFactory</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;guidFactory&#123;</span><br><span class="line">        nodeID: nodeID,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在利用工厂模式生成 <code>GUID</code> 时，首先计算当前时间戳，并且除以1048576（2的20次方），这样是为了去除时间的假随机部分，如果新生成的<code>timestamp</code> 小于 <code>lastTimestamp</code> ，则返回 <code>ErrTimeBackwards</code> 错误，对于相同的时间戳，我们的 <code>sequence</code> 采取递增策略，如果 <code>sequence</code> 达到最大值后归0，则返回 <code>ErrSequenceExpired</code> 错误，如果时间戳不相同，则令 <code>sequence</code> 重新从0开始，最后使三部分拼接组成一个新的 <code>guid</code> ，如果生成的 <code>guid</code> 小于 <code>lastID</code> ，则返回 <code>ErrIDBackwards</code> 错误，如果正常则返回结果。整个计算的过程需要由锁来保护。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(g *guidFactory)</span> <span class="title">Create</span><span class="params">()</span> <span class="params">(guid, error)</span></span> &#123;</span><br><span class="line">    f.Lock()</span><br><span class="line"></span><br><span class="line">    <span class="comment">// divide by 1048576, giving pseudo-milliseconds</span></span><br><span class="line">    ts := time.Now().UnixNano() &gt;&gt; <span class="number">20</span></span><br><span class="line"> </span><br><span class="line">    <span class="keyword">if</span> ts &lt; f.lastTimestamp &#123;</span><br><span class="line">        f.Unlock()</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>, ErrTimeBackwards</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> f.lastTimestamp == ts &#123;</span><br><span class="line">        f.sequence = (f.sequence + <span class="number">1</span>) &amp; sequenceMask</span><br><span class="line">        <span class="keyword">if</span> f.sequence == <span class="number">0</span> &#123;</span><br><span class="line">            f.Unlock()</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span>, ErrSequenceExpired</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        f.sequence = <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    f.lastTimestamp = ts</span><br><span class="line"></span><br><span class="line">    id := guid(((ts - twepoch) &lt;&lt; timestampShift) |</span><br><span class="line">        (f.nodeID &lt;&lt; nodeIDShift) |</span><br><span class="line">        f.sequence)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> id &lt;= f.lastID &#123;</span><br><span class="line">        f.Unlock()</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>, ErrIDBackwards</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    f.lastID = id</span><br><span class="line"></span><br><span class="line">    f.Unlock()</span><br><span class="line"></span><br><span class="line">    return id, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>为了方便结果的表示，我们会将10进制转换为16进制，利用标准库中的 <code>hex</code> 就可以轻松实现了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(g guid)</span> <span class="title">Hex</span><span class="params">()</span> <span class="title">MessageID</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> h MessageID</span><br><span class="line">    <span class="keyword">var</span> b [<span class="number">8</span>]<span class="keyword">byte</span></span><br><span class="line">    </span><br><span class="line">    b[<span class="number">0</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">56</span>)</span><br><span class="line">    b[<span class="number">1</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">48</span>)</span><br><span class="line">    b[<span class="number">2</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">40</span>)</span><br><span class="line">    b[<span class="number">3</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">32</span>)</span><br><span class="line">    b[<span class="number">4</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">24</span>)</span><br><span class="line">    b[<span class="number">5</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">16</span>)</span><br><span class="line">    b[<span class="number">6</span>] = <span class="keyword">byte</span>(g &gt;&gt; <span class="number">8</span>)</span><br><span class="line">    b[<span class="number">7</span>] = <span class="keyword">byte</span>(g)</span><br><span class="line"></span><br><span class="line">    hex.Encode(h[:], b[:])</span><br><span class="line">    <span class="keyword">return</span> h</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/23/Heartbeat/index.html b/2018/05/23/Heartbeat/index.html
deleted file mode 100644
index 06ebbb9..0000000
--- a/2018/05/23/Heartbeat/index.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Heartbeat | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在一个分布式集群中，个别节点出现宕机的情况并不少见，例如在一个只有一个主节点，和多个从节点的集群中，从节点发生宕机对整个系统影响倒不算太大，如果主节点宕机，系统将不能正常运行，所以必须有一个机制检测各个节点是否正常运行。 心跳机制是设计高可用性分布式系统的重要技术。心跳机制通过周期性地向其他节点发送心跳消息并等待确认来检测集群中的节点状态。当节点状态发生变化时，会通知发送心跳检测消息的节点。如果发">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Heartbeat">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/23/Heartbeat/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在一个分布式集群中，个别节点出现宕机的情况并不少见，例如在一个只有一个主节点，和多个从节点的集群中，从节点发生宕机对整个系统影响倒不算太大，如果主节点宕机，系统将不能正常运行，所以必须有一个机制检测各个节点是否正常运行。 心跳机制是设计高可用性分布式系统的重要技术。心跳机制通过周期性地向其他节点发送心跳消息并等待确认来检测集群中的节点状态。当节点状态发生变化时，会通知发送心跳检测消息的节点。如果发">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:15.201Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Heartbeat">
-<meta name="twitter:description" content="在一个分布式集群中，个别节点出现宕机的情况并不少见，例如在一个只有一个主节点，和多个从节点的集群中，从节点发生宕机对整个系统影响倒不算太大，如果主节点宕机，系统将不能正常运行，所以必须有一个机制检测各个节点是否正常运行。 心跳机制是设计高可用性分布式系统的重要技术。心跳机制通过周期性地向其他节点发送心跳消息并等待确认来检测集群中的节点状态。当节点状态发生变化时，会通知发送心跳检测消息的节点。如果发">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Heartbeat"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Heartbeat
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-23T09:52:18.000Z" itemprop="datePublished">
-        May 23, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在一个分布式集群中，个别节点出现宕机的情况并不少见，例如在一个只有一个主节点，和多个从节点的集群中，从节点发生宕机对整个系统影响倒不算太大，如果主节点宕机，系统将不能正常运行，所以必须有一个机制检测各个节点是否正常运行。</p>
-<p>心跳机制是设计高可用性分布式系统的重要技术。心跳机制通过周期性地向其他节点发送心跳消息并等待确认来检测集群中的节点状态。当节点状态发生变化时，会通知发送心跳检测消息的节点。如果发送心跳检测消息的节点在一段时间内未收到确认，则该节点将被视为失败。这是心跳机制的基本原理。</p>
-<p>在设计心跳时，需要考虑心跳是单向，还是双向的，单向的心跳可以保证当发送方出现问题时，接收方在一定的时间内可以检测到，而双向则可以保证双方都可以检测到对方是否出现问题。</p>
-<p>下面我们来实现一个单向的心跳检测机制，这里存在一个主节点和多个从节点，主节点会向连接到自己的从节点定期发送心跳消息，如果从节点在规定时间内没有收到来自主节点的心跳消息，则认为主节点发生异常，然后进行相应的超时处理流程（如自己参与选举成为主节点等）。</p>
-<h2 id="Master"><a href="#Master" class="headerlink" title="Master"></a>Master</h2><p>在主节点中我们维护连接到主节点的从节点的信息，使用用一个数组保存，当节点加入或者退出系统时候，分别调用 <code>Add</code> 和 <code>Del</code> 方法进行增删。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Master <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.RWMutex</span><br><span class="line">    n      <span class="keyword">int</span></span><br><span class="line">    slaves []*Slave</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Master)</span> <span class="title">Add</span><span class="params">(s *Slave)</span></span> &#123;</span><br><span class="line">    s.Lock()</span><br><span class="line">    <span class="keyword">defer</span> s.Unlock()</span><br><span class="line">    s.n++</span><br><span class="line">    s.slaves = <span class="built_in">append</span>(s.slaves, s)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Master)</span> <span class="title">Del</span><span class="params">(s *Slave)</span></span> &#123;</span><br><span class="line">    s.Lock()</span><br><span class="line">    <span class="keyword">defer</span> s.Unlock()</span><br><span class="line">    n := <span class="built_in">make</span>([]*Slave, <span class="built_in">len</span>(s.slaves)<span class="number">-1</span>)</span><br><span class="line">    <span class="keyword">for</span> _, x := <span class="keyword">range</span> m.slaves &#123;</span><br><span class="line">        <span class="keyword">if</span> x != s &#123;</span><br><span class="line">            n = <span class="built_in">append</span>(n, x)</span><br><span class="line">        &#125; </span><br><span class="line">    &#125;</span><br><span class="line">    s.n--</span><br><span class="line">    s.slaves = n</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>一旦从节点与主节点建立连接，主节点会通过 <code>heartbeatLoop</code> 向从节点定时发送心跳消息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Master)</span> <span class="title">handleConn</span><span class="params">(conn net.Conn)</span></span> &#123;</span><br><span class="line">    s := &amp;slave&#123;</span><br><span class="line">        conn: conn,</span><br><span class="line">        connectTime: time.Now()</span><br><span class="line">    &#125;</span><br><span class="line">    m.Add(s)</span><br><span class="line">    log.Println(<span class="string">"Connected: "</span>, conn.RemoteAddr)</span><br><span class="line">    <span class="keyword">go</span> s.heartbeatLoop()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Slave"><a href="#Slave" class="headerlink" title="Slave"></a>Slave</h2><p><code>slave</code> 是主节点维护的从节点的信息，<code>connectTime</code> 表示从节点第一次连接的时间，<code>exit chan struct{}</code> 用于接收退出信号，例如当从节点退出该集群时或者从节点发生宕机时，通过该机制停止向从节点发送心跳信息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> slave <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.RWMutex</span><br><span class="line">    conn        net.Conn</span><br><span class="line">    connectTime time.Time</span><br><span class="line">    exit        <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在 <code>hearbeatLoop</code> 方法中，通过 <code>time.NewTicker</code> 来设置一个定时器，每隔一秒钟向从节点发送心跳消息。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *slave)</span> <span class="title">heartbeatLoop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    ticker := time.NewTicker(<span class="number">1</span> * time.Second)</span><br><span class="line">    <span class="keyword">defer</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        s.conn.Close()</span><br><span class="line">        ticker.Stop()</span><br><span class="line">    &#125;()</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> t := &lt;-ticker.C:</span><br><span class="line">            s.Lock()</span><br><span class="line">            c.conn.Write([]<span class="keyword">byte</span>(fmt.Sprintf(<span class="string">"heartbeat %d"</span>, time.Now())))</span><br><span class="line">            s.Unlock()</span><br><span class="line">        <span class="keyword">case</span> &lt;-s.exit:</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *slave)</span> <span class="title">stop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    s.exit &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Main-Routine"><a href="#Main-Routine" class="headerlink" title="Main Routine"></a>Main Routine</h2><h2 id="master-main"><a href="#master-main" class="headerlink" title="master main"></a>master main</h2><p>主节点通过监听相应的端口，处理与自己连接的请求，对于每个连接请求，都会起一个新的 <code>goroutine</code> 分别处理。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    l, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">":8080"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> l.Close()</span><br><span class="line">    m := &amp;Master&#123;&#125;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        conn, err := l.Accept()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Fatal(err)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">go</span> m.handleConnection(conn)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="slave-main"><a href="#slave-main" class="headerlink" title="slave main"></a>slave main</h2><p>从节点会接收来自主节点的心跳消息，并通过 <code>time.NewTimer</code> 来设置一个定时器，如果在规定的时间内没有收到来自主节点的消息，则说明心跳超时，怀疑主节点出现异常，如果在规定的时间内收到心跳消息，则通过<code>timer.Reset</code> 来重置定时器。一般来说，心跳超时的时间是心跳发送周期的3倍左右。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    conn, err := net.Dial(<span class="string">"tcp"</span>, <span class="string">"localhost:8080"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    timer := time.NewTimer(<span class="number">3</span> * time.Second)</span><br><span class="line"></span><br><span class="line">    msgChan := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">string</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(conn net.Conn)</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">100</span>)</span><br><span class="line">            n, err := conn.Read(b)</span><br><span class="line">            <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">                <span class="built_in">panic</span>(err)</span><br><span class="line">            &#125;</span><br><span class="line">            msgChan &lt;- <span class="keyword">string</span>(b[:n])</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;(conn)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> m := &lt;-msgChan:</span><br><span class="line">            fmt.Println(m)</span><br><span class="line">        <span class="keyword">case</span> &lt;-timer.C:</span><br><span class="line">            fmt.Println(<span class="string">"Timed out"</span>)</span><br><span class="line">            <span class="comment">// do something here</span></span><br><span class="line">            &lt;-msgChan</span><br><span class="line">        &#125;</span><br><span class="line">        timer.Reset(<span class="number">3</span> * time.Second)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Randomized-Timeout"><a href="#Randomized-Timeout" class="headerlink" title="Randomized Timeout"></a>Randomized Timeout</h2><p>上面使用的计时器的时间间隔都是相同的，但是在很多工程项目例如 <code>Raft</code> 中，常常使用 <code>Randomized Timeout</code> 这种奇技淫巧来减少 <code>split votes</code> 情况的发生。使用随机超时我们需要自己定义一个 <code>var timeout &lt;-chan time.Time</code> ，每次重置计时器时（例如收到心跳消息或者计时器超时），先将相应的 <code>timeout</code> 设置为 <code>nil</code> ，然后获取一个随机的时间间隔，并使用 <code>time.After</code> 来获得一个新的计时器。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    rand.Seed(time.Now().UTC().UnixNano())</span><br><span class="line">    ticker := time.NewTicker(<span class="number">250</span> * time.Millisecond)</span><br><span class="line">    <span class="keyword">defer</span> ticker.Stop()</span><br><span class="line">    appendEntries := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> <span class="keyword">range</span> ticker.C &#123;</span><br><span class="line">            appendEntries &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> timeout &lt;-<span class="keyword">chan</span> time.Time</span><br><span class="line">    <span class="keyword">for</span> &#123;  </span><br><span class="line">        <span class="keyword">if</span> timeout == <span class="literal">nil</span> &#123;</span><br><span class="line">            timeout = time.After(time.Duration(r(<span class="number">150</span>, <span class="number">300</span>)) * time.Millisecond)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> m := &lt;-appendEntries:</span><br><span class="line">            timeout = <span class="literal">nil</span></span><br><span class="line">            fmt.Println(<span class="string">"received a message"</span>)</span><br><span class="line">            <span class="comment">// process(m)</span></span><br><span class="line">        <span class="keyword">case</span> &lt;-timeout:</span><br><span class="line">            timeout = <span class="literal">nil</span></span><br><span class="line">            fmt.Println(<span class="string">"convert to candidate"</span>)</span><br><span class="line">            <span class="comment">// do something such as election</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">r</span><span class="params">(min, max <span class="keyword">int</span>)</span> <span class="title">int</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> rand.Intn(max-min) + min</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/24/LRU/index.html b/2018/05/24/LRU/index.html
deleted file mode 100644
index 2120345..0000000
--- a/2018/05/24/LRU/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>LRU | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="最近最少使用（ Least Recently Used ）也就是 LRU 算法是内存页面置换算法的一种，使用该算法可以在有限的资源内提高内存访问的速度，它利用了著名的局部性原理，更具体的说是时间局部性，也就是说如果一个信息项正在被访问，那么在近期它很可能还会被再次访问。 例如我们有3个物理块，访问序列为 7，0，1，2，0，3，0  访问7时，LRU缺失，此时LRU未满，放入7，此时淘汰顺序为7">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="LRU">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/24/LRU/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="最近最少使用（ Least Recently Used ）也就是 LRU 算法是内存页面置换算法的一种，使用该算法可以在有限的资源内提高内存访问的速度，它利用了著名的局部性原理，更具体的说是时间局部性，也就是说如果一个信息项正在被访问，那么在近期它很可能还会被再次访问。 例如我们有3个物理块，访问序列为 7，0，1，2，0，3，0  访问7时，LRU缺失，此时LRU未满，放入7，此时淘汰顺序为7">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://i.ytimg.com/vi/4wVp97-uqr0/maxresdefault.jpg">
-<meta property="og:updated_time" content="2018-06-26T08:46:42.796Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="LRU">
-<meta name="twitter:description" content="最近最少使用（ Least Recently Used ）也就是 LRU 算法是内存页面置换算法的一种，使用该算法可以在有限的资源内提高内存访问的速度，它利用了著名的局部性原理，更具体的说是时间局部性，也就是说如果一个信息项正在被访问，那么在近期它很可能还会被再次访问。 例如我们有3个物理块，访问序列为 7，0，1，2，0，3，0  访问7时，LRU缺失，此时LRU未满，放入7，此时淘汰顺序为7">
-<meta name="twitter:image" content="https://i.ytimg.com/vi/4wVp97-uqr0/maxresdefault.jpg">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-LRU"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      LRU
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-23T16:23:40.000Z" itemprop="datePublished">
-        May 24, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>最近最少使用（ <code>Least Recently Used</code> ）也就是 <code>LRU</code> 算法是内存页面置换算法的一种，使用该算法可以在有限的资源内提高内存访问的速度，它利用了著名的局部性原理，更具体的说是时间局部性，也就是说如果一个信息项正在被访问，那么在近期它很可能还会被再次访问。</p>
-<p>例如我们有3个物理块，访问序列为 <code>7，0，1，2，0，3，0</code></p>
-<ul>
-<li>访问7时，LRU缺失，此时LRU未满，放入7，此时淘汰顺序为7</li>
-<li>访问0时，LRU缺失，此时LRU未满，放入0，此时淘汰顺序为7，0</li>
-<li>访问1时，LRU缺失，此时LRU未满，放入1，此时淘汰顺序为7，0 ，1</li>
-<li>访问2时，LRU缺失，此时LRU已满，驱逐7，放入2，此时淘汰顺序为0，1，2</li>
-<li>访问0时，LRU命中，更新淘汰顺序，此时淘汰循序为1，2，0</li>
-<li>访问3时，LRU缺失，此时LRU已满，驱逐1，放入3，此时淘汰顺序为2，0，3</li>
-<li>访问0时，LRU命中，更新淘汰顺序，此时淘汰顺序为0，3，2</li>
-</ul>
-<p><img src="https://i.ytimg.com/vi/4wVp97-uqr0/maxresdefault.jpg" alt="LRU"></p>
-<p>我们利用链表（ <code>*list.List</code> ）维护其淘汰顺序，利用 <code>map</code> 作为其存储引擎（作为物质基础）。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&lt;---------------------------------------------------------&gt;</span><br><span class="line">newest                                               oldest</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Key <span class="keyword">interface</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> entry <span class="keyword">struct</span> &#123;</span><br><span class="line">    key Key</span><br><span class="line">    value <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Cache <span class="keyword">struct</span> &#123;</span><br><span class="line">    MaxEntries <span class="keyword">int</span></span><br><span class="line">    OnEvicted  <span class="function"><span class="keyword">func</span><span class="params">(key Key, value <span class="keyword">interface</span>&#123;&#125;)</span></span></span><br><span class="line"><span class="function">    </span></span><br><span class="line"><span class="function">    <span class="title">ll</span>         *<span class="title">list</span>.<span class="title">List</span></span></span><br><span class="line"><span class="function">    <span class="title">cache</span>      <span class="title">map</span>[<span class="title">interface</span></span>&#123;&#125;]*list.Element</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(maxEntries <span class="keyword">int</span>)</span> *<span class="title">Cache</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Cache&#123;</span><br><span class="line">        MaxEntries: maxEntries,</span><br><span class="line">        ll:         list.New(),</span><br><span class="line">        cache:      <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">interface</span>&#123;&#125;]*list.Element),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为我们经常需要判断当前的 <code>LRU</code> 缓存是否存满，所以我们构造一个<code>helper function</code> 来获取当前缓存的容量。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Cache)</span> <span class="title">Len</span><span class="params">()</span> <span class="title">int</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> c.cache == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> c.ll.Len()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>淘汰顺序在两种情况下会更新，一是新增元素时，如果元素在 <code>LRU</code> 缓存中不存在，则将它放在链表的头部（ <code>PushFront</code> ），如果存在，则直接将其移到链表的头部（ <code>MoveToFront</code> ）。二是在获取元素时，如果元素存在，则直接将其移到链表的头部（ <code>MoveToFront</code> ）。这样一来我们就能确保最新的东西在链表头，最老的东西在链表尾。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Cache)</span> <span class="title">Add</span><span class="params">(key Key, value interfacfe&#123;&#125;)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> c.cache == <span class="literal">nil</span> &#123;</span><br><span class="line">        c.cache = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">interface</span>&#123;&#125;*list.Element])</span><br><span class="line">        c.ll = list.New()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> ee, ok := c.cache[key]; ok &#123;</span><br><span class="line">        c.ll.MoveToFront(ee)</span><br><span class="line">        ee.Value.(*entry).value = value</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    ele := c.ll.PushFront(&amp;entry&#123;key, value&#125;)</span><br><span class="line">    c.cache[key] = ele</span><br><span class="line">    <span class="keyword">if</span> c.MaxEntries != <span class="number">0</span> &amp;&amp; c.ll.Len() &gt; c.MaxEntries &#123;</span><br><span class="line">        c.RemoveOldest()</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Cache)</span> <span class="title">Get</span><span class="params">(key Key)</span> <span class="params">(value <span class="keyword">interface</span>&#123;&#125;, ok <span class="keyword">bool</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> c.cache == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> ele, hit := c.cache[key]; hit &#123;</span><br><span class="line">        c.ll.MoveToFront(ele)</span><br><span class="line">        <span class="keyword">return</span> ele.Value.(*entry).value, <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>RemoveOldest</code> 将最老的元素淘汰，也就是说将链表中最后一项移除，并将<code>map</code> 中对应的元素删除。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Cache)</span> <span class="title">RemoveOldest</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> c.cache == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    ele := c.ll.Back()</span><br><span class="line">    <span class="keyword">if</span> ele != <span class="literal">nil</span> &#123;</span><br><span class="line">        c.removeElement(ele)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Cache)</span> <span class="title">removeElement</span><span class="params">(e *list.Element)</span></span> &#123;</span><br><span class="line">    c.ll.Remove(e)</span><br><span class="line">    kv := e.Value.(*entry)</span><br><span class="line">    <span class="built_in">delete</span>(c.cache, kv.key)</span><br><span class="line">    <span class="keyword">if</span> c.OnEvicted != <span class="literal">nil</span> &#123;</span><br><span class="line">        c.OnEvicted(kv.key, kv.value)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>清除 <code>LRU</code> 缓存只需要将链表和 <code>map</code> 设为 <code>nil</code> 就可以了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Cache)</span> <span class="title">Clear</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> c.OnEvicted != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> _, e := <span class="keyword">range</span> c.cache &#123;</span><br><span class="line">            kv := e.Value.(*entry)</span><br><span class="line">            c.OnEvicted(kv.key, kv.value)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    c.ll = <span class="literal">nil</span></span><br><span class="line">    c.cache = <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/24/SingleFlight/index.html b/2018/05/24/SingleFlight/index.html
deleted file mode 100644
index 4eb5211..0000000
--- a/2018/05/24/SingleFlight/index.html
+++ /dev/null
@@ -1,253 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Single Flight | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="很多人闲来无事就喜欢刷票圈逛微博，所有的消息看完一遍之后，就开启疯狂下拉刷新模式，希望能第一时间看到什么劲爆的消息。对于应用的使用者，这倒没什么，但是如果连续多次下拉刷新操作都分别对应一次服务器请求的话，那么服务器估计就得扑街了，所以我们需要限制在一定时间内同一个请求的数量，以避免无用的请求。 我们需要实现一种机制，对于特定的请求，在该请求触发之后但还没有返回结果之前，对于之后所有相同的请求，无论">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Single Flight">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/24/SingleFlight/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="很多人闲来无事就喜欢刷票圈逛微博，所有的消息看完一遍之后，就开启疯狂下拉刷新模式，希望能第一时间看到什么劲爆的消息。对于应用的使用者，这倒没什么，但是如果连续多次下拉刷新操作都分别对应一次服务器请求的话，那么服务器估计就得扑街了，所以我们需要限制在一定时间内同一个请求的数量，以避免无用的请求。 我们需要实现一种机制，对于特定的请求，在该请求触发之后但还没有返回结果之前，对于之后所有相同的请求，无论">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:57.079Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Single Flight">
-<meta name="twitter:description" content="很多人闲来无事就喜欢刷票圈逛微博，所有的消息看完一遍之后，就开启疯狂下拉刷新模式，希望能第一时间看到什么劲爆的消息。对于应用的使用者，这倒没什么，但是如果连续多次下拉刷新操作都分别对应一次服务器请求的话，那么服务器估计就得扑街了，所以我们需要限制在一定时间内同一个请求的数量，以避免无用的请求。 我们需要实现一种机制，对于特定的请求，在该请求触发之后但还没有返回结果之前，对于之后所有相同的请求，无论">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-SingleFlight"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Single Flight
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-24T05:46:36.000Z" itemprop="datePublished">
-        May 24, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>很多人闲来无事就喜欢刷票圈逛微博，所有的消息看完一遍之后，就开启疯狂下拉刷新模式，希望能第一时间看到什么劲爆的消息。对于应用的使用者，这倒没什么，但是如果连续多次下拉刷新操作都分别对应一次服务器请求的话，那么服务器估计就得扑街了，所以我们需要限制在一定时间内同一个请求的数量，以避免无用的请求。</p>
-<p>我们需要实现一种机制，对于特定的请求，在该请求触发之后但还没有返回结果之前，对于之后所有相同的请求，无论多少个，都不会真正触发，而是等待第一个请求返回，然后共用一个结果。</p>
-<p><code>SingleFlight</code> 就可以帮助我们实现上述的要求，我们使用结构体 <code>call</code> 来表示特定请求返回的结果，在 <code>SingleFlight</code> 结构体中使用一个 <code>map</code> 来存储不同的请求结果，也就是一个请求对应一个<code>call</code>，并用锁保护 <code>map</code> 的读写。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> SingleFlight <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Mutex</span><br><span class="line">    m <span class="keyword">map</span>[<span class="keyword">string</span>]*call</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> call <span class="keyword">struct</span> &#123;</span><br><span class="line">    wg  sync.WaitGroup</span><br><span class="line">    val <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">    err error</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>一般来说，<code>call</code> 是一些所需时间长，消耗资源多的操作的返回结果（例如<code>HTTP</code> 请求）。<code>Do</code> 方法就保证对于同一个请求，在结果未返回之前，后面相同的请求都不会真正进行，而是等待第一个请求的结果。在函数运行时需要检测当前 <code>map</code> 是否为空，如果为空则 <code>make</code> 一个，然后检查是否有相同的请求正在进行，如果有则使用 <code>c.wg.Wait</code> 来等待执行结果。要是这个请求是该时间段内第一个请求，则将它加入 <code>map</code> 中，然后通过 <code>c.wg.Add</code> 来增加 <code>WaitGroup</code> 应该等待的 <code>goroutine</code> 个数，当函数执行完成之后，通过 <code>c.wg.Done</code> 来广播告知他人，此时任何调用<code>c.wg.Wait</code> 的地方都会解除阻塞，并返回该结果。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(sf *SingleFlight)</span> <span class="title">Do</span><span class="params">(key <span class="keyword">string</span>, fn <span class="keyword">func</span>()</span> <span class="params">(<span class="keyword">interface</span>&#123;&#125;, error)</span>) <span class="params">(<span class="keyword">interface</span>&#123;&#125;, error)</span></span> &#123;</span><br><span class="line">    sf.Lock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> sf.m == <span class="literal">nil</span> &#123;</span><br><span class="line">        sf.m = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">string</span>]*call)</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> c, ok := sf.m[key]; ok &#123;</span><br><span class="line">        sf.Unlock()</span><br><span class="line">        c.wg.Wait()</span><br><span class="line">        <span class="keyword">return</span> c.val, c.err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    c := <span class="built_in">new</span>(call)</span><br><span class="line">    c.wg.Add(<span class="number">1</span>)</span><br><span class="line">    sf.m[key] = c</span><br><span class="line">    sf.Unlock()</span><br><span class="line"></span><br><span class="line">    c.val, c.err = fn()</span><br><span class="line">    c.wg.Done()</span><br><span class="line">    </span><br><span class="line">    sf.Lock()</span><br><span class="line">    <span class="built_in">delete</span>(sf.m, key)</span><br><span class="line">    sf.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> c.val, c.err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="WaitGroup"><a href="#WaitGroup" class="headerlink" title="WaitGroup"></a>WaitGroup</h2><p><code>SingleFlight</code> 机制主要是靠 <code>WaitGroup</code> 实现，一般来说，因为<code>main routine</code> 不会等待 <code>goroutine</code> 执行完成，所以需要某种机制等待所有的<code>goroutine</code> 执行完成，使用 <code>WaitGroup</code> 就可以帮助我们达到这样的目的。</p>
-<p><code>WaitGroup</code> 的本质就是一个计数器，当每起一个新的 <code>goroutine</code> 时，我们调用 <code>wg.Add(1)</code> 来增加计数器的数量，当该 <code>goroutine</code> 执行完毕时，利用 <code>wg.Done()</code> 可以将计数器减一，调用 <code>Wait()</code> 方法的地方会一直阻塞 <code>main routine</code> ，只有当计数器为0时，<code>wg</code> 才会解除阻塞，此时程序才可以继续执行下去。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> WaitGroup <span class="keyword">struct</span> &#123;</span><br><span class="line">    noCopy noCopy</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 64-bit value: high 32 bits are counter, low 32 bits are waiter count.</span></span><br><span class="line">    <span class="comment">// 64-bit atomic operations require 64-bit alignment, but 32-bit</span></span><br><span class="line">    <span class="comment">// compilers do not ensure it. So we allocate 12 bytes and then use</span></span><br><span class="line">    <span class="comment">// the aligned 8 bytes in them as state.</span></span><br><span class="line">    state1 [<span class="number">12</span>]<span class="keyword">byte</span></span><br><span class="line">    sema   <span class="keyword">uint32</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(wg *WaitGroup)</span> <span class="title">Add</span><span class="params">(delta <span class="keyword">int</span>)</span></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(wg *WaitGroup)</span> <span class="title">Done</span><span class="params">()</span></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(wg *WaitGroup)</span> <span class="title">Wait</span><span class="params">()</span></span></span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line"><span class="keyword">var</span> urls = []<span class="keyword">string</span>&#123;</span><br><span class="line">    <span class="string">"http://www.golang.org/"</span>,</span><br><span class="line">    <span class="string">"http://www.google.com/"</span>,</span><br><span class="line">    <span class="string">"http://www.somestupidname.com/"</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> _, url := <span class="keyword">range</span> urls &#123;</span><br><span class="line">    <span class="comment">// Increment the WaitGroup counter.</span></span><br><span class="line">    wg.Add(<span class="number">1</span>)</span><br><span class="line">    <span class="comment">// Launch a goroutine to fetch the URL.</span></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(url <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    <span class="comment">// Decrement the counter when the goroutine completes</span></span><br><span class="line">    <span class="keyword">defer</span> wg.Done() </span><br><span class="line">    <span class="comment">// Fetch the URL.</span></span><br><span class="line">    http.Get(url)</span><br><span class="line">    &#125;(url)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// Wait for all HTTP fetches to complete.</span></span><br><span class="line">wg.Wait()</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/25/ConcurrentPrimeSieve/index.html b/2018/05/25/ConcurrentPrimeSieve/index.html
deleted file mode 100644
index beef857..0000000
--- a/2018/05/25/ConcurrentPrimeSieve/index.html
+++ /dev/null
@@ -1,268 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Concurrent Prime Sieve | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="本科刚学编程的时候经常遇到判断一个数是不是素数之类的编程题，当时基础比较差，用的方法也相当简单粗暴，直接采用枚举法判断，虽然简单但是效率很低，时间复杂度为 O(n^2) ，后来慢慢了解了神奇的埃氏筛法，只用 O(nlglgn) 的时间复杂度就可以完成，效率大幅度提高，如果对埃氏筛不了解的童鞋可以看看这篇文章 sieve of Eratosthenes。  一般的埃氏筛实现都是单线程的，并不能完全发">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Concurrent Prime Sieve">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/25/ConcurrentPrimeSieve/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="本科刚学编程的时候经常遇到判断一个数是不是素数之类的编程题，当时基础比较差，用的方法也相当简单粗暴，直接采用枚举法判断，虽然简单但是效率很低，时间复杂度为 O(n^2) ，后来慢慢了解了神奇的埃氏筛法，只用 O(nlglgn) 的时间复杂度就可以完成，效率大幅度提高，如果对埃氏筛不了解的童鞋可以看看这篇文章 sieve of Eratosthenes。  一般的埃氏筛实现都是单线程的，并不能完全发">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="http://empslocal.ex.ac.uk/people/staff/mrwatkin/bridge1.jpg">
-<meta property="og:image" content="https://talks.golang.org/2012/concurrency/images/gophereartrumpet.jpg">
-<meta property="og:updated_time" content="2018-06-26T08:44:16.352Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Concurrent Prime Sieve">
-<meta name="twitter:description" content="本科刚学编程的时候经常遇到判断一个数是不是素数之类的编程题，当时基础比较差，用的方法也相当简单粗暴，直接采用枚举法判断，虽然简单但是效率很低，时间复杂度为 O(n^2) ，后来慢慢了解了神奇的埃氏筛法，只用 O(nlglgn) 的时间复杂度就可以完成，效率大幅度提高，如果对埃氏筛不了解的童鞋可以看看这篇文章 sieve of Eratosthenes。  一般的埃氏筛实现都是单线程的，并不能完全发">
-<meta name="twitter:image" content="http://empslocal.ex.ac.uk/people/staff/mrwatkin/bridge1.jpg">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ConcurrentPrimeSieve"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Concurrent Prime Sieve
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-25T06:36:04.000Z" itemprop="datePublished">
-        May 25, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>本科刚学编程的时候经常遇到判断一个数是不是素数之类的编程题，当时基础比较差，用的方法也相当简单粗暴，直接采用枚举法判断，虽然简单但是效率很低，时间复杂度为 <code>O(n^2)</code> ，后来慢慢了解了神奇的埃氏筛法，只用 <code>O(nlglgn)</code> 的时间复杂度就可以完成，效率大幅度提高，如果对埃氏筛不了解的童鞋可以看看这篇文章 <a href="http://empslocal.ex.ac.uk/people/staff/mrwatkin/sieve.htm" target="_blank" rel="noopener">sieve of Eratosthenes</a>。</p>
-<p><img src="http://empslocal.ex.ac.uk/people/staff/mrwatkin/bridge1.jpg" alt="Sieve"></p>
-<p>一般的埃氏筛实现都是单线程的，并不能完全发挥现在多核 <code>CPU</code> 的全部性能，下面给出了 <code>Golang</code> 并发版本的埃氏筛实现。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">generate</span><span class="params">(ch <span class="keyword">chan</span> <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">2</span> ;; i++ &#123;</span><br><span class="line">        ch &lt;- i</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">filter</span><span class="params">(in, out <span class="keyword">chan</span> <span class="keyword">int</span>, prime <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        i := &lt;-in</span><br><span class="line">        <span class="keyword">if</span> i % prime != <span class="number">0</span> &#123;</span><br><span class="line">            out &lt;- i</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    ch := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line">    <span class="keyword">go</span> generate(ch)</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        prime := &lt;-ch</span><br><span class="line">        fmt.Println(prime)</span><br><span class="line">        out := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line">        <span class="keyword">go</span> filter(ch, out, prime)</span><br><span class="line">        ch = out</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="详解"><a href="#详解" class="headerlink" title="详解"></a>详解</h2><p>并发版本的埃氏筛代码行数虽然不多，然而实现还是比较 <code>tricky</code> 的，谁要是第一遍就看懂算我输（你要是天才的话当我没说过）。</p>
-<p><img src="https://talks.golang.org/2012/concurrency/images/gophereartrumpet.jpg" alt="channel"></p>
-<p>首先要起一个 <code>goroutine</code> ，记为 <code>G</code> ， 用于生成2以后的整数，并放到通道中（记为 <code>out0</code> ）供别的 <code>goroutine</code> 读取。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ch := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"><span class="keyword">go</span> generate(ch)          <span class="comment">// ch &lt;- i</span></span><br></pre></td></tr></table></figure>
-<p>进入第一个 <code>for</code> 循环，从上面的通道中取出第一个数2，毫无疑问，2为素数，所以创建一个通道 <code>out1</code> ，并起一个 <code>goroutine</code> ，记为 <code>filter1</code> ，用于过滤所有2的整数倍的数，此时通道数据流的走向为 <code>G -&gt; out1</code> ，只有通过 <code>filter1</code> 筛选的数才有资格进入 <code>out1</code> 中，此时将 <code>ch</code> 设为 <code>out1</code> （ <code>ch</code> 用于记录该链上的最后一个通道），第一个循环结束。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">prime := &lt;-ch             <span class="comment">// &lt;-ch</span></span><br><span class="line">fmt.Println(prime)        <span class="comment">// 输出2 </span></span><br><span class="line">out := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)     <span class="comment">// 记作out1</span></span><br><span class="line"><span class="keyword">go</span> filter(ch, out, prime) <span class="comment">// ch -&gt; out1</span></span><br><span class="line">ch = out                  <span class="comment">// ch = out1</span></span><br><span class="line">        ^</span><br><span class="line">        |</span><br><span class="line">      +----+ </span><br><span class="line">G ---&gt;|out1|---&gt;</span><br><span class="line">      +----+    </span><br><span class="line">        %<span class="number">2</span></span><br><span class="line">        ^</span><br><span class="line">        |</span><br><span class="line">        ch</span><br></pre></td></tr></table></figure>
-<p>进入第二个 <code>for</code> 循环，因为此时 <code>ch</code> 为 <code>out1</code> ，尝试去 <code>out1</code> 中取，3由 <code>G</code> 产生，然后经过 <code>filter1</code> 后成功进入 <code>out1</code> ，说明3是素数，此时我们再创建一个通道 <code>out2</code> ，并且再起一个 <code>goroutine</code> ，记为 <code>filter2</code> ，该 <code>goroutine</code> 会过滤所有3的整数倍的数，此时通道数据流的走向为 <code>G -&gt; out1 -&gt; out2</code> ，只有成功经过 <code>filter1,filter2</code> 筛选的数才能进入通道 <code>out2</code> 中，将 <code>ch</code> 设为 <code>out2</code> ，第二个循环结束。当<code>G</code> 中产生4，并尝试在这个链上移动时，当它经过 <code>filter1</code> 时，由于4是2的整数倍，说明不是素数，不符合要求，4出局。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">prime := &lt;-ch             <span class="comment">// &lt;-out1</span></span><br><span class="line">fmt.Println(prime)        <span class="comment">// 输出3</span></span><br><span class="line">out := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)     <span class="comment">// 记作out2</span></span><br><span class="line"><span class="keyword">go</span> filter(ch, out, prime) <span class="comment">// out1 -&gt; out2</span></span><br><span class="line">ch = out                  <span class="comment">// ch = out2</span></span><br><span class="line"></span><br><span class="line">        ^         ^</span><br><span class="line">        |         |</span><br><span class="line">      +----+    +----+    </span><br><span class="line">G ---&gt;|out1|---&gt;|out2|---&gt;</span><br><span class="line">      +----+    +----+ </span><br><span class="line">        %<span class="number">2</span>        %<span class="number">3</span></span><br><span class="line">                   ^</span><br><span class="line">                   |</span><br><span class="line">                   ch</span><br></pre></td></tr></table></figure>
-<p>进入第三个 <code>for</code> 循环，同样的，此时 <code>ch</code> 为 <code>out2</code> ，尝试去 <code>out2</code> 中取，5由 <code>G</code> 产生，经过 <code>filter1,filter2</code> 后成功进入 <code>out2</code> ，说明5为素数，此时我们再创建一个通道 <code>out3</code> ，并且再起一个 <code>goroutine</code> ，记为 <code>filter3</code> ，该 <code>goroutine</code> 会过滤所有5的整数倍的数，此时通道数据流的走向为 <code>G -&gt; out1 -&gt; out2 -&gt; out3</code> ，只有成功经过 <code>filter1,filter2,filter3</code> 筛选的数才能进入通道 <code>out3</code> 中，将 <code>ch</code> 设为 <code>out3</code> ，第三个循环结束。当 <code>G</code> 中产生6，并尝试在这个链上移动时，经过 <code>filter1</code> 时，由于6是2的整数倍，说明不是素数，不符合要求，同样出局。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">prime := &lt;-ch             <span class="comment">// &lt;-out2</span></span><br><span class="line">fmt.Println(prime)        <span class="comment">// 输出5</span></span><br><span class="line">out := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)     <span class="comment">// 记作out3</span></span><br><span class="line"><span class="keyword">go</span> filter(ch, out, prime) <span class="comment">// out2 -&gt; out3</span></span><br><span class="line">ch = out                  <span class="comment">// ch=out3</span></span><br><span class="line"></span><br><span class="line">        ^         ^         ^</span><br><span class="line">        |         |         |</span><br><span class="line">      +----+    +----+    +----+    </span><br><span class="line">G ---&gt;|out1|---&gt;|out2|---&gt;|out3|---&gt;</span><br><span class="line">      +----+    +----+    +----+</span><br><span class="line">        %<span class="number">2</span>        %<span class="number">3</span>        %<span class="number">5</span>        </span><br><span class="line">                            ^</span><br><span class="line">                            |</span><br><span class="line">                            ch</span><br></pre></td></tr></table></figure>
-<p>进入第四个 <code>for</code> 循环，此时 <code>ch</code> 为 <code>out3</code> ，尝试去 <code>out3</code> 中取，7由 <code>G</code> 产生，然后经过 <code>filter1,filter2,filter3</code> 筛选后成功进入 <code>out3</code> ，说明7是素数，此时我们再创建一个通道 <code>out4</code> ，并且再起一个 <code>goroutine</code> ，记为 <code>filter4</code> ，该 <code>goroutine</code> 会过滤所有7的整数倍的数，此时通道数据流的走向为 <code>G -&gt; out1 -&gt; out2 -&gt; out3 -&gt; out4</code> ，只有成功经过 <code>filter1,filter2,filter2,filter4</code> 筛选的数才能进入通道 <code>out4</code> 中，将 <code>ch</code> 设为 <code>out4</code> ，第四个循环结束。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">prime := &lt;-ch             <span class="comment">// &lt;-out3</span></span><br><span class="line">fmt.Println(prime)        <span class="comment">// 输出7</span></span><br><span class="line">out := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)     <span class="comment">// 记作out4</span></span><br><span class="line"><span class="keyword">go</span> filter(ch, out, prime) <span class="comment">// out3 -&gt; out4</span></span><br><span class="line">ch = out                  <span class="comment">// ch=out4</span></span><br><span class="line"></span><br><span class="line">        ^         ^         ^         ^</span><br><span class="line">        |         |         |         |</span><br><span class="line">      +----+    +----+    +----+    +----+</span><br><span class="line">G ---&gt;|out1|---&gt;|out2|---&gt;|out3|---&gt;|out4|---&gt;</span><br><span class="line">      +----+    +----+    +----+    +----+</span><br><span class="line">        %<span class="number">2</span>        %<span class="number">3</span>        %<span class="number">5</span>        %<span class="number">7</span>            </span><br><span class="line">                                      ^</span><br><span class="line">                                      |</span><br><span class="line">                                      ch</span><br></pre></td></tr></table></figure>
-<p>以此类推，并发版本素数筛的本质就是构建 <code>DaisyChain</code> ，每个数经过 <code>DaisyChain</code> 层层筛选后，如果最终保留，说明该数为素数，作为 <code>DaisyChain</code> 的最后一层加入，如此往复，就可以达到快速筛选素数的目的了。</p>
-<h2 id="chain-of-gophers"><a href="#chain-of-gophers" class="headerlink" title="chain of gophers"></a>chain of gophers</h2><p>上面这种将多个通道串联起来形成菊花链的模式还是比较常见，代码的关键就在于对通道指针的理解，例如下面的例子中就指定了 <code>left</code> 和 <code>right</code> 两个通道”指针”，最初这两个”指针”都指向 <code>leftmost</code> 通道，每次新建一个通道时候，都将 <code>left</code> 重新指向 <code>right</code> ，最后向 <code>right</code> 通道中发送0，<code>leftmost</code> 通道也就会很快收到最终的一个值了。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">   +----+    +----+    +----+    +----+           +----+</span><br><span class="line">&lt;- |    | &lt;- |    | &lt;- |    | &lt;- |    | &lt;- ... &lt;- |    | &lt;- 1</span><br><span class="line">   +----+    +----+    +----+    +----+           +----+</span><br><span class="line">  leftmost                                         right</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">f</span><span class="params">(left, right <span class="keyword">chan</span> <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    left &lt;- <span class="number">1</span> + &lt;-right</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    start := time.Now()</span><br><span class="line">    <span class="keyword">const</span> n = <span class="number">10000</span></span><br><span class="line">    leftmost := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line">    right := leftmost</span><br><span class="line">    left := leftmost</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; n; i++ &#123;</span><br><span class="line">        right = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line">        <span class="keyword">go</span> f(left, right)</span><br><span class="line">        left = right</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(c <span class="keyword">chan</span> <span class="keyword">int</span>)</span></span> &#123; c &lt;- <span class="number">0</span> &#125;(right)</span><br><span class="line"></span><br><span class="line">    fmt.Println(&lt;-leftmost, time.Since(start))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/26/TryLock/index.html b/2018/05/26/TryLock/index.html
deleted file mode 100644
index 7c1b825..0000000
--- a/2018/05/26/TryLock/index.html
+++ /dev/null
@@ -1,255 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Try Lock | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="123456789101112type Mutex struct &amp;#123;...&amp;#125;// Lock locks m. // If the lock is already in use, the calling goroutine//  blocks until the mutex is available.func (m *Mutex) Lock()// Unlock unlocks">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Try Lock">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/26/TryLock/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="123456789101112type Mutex struct &amp;#123;...&amp;#125;// Lock locks m. // If the lock is already in use, the calling goroutine//  blocks until the mutex is available.func (m *Mutex) Lock()// Unlock unlocks">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:28.423Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Try Lock">
-<meta name="twitter:description" content="123456789101112type Mutex struct &amp;#123;...&amp;#125;// Lock locks m. // If the lock is already in use, the calling goroutine//  blocks until the mutex is available.func (m *Mutex) Lock()// Unlock unlocks">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TryLock"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Try Lock
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-26T14:05:27.000Z" itemprop="datePublished">
-        May 26, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Mutex <span class="keyword">struct</span> &#123;...&#125;</span><br><span class="line"><span class="comment">// Lock locks m. </span></span><br><span class="line"><span class="comment">// If the lock is already in use, the calling goroutine</span></span><br><span class="line"><span class="comment">//  blocks until the mutex is available.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mutex)</span> <span class="title">Lock</span><span class="params">()</span></span></span><br><span class="line"><span class="function">// <span class="title">Unlock</span> <span class="title">unlocks</span> <span class="title">m</span>. </span></span><br><span class="line"><span class="function">// <span class="title">It</span> <span class="title">is</span> <span class="title">a</span> <span class="title">run</span>-<span class="title">time</span> <span class="title">error</span> <span class="title">if</span> <span class="title">m</span> <span class="title">is</span> <span class="title">not</span> <span class="title">locked</span> <span class="title">on</span> <span class="title">entry</span> <span class="title">to</span> <span class="title">Unlock</span>. </span></span><br><span class="line"><span class="function">// </span></span><br><span class="line"><span class="function">// <span class="title">A</span> <span class="title">locked</span> <span class="title">Mutex</span> <span class="title">is</span> <span class="title">not</span> <span class="title">associated</span> <span class="title">with</span> <span class="title">a</span> <span class="title">particular</span> <span class="title">goroutine</span>. </span></span><br><span class="line"><span class="function">// <span class="title">It</span> <span class="title">is</span> <span class="title">allowed</span> <span class="title">for</span> <span class="title">one</span> <span class="title">goroutine</span> <span class="title">to</span> <span class="title">lock</span> <span class="title">a</span> <span class="title">Mutex</span> <span class="title">and</span> <span class="title">then</span></span></span><br><span class="line"><span class="function">// <span class="title">arrange</span> <span class="title">for</span> <span class="title">another</span> <span class="title">goroutine</span> <span class="title">to</span> <span class="title">unlock</span> <span class="title">it</span>.</span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(m *Mutex)</span> <span class="title">Unlock</span><span class="params">()</span></span></span><br></pre></td></tr></table></figure>
-<p><code>sync.Mutex</code> 提供了 <code>Lock</code> 和 <code>Unlock</code> 两个方法分别对应上锁和解锁操作，如果锁已经被占据了，<code>Lock</code> 方法会阻塞相应的 <code>goroutine</code> 。在 <code>C</code> 中也有互斥锁的实现，但除了一般的上锁操作和解锁操作，它还多了一种方法 —— <code>pthread_mutex_trylock</code> ，也就是<code>TryLock</code> ， <code>pthread_mutex_trylock</code> 语义与 <code>pthread_mutex_lock</code> 类似，不同的是在锁已经被占据时返回 <code>EBUSY</code> 而不是挂起等待。</p>
-<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;pthread.h&gt;</span></span></span><br><span class="line"><span class="comment">// lock a mutex, If the mutex is already locked, </span></span><br><span class="line"><span class="comment">// the calling thread will block until the mutex becomes available.</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_lock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> *mutex)</span></span>;</span><br><span class="line"><span class="comment">// unlock a mutex</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_unlock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> *mutex)</span></span>;</span><br><span class="line"><span class="comment">// attempt to lock a mutex without blocking</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">pthread_mutex_trylock</span><span class="params">(<span class="keyword">pthread_mutex_t</span> *mutex)</span></span>;</span><br></pre></td></tr></table></figure>
-<p>下面我们自己来实现一个 <code>golang</code> 版本的 <code>try lock</code> 。实现互斥锁的关键就在于原子操作，保证即使有多个 <code>CPU</code> 存在的情况下，也不能同时执行同一条指令。利用 <code>sync/atomic</code> 库下面的方法可以轻松实现对一个数的原子操作。</p>
-<p>我们实现的互斥锁中有两个东西，首先是一个 <code>v int32</code> ，因为是互斥锁，所以初始化为1，还有一个 <code>ch</code> 通道用于唤醒阻塞等待的 <code>goroutine</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Mutex <span class="keyword">struct</span> &#123;</span><br><span class="line">    v <span class="keyword">int32</span></span><br><span class="line">    ch <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mutex)</span> <span class="title">Init</span><span class="params">()</span></span> &#123;</span><br><span class="line">    m.v = <span class="number">1</span></span><br><span class="line">    m.ch = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, <span class="number">1</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Lock</code> 方法获取一个锁，如果锁被占据了，则一直阻塞等待( <code>&lt;-m.ch</code> )，等待其他 <code>goroutine</code> 唤醒，相当于 <code>PV</code> 操作中的 <code>P</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mutex)</span> <span class="title">Lock</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> atomic.AddInt32(&amp;m.v, <span class="number">-1</span>) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> v := atomic.LoadInt32(&amp;m.v); v &gt;= <span class="number">0</span> &amp;&amp; atomic.SwapInt32(&amp;m.v, <span class="number">-1</span>) == <span class="number">1</span> &#123;</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">        &lt;-m.ch</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Unlock</code> 方法释放 <code>Mutex</code> ，如果当前有因为等待该锁而被阻塞的<code>goroutine</code> （说明 <code>atomic.SwapInt32(&amp;m.v, 1) != 0</code> ），则执行 <code>m.ch &lt;- struct{}{}</code> 将阻塞的 <code>goroutine</code> 唤醒，对应 <code>PV</code> 操作中的 <code>V</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mutex)</span> <span class="title">Unlock</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> atomic.SwapInt32(&amp;m.v, <span class="number">1</span>) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> m.ch &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上面的 <code>Lock</code> 方法会在锁可用之前阻塞调用该方法的 <code>goroutine</code> ，<code>TryLoad</code> 方法并不会阻塞，通过 <code>atomic.LoadInt32(&amp;m.v)</code> 来查看当前资源是否可用，如果不可用(说明 <code>v &lt;= 0</code> )，则返回 <code>false</code> ，如果 <code>atomic.CompareAndSwapInt32(&amp;m.v, 1, 0)</code> 返回 <code>true</code> ，说明资源可用直接上锁。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mutex)</span> <span class="title">TryLock</span><span class="params">()</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    v := atomic.LoadInt32(&amp;m.v)</span><br><span class="line">    <span class="keyword">if</span> v &lt;= <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> atomic.CompareAndSwapInt32(&amp;m.v, <span class="number">1</span>, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/27/TUNTAP/index.html b/2018/05/27/TUNTAP/index.html
deleted file mode 100644
index bff9b9a..0000000
--- a/2018/05/27/TUNTAP/index.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>TUN/TAP | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="TUN/TAP 为我们在 macOS 下面提供了虚拟网络接口（ TUN/TAP ），其本质是字符设备（ character special file ）。因为在 Unix 中一切皆文件，所以我们可以像操作文件一样操作这两种设备。  TUN 模拟网络层设备，它可以操作第3层数据包例如 IP 数据包。 TAP 模拟链路层设备，用于操作第2层数据包例如以太网帧。 12345678910111213141">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="TUN&#x2F;TAP">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/27/TUNTAP/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="TUN/TAP 为我们在 macOS 下面提供了虚拟网络接口（ TUN/TAP ），其本质是字符设备（ character special file ）。因为在 Unix 中一切皆文件，所以我们可以像操作文件一样操作这两种设备。  TUN 模拟网络层设备，它可以操作第3层数据包例如 IP 数据包。 TAP 模拟链路层设备，用于操作第2层数据包例如以太网帧。 12345678910111213141">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://1.bp.blogspot.com/-mnxh0kXQeKI/V10lx7q7H4I/AAAAAAAALYs/i427R0SfAQckApSz3piMDu7LiJnPzzu4gCLcB/s1600/tuntap.png">
-<meta property="og:updated_time" content="2018-06-26T08:47:26.177Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="TUN&#x2F;TAP">
-<meta name="twitter:description" content="TUN/TAP 为我们在 macOS 下面提供了虚拟网络接口（ TUN/TAP ），其本质是字符设备（ character special file ）。因为在 Unix 中一切皆文件，所以我们可以像操作文件一样操作这两种设备。  TUN 模拟网络层设备，它可以操作第3层数据包例如 IP 数据包。 TAP 模拟链路层设备，用于操作第2层数据包例如以太网帧。 12345678910111213141">
-<meta name="twitter:image" content="https://1.bp.blogspot.com/-mnxh0kXQeKI/V10lx7q7H4I/AAAAAAAALYs/i427R0SfAQckApSz3piMDu7LiJnPzzu4gCLcB/s1600/tuntap.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TUNTAP"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      TUN/TAP
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-27T06:05:03.000Z" itemprop="datePublished">
-        May 27, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><a href="http://tuntaposx.sourceforge.net/" target="_blank" rel="noopener">TUN/TAP</a> 为我们在 <code>macOS</code> 下面提供了虚拟网络接口（ <code>TUN/TAP</code> ），其本质是字符设备（ <code>character special file</code> ）。因为在 <code>Unix</code> 中一切皆文件，所以我们可以像操作文件一样操作这两种设备。</p>
-<p><img src="https://1.bp.blogspot.com/-mnxh0kXQeKI/V10lx7q7H4I/AAAAAAAALYs/i427R0SfAQckApSz3piMDu7LiJnPzzu4gCLcB/s1600/tuntap.png" alt="TUNTAP"></p>
-<p><code>TUN</code> 模拟网络层设备，它可以操作第3层数据包例如 <code>IP</code> 数据包。 <code>TAP</code> 模拟链路层设备，用于操作第2层数据包例如以太网帧。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> maxDevices = <span class="number">16</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    ErrBusy        = errors.New(<span class="string">"device is already in use"</span>)</span><br><span class="line">	  ErrNotReady    = errors.New(<span class="string">"device is not ready"</span>)</span><br><span class="line">	  ErrExhausted   = errors.New(<span class="string">"no devices are available"</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Interface <span class="keyword">interface</span> &#123;</span><br><span class="line">    Name() <span class="keyword">string</span></span><br><span class="line">    String() <span class="keyword">string</span></span><br><span class="line">    io.ReadWriteCloser</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Tun</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(Interface, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> newTUN(name)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Tap</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(Interface, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> newTAP(name)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>TUN/TAP</code> 在 <code>/dev</code>目录下，以 <code>/dev/tunX</code> 和 <code>/dev/tapX</code> 的形式存在，<code>X</code> 从0到15。每个字符设备都与同名的网络接口关联。网络接口只有在相应的字符设备被程序打开时才会创建，并且在字符设备关闭时将被删除。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> device <span class="keyword">struct</span> &#123;</span><br><span class="line">    n <span class="keyword">string</span></span><br><span class="line">    f *os.File</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *device)</span> <span class="title">Name</span><span class="params">()</span> <span class="title">string</span></span> &#123; <span class="keyword">return</span> d.n &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *device)</span> <span class="title">String</span><span class="params">()</span> <span class="title">string</span></span> &#123; <span class="keyword">return</span> d.n &#125;</span><br></pre></td></tr></table></figure>
-<p>新创建设备时，我们像正常打开文件一样使用 <code>TUN</code> 或者 <code>TAP</code> 设备，如果设备已经被占用，则报 <code>ErrBusy</code> 错误。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">newDevice</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(Interface, error)</span></span> &#123;</span><br><span class="line">    file, err := os.OpenFile(name, os.O_EXCL|os.O_RWWR, <span class="number">0</span>)</span><br><span class="line">    <span class="keyword">if</span> isBusy(err) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, ErrBusy</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">return</span> &amp;device&#123;n: name, f: file&#125;, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">isBusy</span><span class="params">(err error)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> perr, ok := err.(*os.PathError); ok &#123;</span><br><span class="line">        <span class="keyword">if</span> code, ok := perr.Err.(syscall.Errno); ok &#123;</span><br><span class="line">            <span class="keyword">if</span> code == <span class="number">0x10</span> || code == <span class="number">0x11</span> &#123;</span><br><span class="line">                <span class="comment">// device busy || exclusive lock</span></span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>tunX</code> 是 <code>IP</code> 隧道设备，可用于与内核交换 <code>IP</code> 数据包。使用 <code>read()</code> 获取单个数据包，使用 <code>write()</code> 可以将数据包写入 <code>/dev/tunX</code> 设备中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">newTUN</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(Interface, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(name) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> i := o; i &lt; maxDevices; i++ &#123;</span><br><span class="line">            iface, err := newDevice(<span class="string">"/dev/tun"</span> + strconv.Itoa(i))</span><br><span class="line">            <span class="keyword">if</span> err == ErrBusy &#123;</span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, ErrExhausted</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> newDevice(name)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>tapX</code> 是 <code>ethertap</code> 设备，为内核的以太网层提供接口。每次从 <code>/dev/tapX</code> 字符设备中读取或写入一个数据包。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">newTAP</span><span class="params">(name <span class="keyword">string</span>)</span> <span class="params">(Interface, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(name) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> i := o; i &lt; maxDevices; i++ &#123;</span><br><span class="line">            iface, err := newDevice(<span class="string">"/dev/tap"</span> + strconv.Itoa(i))</span><br><span class="line">            <span class="keyword">if</span> err == ErrBusy &#123;</span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span>, ErrExhausted</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> newDevice(name)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>对于字符设备，可以像操作正常文件一样进行读/写操作来向设备写入数据包或者获取数据包。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *device)</span> <span class="title">Read</span><span class="params">(p []<span class="keyword">byte</span>)</span> <span class="params">(n <span class="keyword">int</span>, err error)</span></span> &#123;</span><br><span class="line">    n, err := d.f.Read(p)</span><br><span class="line">    <span class="keyword">if</span> isNotReady(err) &#123;</span><br><span class="line">        err = ErrNotReady</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *device)</span> <span class="title">Write</span><span class="params">(p []<span class="keyword">byte</span>)</span> <span class="params">(n <span class="keyword">int</span>, err error)</span></span> &#123;</span><br><span class="line">    n, err := d.f.Write(p)</span><br><span class="line">    <span class="keyword">if</span> isNotReady(err) &#123;</span><br><span class="line">        err = ErrNotReady </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">isNotReady</span><span class="params">(err error)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> perr, ok := err.(*os.PathError); ok &#123;</span><br><span class="line">        <span class="keyword">if</span> code, ok := perr.Err.(syscall.Errno); ok &#123;</span><br><span class="line">            <span class="keyword">if</span> code == <span class="number">0x05</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *device)</span> <span class="title">Close</span><span class="params">()</span> <span class="title">error</span></span> &#123; </span><br><span class="line">    <span class="keyword">return</span> d.f.Close() </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/28/Shredder-Gluer/index.html b/2018/05/28/Shredder-Gluer/index.html
deleted file mode 100644
index 37aa28e..0000000
--- a/2018/05/28/Shredder-Gluer/index.html
+++ /dev/null
@@ -1,251 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Shredder &amp; Gluer | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="有时候我们需要向服务器上传一个很大的文件，但是无奈网络不稳定，再加上使用的软件不支持断点续传，经常会出现文件上传到一半出错，无奈只能从头再来，可以说是非常烦恼了。还有的时候服务器明确规定了单次上传文件的大小，手头又没有啥好的软件可以帮助我们进行文件的分割和合并操作，只好自己写一个。 要是一个人被砍了头，手，脚，再把这几个肢体合并起来大概率这人也是废了（在医学水平没有极大进步的情况下），但是对于一个">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Shredder &amp; Gluer">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/28/Shredder-Gluer/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="有时候我们需要向服务器上传一个很大的文件，但是无奈网络不稳定，再加上使用的软件不支持断点续传，经常会出现文件上传到一半出错，无奈只能从头再来，可以说是非常烦恼了。还有的时候服务器明确规定了单次上传文件的大小，手头又没有啥好的软件可以帮助我们进行文件的分割和合并操作，只好自己写一个。 要是一个人被砍了头，手，脚，再把这几个肢体合并起来大概率这人也是废了（在医学水平没有极大进步的情况下），但是对于一个">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:59.769Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Shredder &amp; Gluer">
-<meta name="twitter:description" content="有时候我们需要向服务器上传一个很大的文件，但是无奈网络不稳定，再加上使用的软件不支持断点续传，经常会出现文件上传到一半出错，无奈只能从头再来，可以说是非常烦恼了。还有的时候服务器明确规定了单次上传文件的大小，手头又没有啥好的软件可以帮助我们进行文件的分割和合并操作，只好自己写一个。 要是一个人被砍了头，手，脚，再把这几个肢体合并起来大概率这人也是废了（在医学水平没有极大进步的情况下），但是对于一个">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Shredder-Gluer"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Shredder &amp; Gluer
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-28T03:38:22.000Z" itemprop="datePublished">
-        May 28, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>有时候我们需要向服务器上传一个很大的文件，但是无奈网络不稳定，再加上使用的软件不支持断点续传，经常会出现文件上传到一半出错，无奈只能从头再来，可以说是非常烦恼了。还有的时候服务器明确规定了单次上传文件的大小，手头又没有啥好的软件可以帮助我们进行文件的分割和合并操作，只好自己写一个。</p>
-<p>要是一个人被砍了头，手，脚，再把这几个肢体合并起来大概率这人也是废了（在医学水平没有极大进步的情况下），但是对于一个文件来说则不同，无论什么格式的文件，其实本质上都是一大堆字节，如果我们在固定的地方进行切割，最后再在被切割的地方合并的话，这个文件还是可以被正常使用的。</p>
-<h2 id="Get-Basic-Info"><a href="#Get-Basic-Info" class="headerlink" title="Get Basic Info"></a>Get Basic Info</h2><p>在对文件切割之前，我们需要获得文件的基本信息，即文件的大小或者说是字节数，还需要决定切割后每个单位的大小，知道了这两个参数之后，就可以算出所有分割块的数量了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">f, err := os.Open(<span class="string">"some_very_big_file"</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="built_in">panic</span>(err)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">defer</span> f.Close()</span><br><span class="line">fileInfo, err := f.Stat()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="built_in">panic</span>(err)</span><br><span class="line">&#125;</span><br><span class="line">fileSize := fileInfo.Size()</span><br><span class="line">partSize := <span class="number">1</span> &lt;&lt; <span class="number">28</span></span><br><span class="line">concurrency := <span class="keyword">int</span>(fileSize / <span class="keyword">int64</span>(partSize))</span><br><span class="line"><span class="keyword">if</span> remainder := fileSize % <span class="keyword">int64</span>(partSize); remainder != <span class="number">0</span> &#123;</span><br><span class="line">    concurrency++</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Shredder"><a href="#Shredder" class="headerlink" title="Shredder"></a>Shredder</h2><p>利用 <code>io.NewSectionReader</code> 可以读取文件特定偏移的数据，然后利用<code>buffo.NewReader</code> 来缓冲读数据，利用 <code>bufio.NewWriter</code> 来缓冲写数据提高效率，最后利用 <code>io.Copy(bw, br)</code> 将文件特定部分复制到新文件中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line">wg.Add(concurrency)</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i &lt; concurrency; i++ &#123;</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(i <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> wg.Done()</span><br><span class="line">        sr := io.NewSectionReader(f, <span class="keyword">int64</span>(i * partSize), <span class="keyword">int64</span>(partSize))</span><br><span class="line">        br := bufio.NewReader(sr)</span><br><span class="line">        partFile, err := os.Create(<span class="string">"partFile_"</span> + strconv.Itoa(i))</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="built_in">panic</span>(err)</span><br><span class="line">        &#125;</span><br><span class="line">        bw := bufio.NewWriter(partFile)</span><br><span class="line">        io.Copy(bw, br)</span><br><span class="line">    &#125;(i)</span><br><span class="line">&#125;</span><br><span class="line">wg.Wait()</span><br></pre></td></tr></table></figure>
-<h2 id="Gluer"><a href="#Gluer" class="headerlink" title="Gluer"></a>Gluer</h2><p>合并与分割互为逆操作，因为我们对上面分割后的文件采取了顺序命名操作，所以可以根据编号的顺序，利用 <code>Seek</code> 方法指定合并文件的写偏移地址，通过 <code>bufio.NewReader</code> 对分割文件进行缓冲读操作，同理利用 <code>bufio.NewWriter</code> 对合并文件进行缓冲写操作，通过 <code>io.Copy(bw, br)</code> 将分割文件放入最终合并文件的正确位置。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">matches, err := filepath.Glob(<span class="string">"partFile_*"</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="built_in">panic</span>(err)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">mergedFile, err := os.Create(<span class="string">"mergedFile"</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="built_in">panic</span>(err)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> _, v := <span class="keyword">range</span> matches &#123;</span><br><span class="line">    ss := strings.Split(v, <span class="string">"_"</span>)</span><br><span class="line">    i, err := strconv.Atoi(ss[<span class="number">1</span>])</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    mergedFile.Seek(<span class="keyword">int64</span>(i * partSize), os.SEEK_SET)</span><br><span class="line">    f, err := os.Open(v)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    br := bufio.NewReader(f)</span><br><span class="line">    bw := bufio.NewWriter(mergedFile)</span><br><span class="line">    io.Copy(bw, br)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/29/ProtocolMultiplexer/index.html b/2018/05/29/ProtocolMultiplexer/index.html
deleted file mode 100644
index b473ab1..0000000
--- a/2018/05/29/ProtocolMultiplexer/index.html
+++ /dev/null
@@ -1,253 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Protocol Multiplexer | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="假设我们要实现一个 RPC 框架并且每个客户端与服务器只维护一根 TCP 连接，但客户端可能会同时发出很多 RPC 请求，服务器收到请求处理后将结果返还给客户端，现在问题来了，由于只有一根 TCP 连接，客户端收到的结果可能是乱序的，我们该如何将请求和答复对应起来呢，如果采取同步的方法倒是不用担心乱序的问题，但是效率肯定非常低，同步导致系统大部分时间在等待 I/O ，为了提高 CPU 的利用率，我">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Protocol Multiplexer">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/29/ProtocolMultiplexer/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="假设我们要实现一个 RPC 框架并且每个客户端与服务器只维护一根 TCP 连接，但客户端可能会同时发出很多 RPC 请求，服务器收到请求处理后将结果返还给客户端，现在问题来了，由于只有一根 TCP 连接，客户端收到的结果可能是乱序的，我们该如何将请求和答复对应起来呢，如果采取同步的方法倒是不用担心乱序的问题，但是效率肯定非常低，同步导致系统大部分时间在等待 I/O ，为了提高 CPU 的利用率，我">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:20.507Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Protocol Multiplexer">
-<meta name="twitter:description" content="假设我们要实现一个 RPC 框架并且每个客户端与服务器只维护一根 TCP 连接，但客户端可能会同时发出很多 RPC 请求，服务器收到请求处理后将结果返还给客户端，现在问题来了，由于只有一根 TCP 连接，客户端收到的结果可能是乱序的，我们该如何将请求和答复对应起来呢，如果采取同步的方法倒是不用担心乱序的问题，但是效率肯定非常低，同步导致系统大部分时间在等待 I/O ，为了提高 CPU 的利用率，我">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ProtocolMultiplexer"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Protocol Multiplexer
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-29T11:50:23.000Z" itemprop="datePublished">
-        May 29, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>假设我们要实现一个 <code>RPC</code> 框架并且每个客户端与服务器只维护一根 <code>TCP</code> 连接，但客户端可能会同时发出很多 <code>RPC</code> 请求，服务器收到请求处理后将结果返还给客户端，现在问题来了，由于只有一根 <code>TCP</code> 连接，客户端收到的结果可能是乱序的，我们该如何将请求和答复对应起来呢，如果采取同步的方法倒是不用担心乱序的问题，但是效率肯定非常低，同步导致系统大部分时间在等待 <code>I/O</code> ，为了提高 <code>CPU</code> 的利用率，我们可以采用多路复用的方法。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ProtocolMux <span class="keyword">interface</span> &#123;</span><br><span class="line">    <span class="comment">// Init initializes the mux to manage messages to the given service.</span></span><br><span class="line">    Init(Service)</span><br><span class="line">    <span class="comment">// Call makes a request with the given message and returns the reply.</span></span><br><span class="line">    <span class="comment">// Multiple goroutines may call Call concurrently.</span></span><br><span class="line">    Call(Msg) Msg</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Service</code> 接口仅仅指明了服务需要实现的接口，这些服务实际就是对网络库的封装，可以是 <code>TCP</code> 或者 <code>UDP</code> ，<code>Send</code> 和 <code>Recv</code> 方法不能在并发条件下使用，并发使用可能会导致数据竞争。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Service <span class="keyword">interface</span> &#123;</span><br><span class="line">    <span class="comment">// ReadTag returns the muxing identifier in the request or reply message.</span></span><br><span class="line">    <span class="comment">// Multiple goroutines may call ReadTag concurrently.</span></span><br><span class="line">    ReadTag(Msg) <span class="keyword">int64</span></span><br><span class="line">    <span class="comment">// Send sends a request message to the remote service.</span></span><br><span class="line">    <span class="comment">// Send must not be called concurrently with itself.</span></span><br><span class="line">    Send(Msg)</span><br><span class="line">    <span class="comment">// Recv waits for and returns a reply mesasge from the remote service.</span></span><br><span class="line">    <span class="comment">// Recv must not be called concurrently with itself.</span></span><br><span class="line">    Recv(Msg)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>实现多路复用的核心就在于使用 <code>pending</code> 这个 <code>map</code> 来存储还未收到答复的请求，每一个请求都有自己独一无二的标签（例如请求的序列号），每个标签对应一个答复，答复用通道 <code>chan Msg</code> 来表示，当收到该标签对应的答复时，该通道返回结果（ <code>&lt;-done</code> ），这样就可以保证请求和答复一一对应，而不用关心接收消息先后顺序的问题了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Mux <span class="keyword">struct</span> &#123;</span><br><span class="line">    srv     Service</span><br><span class="line">    send    <span class="keyword">chan</span> Msg</span><br><span class="line">    mu      sync.Mutex</span><br><span class="line">    pending <span class="keyword">map</span>[<span class="keyword">int64</span>]<span class="keyword">chan</span>&lt;- Msg</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mux)</span> <span class="title">Init</span><span class="params">(srv Service)</span></span> &#123;</span><br><span class="line">    m.srv = srv</span><br><span class="line">    m.pending = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">int64</span>]<span class="keyword">chan</span> Msg)</span><br><span class="line">    <span class="keyword">go</span> m.sendLoop()</span><br><span class="line">    <span class="keyword">go</span> m.recvLoop()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>sendLoop</code> 负责消息的发送，而 <code>recvLoop</code> 则会对接受到的答复进行判断标签操作，并将 <code>pending</code> 中这个标签对应的通道取出，然后向这个通道发消息从而告知对应的 <code>Call</code> 函数该请求已经处理完。这两个方法就是复用机制的体现，因为它们底层只使用一个连接来处理多个请求。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mux)</span> <span class="title">sendLoop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> args := <span class="keyword">range</span> m.send &#123;</span><br><span class="line">        m.srv.Send(args)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mux)</span> <span class="title">recvLoop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        reply := m.srv.Recv()</span><br><span class="line">        tag := m.srv.Tag(reply)</span><br><span class="line">   </span><br><span class="line">        m.mu.Lock()</span><br><span class="line">        done := m.pending[tag]</span><br><span class="line">        m.mu.Unlock()</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> done == <span class="literal">nil</span> &#123;</span><br><span class="line">            <span class="built_in">panic</span>(<span class="string">"unexpected reply"</span>)</span><br><span class="line">        &#125;</span><br><span class="line">        done &lt;- reply</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>对于 <code>Call</code> 方法，整个调用过程是阻塞的，先通过 <code>ReadTag</code> 获取 <code>Msg</code> 的标签，并新建一个通道 <code>done := make(chan Msg, 1)</code> ，作为将来事件完成时的通知。并将该通道存储到 <code>pending</code> 中，通过 <code>m.send &lt;- args</code> 将消息发送到 <code>send</code> 中，<code>sendLoop</code> 会执行真正的发送操作，最后阻塞，等待结果返回（ <code>&lt;-done</code> ）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(m *Mux)</span> <span class="title">Call</span><span class="params">(args Msg)</span> <span class="params">(reply Msg)</span></span> &#123;</span><br><span class="line">    tag := m.srv.ReadTag(args)</span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> Msg, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    m.mu.Lock()</span><br><span class="line">    <span class="keyword">if</span> m.pending[tag] != <span class="literal">nil</span> &#123;</span><br><span class="line">        m.mu.Unlock()</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"mux: duplicate call tag"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    m.pending[tag] = done</span><br><span class="line">    m.mu.Unlock()</span><br><span class="line">    </span><br><span class="line">    m.send &lt;- args</span><br><span class="line">    <span class="keyword">return</span> &lt;-done</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/05/31/MemoryMappedFile/index.html b/2018/05/31/MemoryMappedFile/index.html
deleted file mode 100644
index 0ab0bf9..0000000
--- a/2018/05/31/MemoryMappedFile/index.html
+++ /dev/null
@@ -1,262 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Memory Mapped File | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="内存映射文件( memory mapped file )与磁盘上的文件存在直接的对应关系。内存映射 I/O 将磁盘上的文件映射到用户进程地址空间中，这样，当我们从映射内存中获取字节时，会读取文件的相应字节。同样的，当我们将数据存储在映射内存中时，相应的字节会自动写入文件中。这样以来就可以在不使用 read() 或 write() 系统调用的情况下执行 I/O 操作 。  mmap &amp;amp; mu">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Memory Mapped File">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/05/31/MemoryMappedFile/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="内存映射文件( memory mapped file )与磁盘上的文件存在直接的对应关系。内存映射 I/O 将磁盘上的文件映射到用户进程地址空间中，这样，当我们从映射内存中获取字节时，会读取文件的相应字节。同样的，当我们将数据存储在映射内存中时，相应的字节会自动写入文件中。这样以来就可以在不使用 read() 或 write() 系统调用的情况下执行 I/O 操作 。  mmap &amp;amp; mu">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="http://www.tutorialsdaddy.com/wp-content/uploads/2016/11/linux-mmap.png">
-<meta property="og:image" content="https://cdn.shopify.com/s/files/1/2187/3161/products/450ba4cc5f96d682fde154a5e569ebf4_1024x.png?v=1520446011">
-<meta property="og:updated_time" content="2018-06-26T08:46:55.175Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Memory Mapped File">
-<meta name="twitter:description" content="内存映射文件( memory mapped file )与磁盘上的文件存在直接的对应关系。内存映射 I/O 将磁盘上的文件映射到用户进程地址空间中，这样，当我们从映射内存中获取字节时，会读取文件的相应字节。同样的，当我们将数据存储在映射内存中时，相应的字节会自动写入文件中。这样以来就可以在不使用 read() 或 write() 系统调用的情况下执行 I/O 操作 。  mmap &amp;amp; mu">
-<meta name="twitter:image" content="http://www.tutorialsdaddy.com/wp-content/uploads/2016/11/linux-mmap.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-MemoryMappedFile"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Memory Mapped File
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-05-31T11:05:38.000Z" itemprop="datePublished">
-        May 31, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>内存映射文件( <code>memory mapped file</code> )与磁盘上的文件存在直接的对应关系。内存映射 <code>I/O</code> 将磁盘上的文件映射到用户进程地址空间中，这样，当我们从映射内存中获取字节时，会读取文件的相应字节。同样的，当我们将数据存储在映射内存中时，相应的字节会自动写入文件中。这样以来就可以在不使用 <code>read()</code> 或 <code>write()</code> 系统调用的情况下执行 <code>I/O</code> 操作 。</p>
-<p><img src="http://www.tutorialsdaddy.com/wp-content/uploads/2016/11/linux-mmap.png" alt="mmap"></p>
-<h2 id="mmap-amp-munmap"><a href="#mmap-amp-munmap" class="headerlink" title="mmap &amp; munmap"></a>mmap &amp; munmap</h2><p><code>mmap</code> 系统调用将文件或设备映射到内存中，当调用成功时，它会返回映射内存的起始地址。第一个参数 <code>addr</code> 表示文件要映射到内存中的虚拟地址，一般都为 <code>NULL</code> ，表示由内核决定合适的映射地址。第二个参数 <code>len</code> 指定映射的大小（以字节为单位），通常情况下，内核创建的映射内存的大小是内存页面大小的整数倍。第三个参数 <code>prot</code> 指定访问权限，可以是 <code>PROT_READ</code>，<code>PROT_WRITE</code> ，<code>PROT_EXEC</code> 。第四个参数 <code>flags</code> 可以是 <code>MAP_PRIVATE</code>，<code>MAP_SHARED</code> 。第五个参数 <code>fd</code> 标识映射文件的文件描述符。第六个参数 <code>offset</code> 指定了文件映射的起点。为了映射整个文件，我们将 <code>offset</code> 指定为0，将 <code>len</code> 指定为整个文件的大小。</p>
-<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/mman.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> *</span><br><span class="line">mmap(<span class="keyword">void</span> *addr, <span class="keyword">size_t</span> len, <span class="keyword">int</span> prot, <span class="keyword">int</span> flags, <span class="keyword">int</span> fd, <span class="keyword">off_t</span> offset);</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> </span><br><span class="line">munmap(<span class="keyword">void</span> *addr, <span class="keyword">size_t</span> len);</span><br></pre></td></tr></table></figure>
-<p>Golang中系统调用参数有些许不同，但本质是一样的。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> syscall</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Mmap</span><span class="params">(fd <span class="keyword">int</span>, offset <span class="keyword">int64</span>, length <span class="keyword">int</span>, prot <span class="keyword">int</span>, flags <span class="keyword">int</span>)</span> <span class="params">(data []<span class="keyword">byte</span>, err error)</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">Munmap</span><span class="params">(b []<span class="keyword">byte</span>)</span> <span class="params">(err error)</span></span></span><br></pre></td></tr></table></figure>
-<h2 id="GPIO"><a href="#GPIO" class="headerlink" title="GPIO"></a>GPIO</h2><p>当然了，如果光介绍 <code>mmap</code> 这个系统调用就太无聊了，我们下面来看一下 <code>mmap</code> 能帮助我们干什么事情，如果你玩树莓派的话，我们可以用 <code>mmap</code> 来写一个 <code>GPIO</code> 驱动。</p>
-<p><img src="https://cdn.shopify.com/s/files/1/2187/3161/products/450ba4cc5f96d682fde154a5e569ebf4_1024x.png?v=1520446011" alt="RasberryPi"></p>
-<p>在树莓派的 <code>/dev</code> 目录下存在 <code>mem</code> 和 <code>gpiomem</code> 这两个文件。通过 <code>mmap</code> <code>/dev/gpiomem</code> 文件我们可以在没有 <code>root</code> 权限的情况下访问 <code>GPIO</code> 寄存器。打开 <code>/dev/gpiomem</code> 设备文件并使用 <code>mmap()</code> 函数可将 <code>GPIO</code> 寄存器映射到进程内存空间中去。<code>/dev/mem</code> 代表整个系统的内存空间。<code>/dev/gpiomem</code> 仅允许访问 <code>GPIO</code> 外设寄存器， <code>/dev/mem</code> 允许访问所有外设寄存器以及所有内存，相对来说更加危险。为了保护内存空间，最好使用 <code>/dev/gpiomem</code> 而非 <code>/dev/mem</code> 来控制 <code>GPIO</code> 寄存器。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">          Rev 2 and 3 Raspberry Pi </span><br><span class="line">+-----+---------+----------+---------+-----+</span><br><span class="line">| BCM |   Name  | Physical | Name    | BCM |</span><br><span class="line">+-----+---------+----++----+---------+-----+ </span><br><span class="line">|     |    3.3v |  1 || 2  | 5v      |     |</span><br><span class="line">|   2 |   SDA 1 |  3 || 4  | 5v      |     | </span><br><span class="line">|   3 |   SCL 1 |  5 || 6  | 0v      |     |</span><br><span class="line">|   4 | GPIO  7 |  7 || 8  | TxD     | 14  |</span><br><span class="line">|     |      0v |  9 || 10 | RxD     | 15  | </span><br><span class="line">|  17 | GPIO  0 | 11 || 12 | GPIO  1 | 18  | </span><br><span class="line">|  27 | GPIO  2 | 13 || 14 | 0v      |     |</span><br><span class="line">|  22 | GPIO  3 | 15 || 16 | GPIO  4 | 23  |</span><br><span class="line">|     |    3.3v | 17 || 18 | GPIO  5 | 24  |  </span><br><span class="line">|  10 |    MOSI | 19 || 20 | 0v      |     |  </span><br><span class="line">|   9 |    MISO | 21 || 22 | GPIO  6 | 25  | </span><br><span class="line">|  11 |    SCLK | 23 || 24 | CE0     | 8   |</span><br><span class="line">|     |      0v | 25 || 26 | CE1     | 7   | </span><br><span class="line">|   0 |   SDA 0 | 27 || 28 | SCL 0   | 1   | </span><br><span class="line">|   5 | GPIO 21 | 29 || 30 | 0v      |     |</span><br><span class="line">|   6 | GPIO 22 | 31 || 32 | GPIO 26 | 12  |</span><br><span class="line">|  13 | GPIO 23 | 33 || 34 | 0v      |     |</span><br><span class="line">|  19 | GPIO 24 | 35 || 36 | GPIO 27 | 16  |</span><br><span class="line">|  26 | GPIO 25 | 37 || 38 | GPIO 28 | 20  |</span><br><span class="line">|     |      0v | 39 || 40 | GPIO 29 | 21  |</span><br><span class="line">+-----+---------+----++----+---------+-----+</span><br></pre></td></tr></table></figure>
-<p>如果通过 <code>/dev/mem</code> 访问 <code>GPIO</code> 外设寄存器，那么我们需要确定其内存中的基地址，我们通过读取 <code>/proc/device-tree/soc/ranges</code> 来确定基地址。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    bcm2835Base = <span class="number">0x20000000</span></span><br><span class="line">    gpioOffset  = <span class="number">0x200000</span></span><br><span class="line">    memLength = <span class="number">4096</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> gpioBase <span class="keyword">int64</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    memLock sync.Mutex</span><br><span class="line">    gpioMem  []<span class="keyword">byte</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">init</span><span class="params">()</span></span> &#123;</span><br><span class="line">    base := getBase()</span><br><span class="line">    gpioBase = base + gpioOffset </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getBase</span><span class="params">()</span> <span class="params">(base <span class="keyword">int64</span>)</span></span> &#123;</span><br><span class="line">    base = bcm2835Base</span><br><span class="line">    ranges, err := os.Open(<span class="string">"/proc/device-tree/soc/ranges"</span>)</span><br><span class="line">    <span class="keyword">defer</span> ranges.Close()</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">4</span>)</span><br><span class="line">    n, err := ranges.ReadAt(b, <span class="number">4</span>)</span><br><span class="line">    <span class="keyword">if</span> n != <span class="number">4</span> || err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    buf := bytes.NewReader(b)</span><br><span class="line">    <span class="keyword">var</span> out <span class="keyword">uint32</span></span><br><span class="line">    err = binary.Read(buf, binary.BigEndian, &amp;out)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">int64</span>(out)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p> <code>Open</code> 函数通过映射 <code>/dev/mem</code> 文件来将 <code>GPIO</code> 寄存器映射到内存中，这样以来我们就可以通过直接改变 <code>gpioMem</code> 的值来操控 <code>GPIO</code> 寄存器了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Open</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="comment">// Open fd for rw mem access; try dev/mem first (need root)</span></span><br><span class="line">    file, err := os.OpenFile(<span class="string">"/dev/mem"</span>, os.O_RDWR|os.O_SYNC, <span class="number">0</span>)</span><br><span class="line">    <span class="keyword">if</span> os.IsPermission(err) &#123;</span><br><span class="line">        <span class="comment">// try gpiomem otherwise (some extra functions like clock and pwm setting wont work)</span></span><br><span class="line">        file, err = os.OpenFile(<span class="string">"/dev/gpiomem"</span>, os.O_RDWR|os.O_SYNC, <span class="number">0</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// FD can be closed after memory mapping</span></span><br><span class="line">    <span class="keyword">defer</span> file.Close()</span><br><span class="line"></span><br><span class="line">    memLock.Lock()</span><br><span class="line">    <span class="keyword">defer</span> memLock.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Memory map GPIO registers to slice</span></span><br><span class="line">    gpioMem, err = syscall.Mmap(</span><br><span class="line">        <span class="keyword">int</span>(file.Fd()),</span><br><span class="line">        gpioBase,</span><br><span class="line">        memLength,</span><br><span class="line">        syscall.PROT_READ|syscall.PROT_WRITE,</span><br><span class="line">        syscall.MAP_SHARED,</span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Close</code> 函数使用 <code>syscall.Munmap</code> 系统调用来解除内存映射。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Close</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    memLock.Lock()</span><br><span class="line">    <span class="keyword">defer</span> memLock.Unlock()</span><br><span class="line">    <span class="keyword">if</span> err := syscall.Munmap(mem); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/01/Semaphore/index.html b/2018/06/01/Semaphore/index.html
deleted file mode 100644
index ee6c446..0000000
--- a/2018/06/01/Semaphore/index.html
+++ /dev/null
@@ -1,250 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Semaphore | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="现在要完成一个非常简单的任务，给定很多图片的 URL ，将它们下载到本地，你会怎么做？ Sequential如果你想也不想，就写下了下面这种代码，说明你是一个能干活的程序员，但这并不意味着你是一个优秀的程序员。下面的代码虽然没有什么致命的错误，但是效率非常低，程序运行时 CPU 大部分时间都在等待网络 I/O 而处于空闲状态，导致 CPU 的利用率非常低。 12345for idx, task :">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Semaphore">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/01/Semaphore/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="现在要完成一个非常简单的任务，给定很多图片的 URL ，将它们下载到本地，你会怎么做？ Sequential如果你想也不想，就写下了下面这种代码，说明你是一个能干活的程序员，但这并不意味着你是一个优秀的程序员。下面的代码虽然没有什么致命的错误，但是效率非常低，程序运行时 CPU 大部分时间都在等待网络 I/O 而处于空闲状态，导致 CPU 的利用率非常低。 12345for idx, task :">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:01.794Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Semaphore">
-<meta name="twitter:description" content="现在要完成一个非常简单的任务，给定很多图片的 URL ，将它们下载到本地，你会怎么做？ Sequential如果你想也不想，就写下了下面这种代码，说明你是一个能干活的程序员，但这并不意味着你是一个优秀的程序员。下面的代码虽然没有什么致命的错误，但是效率非常低，程序运行时 CPU 大部分时间都在等待网络 I/O 而处于空闲状态，导致 CPU 的利用率非常低。 12345for idx, task :">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Semaphore"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Semaphore
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-01T13:07:44.000Z" itemprop="datePublished">
-        Jun 1, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>现在要完成一个非常简单的任务，给定很多图片的 <code>URL</code> ，将它们下载到本地，你会怎么做？</p>
-<h2 id="Sequential"><a href="#Sequential" class="headerlink" title="Sequential"></a>Sequential</h2><p>如果你想也不想，就写下了下面这种代码，说明你是一个能干活的程序员，但这并不意味着你是一个优秀的程序员。下面的代码虽然没有什么致命的错误，但是效率非常低，程序运行时 <code>CPU</code> 大部分时间都在等待网络 <code>I/O</code> 而处于空闲状态，导致 <code>CPU</code> 的利用率非常低。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> idx, task := <span class="keyword">range</span> tasks &#123;</span><br><span class="line">    <span class="keyword">if</span> err := Do(idx, task); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Parallel"><a href="#Parallel" class="headerlink" title="Parallel"></a>Parallel</h2><p>这种完全由相互独立的子任务组成的任务，被称为 <em>embarrassingly parallel</em> ，这种问题可以通过并行的方法提高程序的性能，而且并行程度越高，性能越好，在程序中我们通过添加 <code>go</code> 这个关键字来创建多个 <code>goroutine</code> ，使多个子任务并发执行，以减少网络 <code>I/O</code> 延迟，提高 <code>CPU</code> 的利用率 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line"><span class="keyword">for</span> idx, task := <span class="keyword">range</span> tasks &#123;</span><br><span class="line">    wg.Add(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(i <span class="keyword">int</span>, v <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> wg.Done()</span><br><span class="line">        <span class="keyword">if</span> err := Do(i, v); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            fmt.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;(idx, task)</span><br><span class="line">&#125;</span><br><span class="line">wg.Wait()</span><br></pre></td></tr></table></figure>
-<h2 id="Parallel-with-Semaphore"><a href="#Parallel-with-Semaphore" class="headerlink" title="Parallel with Semaphore"></a>Parallel with Semaphore</h2><p>但是通过创建多个 <code>goroutine</code> 提高并行度从而提高性能的方法有其局限性，例如一次性创建过多的网络连接，超出了进程打开文件的数量限制时，程序就会报错。所以我们需要限制单位时间内并行程序的个数，通过信号量（ <code>semaphore</code> ）来限制并行度。在 <code>golang</code> 中，我们可以使用容量为 n 的 <code>buffered channel</code> 来模拟 <code>counting semaphore</code> ，这样以来在每个子任务执行前需要通过 <code>sem &lt;- struct{}{}</code> 来获取执行许可，如果 <code>sem</code> 通道已满，说明当前已经有n个子任务正在执行，该操作就会阻塞等待，直到通道空闲。当任务执行完成后，使用 <code>&lt;-sem</code> 释放执行许可。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">sem := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, <span class="number">8</span>) <span class="comment">// 8 jobs at once</span></span><br><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line"><span class="keyword">for</span> idx, task := <span class="keyword">range</span> tasks &#123;</span><br><span class="line">    wg.Add(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(i <span class="keyword">int</span>, v <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> wg.Done()</span><br><span class="line">        sem &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">        <span class="keyword">if</span> err := Do(i, v); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            fmt.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">        &lt;-sem</span><br><span class="line">    &#125;(idx, task)</span><br><span class="line">&#125;</span><br><span class="line">wg.Wait()</span><br><span class="line"><span class="built_in">close</span>(sem)</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/02/ReplicatedServiceClient/index.html b/2018/06/02/ReplicatedServiceClient/index.html
deleted file mode 100644
index 2873e31..0000000
--- a/2018/06/02/ReplicatedServiceClient/index.html
+++ /dev/null
@@ -1,247 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Replicated Service Client | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Self-explanatory :-)Actually cause I feel lazy today. 1234567891011type ReplicatedClient interface &amp;#123;    // Init initializes the client to use the given servers.    // To make a particular request">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Replicated Service Client">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/02/ReplicatedServiceClient/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Self-explanatory :-)Actually cause I feel lazy today. 1234567891011type ReplicatedClient interface &amp;#123;    // Init initializes the client to use the given servers.    // To make a particular request">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:13.702Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Replicated Service Client">
-<meta name="twitter:description" content="Self-explanatory :-)Actually cause I feel lazy today. 1234567891011type ReplicatedClient interface &amp;#123;    // Init initializes the client to use the given servers.    // To make a particular request">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ReplicatedServiceClient"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Replicated Service Client
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-02T07:01:00.000Z" itemprop="datePublished">
-        Jun 2, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>Self-explanatory :-)<br>Actually cause I feel lazy today.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ReplicatedClient <span class="keyword">interface</span> &#123;</span><br><span class="line">    <span class="comment">// Init initializes the client to use the given servers.</span></span><br><span class="line">    <span class="comment">// To make a particular request later,</span></span><br><span class="line">    <span class="comment">// the client can use callOne(srv, args), where srv </span></span><br><span class="line">    <span class="comment">// is one of the servers from the list</span></span><br><span class="line">    Init(servers []<span class="keyword">string</span>, callOne(<span class="keyword">string</span>, Args) Reply)</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// Call makes a request to an available server.</span></span><br><span class="line">    <span class="comment">// Multiple gouroutines may call Call concurrently.</span></span><br><span class="line">    Call(args Args) Reply </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Client <span class="keyword">struct</span> &#123;</span><br><span class="line">    servers []<span class="keyword">string</span></span><br><span class="line">    callOne <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">string</span>, Args)</span> <span class="title">Reply</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">    <span class="title">mu</span> <span class="title">sync</span>.<span class="title">Mutex</span></span></span><br><span class="line"><span class="function">    <span class="title">prefer</span> <span class="title">int</span></span></span><br><span class="line"><span class="function">&#125;</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(c *Client)</span> <span class="title">Init</span><span class="params">(servers []<span class="keyword">string</span>, callOne <span class="keyword">func</span>(<span class="keyword">string</span>, Args)</span> <span class="title">Reply</span>)</span> &#123;</span><br><span class="line">    c.servers = servers</span><br><span class="line">    c.callOne = callOne</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Client)</span> <span class="title">Call</span><span class="params">(args Args)</span> <span class="title">Reply</span></span> &#123;</span><br><span class="line">    <span class="keyword">type</span> result <span class="keyword">struct</span> &#123;</span><br><span class="line">        serverID <span class="keyword">int</span></span><br><span class="line">        reply Reply</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> timeout = <span class="number">1</span> * time.Second</span><br><span class="line">    t := time.NewTimer(timeout)</span><br><span class="line">    <span class="keyword">defer</span> t.Stop()</span><br><span class="line"></span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> result, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    c.mu.Lock()</span><br><span class="line">    prefer := c.prefer</span><br><span class="line">    c.mu.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> r result</span><br><span class="line">    <span class="keyword">for</span> off := <span class="number">0</span>; off &lt; <span class="built_in">len</span>(c.servers); off++ &#123;</span><br><span class="line">        id := (prefer + off) % <span class="built_in">len</span>(c.servers)</span><br><span class="line">        <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">            done &lt;- result&#123;id, c.callOne(c.servers[id], args)&#125;</span><br><span class="line">        &#125;()</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> r = &lt;-done:</span><br><span class="line">            goro Done</span><br><span class="line">        <span class="keyword">case</span> &lt;-t.C:</span><br><span class="line">            t.Reset(timeout)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">Done:</span><br><span class="line">    c.mu.Lock()</span><br><span class="line">    c.prefer = r.serverID</span><br><span class="line">    c.mu.Unlock()</span><br><span class="line">    <span class="keyword">return</span> r.reply  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/03/Raft/index.html b/2018/06/03/Raft/index.html
deleted file mode 100644
index 04a0a9e..0000000
--- a/2018/06/03/Raft/index.html
+++ /dev/null
@@ -1,330 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Raft | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Raft stands for Replicated and Fault Tolerant Raft is something you can build out of a collection of logs Raft is something you can use to get away from the island of Paxos  Goal: Replicated Log Repl">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Raft">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/03/Raft/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Raft stands for Replicated and Fault Tolerant Raft is something you can build out of a collection of logs Raft is something you can use to get away from the island of Paxos  Goal: Replicated Log Repl">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:15.739Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Raft">
-<meta name="twitter:description" content="Raft stands for Replicated and Fault Tolerant Raft is something you can build out of a collection of logs Raft is something you can use to get away from the island of Paxos  Goal: Replicated Log Repl">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Raft"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Raft
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-03T12:59:23.000Z" itemprop="datePublished">
-        Jun 3, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <ul>
-<li>Raft stands for Replicated and Fault Tolerant</li>
-<li>Raft is something you can build out of a collection of logs</li>
-<li>Raft is something you can use to get away from the island of Paxos</li>
-</ul>
-<h2 id="Goal-Replicated-Log"><a href="#Goal-Replicated-Log" class="headerlink" title="Goal: Replicated Log"></a>Goal: Replicated Log</h2><ul>
-<li>Replicated log =&gt; replicated state machine<ul>
-<li>All servers execute same commands in same order</li>
-</ul>
-</li>
-<li>Consensus module ensures proper log replication</li>
-<li>System makes progress as long as any majority of servers are up</li>
-<li>Failure model: fail-stop(not Byzantine), delayed/lost messages    </li>
-</ul>
-<h2 id="Approaches-to-Consensus"><a href="#Approaches-to-Consensus" class="headerlink" title="Approaches to Consensus"></a>Approaches to Consensus</h2><p>Two possible approaches to consensus:</p>
-<ul>
-<li>Symmetric, leader-less:<ul>
-<li>All servers have equal roles</li>
-<li>Clients can contact any server </li>
-</ul>
-</li>
-<li>Asymmetric, leader-based:<ul>
-<li>At any given time, one server is in charge, others accept its decision</li>
-<li>Clients communicate with the leader </li>
-</ul>
-</li>
-<li>Raft uses a leader:<ul>
-<li>Decomposes the problem (normal operation, leader changes)</li>
-<li>Simplifies normal operation (no conflicts)</li>
-<li>More efficient than leader-less approaches  </li>
-</ul>
-</li>
-</ul>
-<h2 id="Leader-Election"><a href="#Leader-Election" class="headerlink" title="Leader Election"></a>Leader Election</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">                  +------------------+</span><br><span class="line">                  | Become Candidate |</span><br><span class="line">                  +------------------+</span><br><span class="line">                           |</span><br><span class="line">                           v</span><br><span class="line">                   +---------------+    timeout</span><br><span class="line">                   | currentTerm++ |&lt;--------------+</span><br><span class="line">                   | vote for self |               |</span><br><span class="line">                   +---------------+               |</span><br><span class="line">                           |                       |</span><br><span class="line">                           v                       |</span><br><span class="line">               +-----------------------+           |</span><br><span class="line">               | Send RequestVote RPCs |-----------+</span><br><span class="line">               |    to other servers   |</span><br><span class="line">               +-----------------------+</span><br><span class="line">votes from majority |              | RPC from Leader</span><br><span class="line">                    v              v</span><br><span class="line">           +----------------+  +---------+</span><br><span class="line">           | Become Leader, |  | Become  |</span><br><span class="line">           | send heartbeats|  | Follower|</span><br><span class="line">           +----------------+  +---------+</span><br></pre></td></tr></table></figure>
-<ul>
-<li>Safety: allow at most one winner per term<ul>
-<li>Each server gives only one vote per term(persist on disk)</li>
-<li>Majority required to win election</li>
-</ul>
-</li>
-</ul>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">   B can&apos;t also                  Voted for</span><br><span class="line">   get majority                candidate A</span><br><span class="line">+-----------------+     +-------------------------+</span><br><span class="line">| +-----+ +-----+ |     | +-----+ +-----+ +-----+ |     </span><br><span class="line">| |     | |     | |     | |     | |     | |     | | </span><br><span class="line">| +-----+ +-----+ |     | +-----+ +-----+ +-----+ |</span><br><span class="line">+-----------------+     +-------------------------+</span><br><span class="line">                  Servers</span><br></pre></td></tr></table></figure>
-<ul>
-<li>Livebess: some candidate must eventually win<ul>
-<li>Choose election timeout randomly in [T, 2T] (e.g. 150-300ms)</li>
-<li>One server usually times out and wins election before others time out</li>
-<li>Works well if T &gt;&gt; broadcast time</li>
-</ul>
-</li>
-</ul>
-<p>Randomized approach simpler than ranking</p>
-<h2 id="Normal-Operation"><a href="#Normal-Operation" class="headerlink" title="Normal Operation"></a>Normal Operation</h2><ul>
-<li>Client sends command to leader</li>
-<li>Leader appends command to its log</li>
-<li>Leader send AppendEntries RPCs to all followers</li>
-<li>Once new entry committed<ul>
-<li>Leader executes command in its state machine, returns result to client</li>
-<li>Leader notifies followers of committed entries in subsequent AppendEntries RPCs</li>
-<li>Followers execute committed commands in their state machines  </li>
-</ul>
-</li>
-<li>Crashed/slow followers<ul>
-<li>Leader retries AppendEntries RPCs until they succeed</li>
-</ul>
-</li>
-<li>Optimal performance in common case:<ul>
-<li>One successful RPC to any majority of servers</li>
-</ul>
-</li>
-</ul>
-<h2 id="Log-Structure"><a href="#Log-Structure" class="headerlink" title="Log Structure"></a>Log Structure</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Command <span class="keyword">string</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Log <span class="keyword">struct</span> &#123;</span><br><span class="line">    Term <span class="keyword">int</span></span><br><span class="line">    Command Command</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Logs []Log</span><br></pre></td></tr></table></figure>
-<ul>
-<li>Must survive crashes (store on disk)</li>
-<li>Entry committed if safe to execute in state machines<ul>
-<li>Replicated on majority of servers by leader of its term</li>
-</ul>
-</li>
-</ul>
-<h2 id="Log-Inconsistencies"><a href="#Log-Inconsistencies" class="headerlink" title="Log Inconsistencies"></a>Log Inconsistencies</h2><p>Crashes can result in log inconsistencies</p>
-<ul>
-<li>Raft minimizes special code for repairing inconsistencies<ul>
-<li>Leader assumes its log is correct</li>
-<li>Normal operation will repair all inconsistencies </li>
-</ul>
-</li>
-</ul>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/05/MagicNumber/index.html b/2018/06/05/MagicNumber/index.html
deleted file mode 100644
index ff36fac..0000000
--- a/2018/06/05/MagicNumber/index.html
+++ /dev/null
@@ -1,251 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Magic Number | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="微笑.jpg，这里年轻人们聊天时经常使用的说法，但是！作为一个严谨的程序员，我们能不能通过文件的后缀来判断这个文件的类型呢？例如看到电脑上存在“微笑.jpg”这个文件，通过后缀 jpg 来判断它就是一个 JPEG 文件呢，答案肯定是否定的，因为文件名可以被轻松篡改，例如这个文件本来是“微笑.gif”，有人想不开就将它改成“微笑.jpg”，虽然没有什么影响，但是可以说明一个问题，我们不能通过文件后缀">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Magic Number">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/05/MagicNumber/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="微笑.jpg，这里年轻人们聊天时经常使用的说法，但是！作为一个严谨的程序员，我们能不能通过文件的后缀来判断这个文件的类型呢？例如看到电脑上存在“微笑.jpg”这个文件，通过后缀 jpg 来判断它就是一个 JPEG 文件呢，答案肯定是否定的，因为文件名可以被轻松篡改，例如这个文件本来是“微笑.gif”，有人想不开就将它改成“微笑.jpg”，虽然没有什么影响，但是可以说明一个问题，我们不能通过文件后缀">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:46:45.861Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Magic Number">
-<meta name="twitter:description" content="微笑.jpg，这里年轻人们聊天时经常使用的说法，但是！作为一个严谨的程序员，我们能不能通过文件的后缀来判断这个文件的类型呢？例如看到电脑上存在“微笑.jpg”这个文件，通过后缀 jpg 来判断它就是一个 JPEG 文件呢，答案肯定是否定的，因为文件名可以被轻松篡改，例如这个文件本来是“微笑.gif”，有人想不开就将它改成“微笑.jpg”，虽然没有什么影响，但是可以说明一个问题，我们不能通过文件后缀">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-MagicNumber"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Magic Number
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-05T08:27:07.000Z" itemprop="datePublished">
-        Jun 5, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>微笑.jpg，这里年轻人们聊天时经常使用的说法，但是！作为一个严谨的程序员，我们能不能通过文件的后缀来判断这个文件的类型呢？例如看到电脑上存在“微笑.jpg”这个文件，通过后缀 <code>jpg</code> 来判断它就是一个 <code>JPEG</code> 文件呢，答案肯定是否定的，因为文件名可以被轻松篡改，例如这个文件本来是“微笑.gif”，有人想不开就将它改成“微笑.jpg”，虽然没有什么影响，但是可以说明一个问题，我们不能通过文件后缀来判断文件的类型。</p>
-<p>如果不使用文件后缀，我们应该如何判断文件的类型呢，答案就是我们今天要讨论的<code>Magic Number</code> ，即魔术数，因为文件的本质就是字节数组，所以在一般的操作系统中，对于特定类型的文件，其开头的几个字节都是相同的，例如对于 <code>JPEG</code> 格式的文件，开头的字节都是 <code>\xff\xd8\xff</code> ，我们可以通过读取文件开头的字节来确定文件的类型，这种方法准确性更高。</p>
-<p>下面我们准备一个魔术数到类型的字典，注意，这里只列举了几个例子，还可以按照这样的格式增加字典项。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> magicNumber = <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span> &#123;</span><br><span class="line">    <span class="string">"\xff\xd8\xff"</span>:      <span class="string">"image/jpeg"</span>,</span><br><span class="line">    <span class="string">"\x89PNG\r\n\x1a\n"</span>: <span class="string">"image/png"</span>,</span><br><span class="line">    <span class="string">"GIF87a"</span>:            <span class="string">"image/gif"</span>,</span><br><span class="line">    <span class="string">"GIF89a"</span>:            <span class="string">"image/gif"</span>,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getFileType</span><span class="params">(incipit []<span class="keyword">byte</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    incipitStr := <span class="keyword">string</span>(incipit)</span><br><span class="line">    <span class="keyword">for</span> magic, mime := <span class="keyword">range</span> magicNumber &#123;</span><br><span class="line">        <span class="keyword">if</span> strings.HasPrefix(incipitStr, magic) &#123;</span><br><span class="line">            <span class="keyword">return</span> mime</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">""</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>真正匹配格式的逻辑比较简单，遍历 <code>magicNumber</code> 这个 <code>map</code> ，判断每个 <code>key</code> 是不是某个字符串的前缀，因为魔术数符合前缀编码的特点，即任何一个编码都不是另一个编码的前缀，所以我们能保证判断文件类型时，不会有二义。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    filepath := os.Args[<span class="number">1</span>]</span><br><span class="line">    file, err := os.Open(filepath)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> file.Close()</span><br><span class="line"></span><br><span class="line">    buff := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">512</span>)</span><br><span class="line">    _, err = file.Read(buff)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    file.Seek(<span class="number">0</span>, os.SEEK_SET)</span><br><span class="line">    typ := getFileType(buff)</span><br><span class="line">    fmt.Println(typ)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="gate-upload"><a href="#gate-upload" class="headerlink" title="gate upload"></a>gate upload</h2><p>下面我们来看一个 <code>Magic Number</code> 的应用场景，例如我们有一个图片上传程序，但是只能允许上传 <code>JPEG</code> 格式的文件，给定一个 <code>io.Reader</code> ， 我们先读取前两个字节，判断其值是否等于 <code>JPEG</code> 的 <code>Magic Number</code> ，如果不等，则直接停止上传，如果相等，则继续上传。由于此时 <code>r</code> 已经读取了两个字节了，所以需要重新构造一个 <code>io.Reader</code>（ <code>r := io.MultiReader(bytes.NewReader(b), r)</code> ）继续上传。利用 <code>Magic Number</code> 我们可以避免将整个文件读入内存中，增加程序的运行效率。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handleUpload</span><span class="params">(r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">2</span>)</span><br><span class="line">    _, err := r.Read(b)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    jpeg := []<span class="keyword">byte</span>&#123;<span class="number">0xFF</span>, <span class="number">0xD8</span>&#125;</span><br><span class="line">    <span class="keyword">if</span> bytes.Equal(b, jprg) &#123;</span><br><span class="line">        <span class="keyword">return</span> error.New(<span class="string">"not a JPEG"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    r := io.MultiReader(bytes.NewReader(b), r)</span><br><span class="line"></span><br><span class="line">    err = uploadFile(r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/06/bitcoin/index.html b/2018/06/06/bitcoin/index.html
deleted file mode 100644
index 4d0a437..0000000
--- a/2018/06/06/bitcoin/index.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>bitcoin | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="如果有时光机的话，我要做的第一件事情肯定就是穿梭回过去买比特币：），算了，不意淫了，还是学习要紧，虽然再也不能靠买比特币一夜暴富了，但是自己按照比特币实现一个山寨比特币的能力还是有的，比特币可以说是现在大红大紫的区块链的始祖，要全部了解它的原理可能还是要埋头啃个几个月的（并不简单）。 虽然比特币交易确认时间长，消耗资源多，但依旧无法掩盖其作为区块链始祖的光环。  Block &amp;amp; Block">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="bitcoin">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/06/bitcoin/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="如果有时光机的话，我要做的第一件事情肯定就是穿梭回过去买比特币：），算了，不意淫了，还是学习要紧，虽然再也不能靠买比特币一夜暴富了，但是自己按照比特币实现一个山寨比特币的能力还是有的，比特币可以说是现在大红大紫的区块链的始祖，要全部了解它的原理可能还是要埋头啃个几个月的（并不简单）。 虽然比特币交易确认时间长，消耗资源多，但依旧无法掩盖其作为区块链始祖的光环。  Block &amp;amp; Block">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://cdn-images-1.medium.com/max/1600/1*_RY4v9D5-BOVMzFMr8Dk4A.png">
-<meta property="og:updated_time" content="2018-06-26T08:43:51.798Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="bitcoin">
-<meta name="twitter:description" content="如果有时光机的话，我要做的第一件事情肯定就是穿梭回过去买比特币：），算了，不意淫了，还是学习要紧，虽然再也不能靠买比特币一夜暴富了，但是自己按照比特币实现一个山寨比特币的能力还是有的，比特币可以说是现在大红大紫的区块链的始祖，要全部了解它的原理可能还是要埋头啃个几个月的（并不简单）。 虽然比特币交易确认时间长，消耗资源多，但依旧无法掩盖其作为区块链始祖的光环。  Block &amp;amp; Block">
-<meta name="twitter:image" content="https://cdn-images-1.medium.com/max/1600/1*_RY4v9D5-BOVMzFMr8Dk4A.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-bitcoin"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      bitcoin
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-06T14:19:02.000Z" itemprop="datePublished">
-        Jun 6, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>如果有时光机的话，我要做的第一件事情肯定就是穿梭回过去买比特币：），算了，不意淫了，还是学习要紧，虽然再也不能靠买比特币一夜暴富了，但是自己按照比特币实现一个山寨比特币的能力还是有的，比特币可以说是现在大红大紫的区块链的始祖，要全部了解它的原理可能还是要埋头啃个几个月的（并不简单）。</p>
-<p>虽然比特币交易确认时间长，消耗资源多，但依旧无法掩盖其作为区块链始祖的光环。</p>
-<p><img src="https://cdn-images-1.medium.com/max/1600/1*_RY4v9D5-BOVMzFMr8Dk4A.png" alt="bitcoin"></p>
-<h2 id="Block-amp-BlockChain"><a href="#Block-amp-BlockChain" class="headerlink" title="Block &amp; BlockChain"></a>Block &amp; BlockChain</h2><p>比特币中有两个重要的基本概念，区块和区块链，如果将区块想象成珍珠，那么区块链就是将这些珍珠都串起来的珍珠项链，这个珍珠项链没有尽头，新加入的珍珠和次新的珍珠彼此靠近，并通过某种关系紧密联系在一起，牢不可破。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Block <span class="keyword">struct</span> &#123;</span><br><span class="line">    idx        <span class="keyword">int</span></span><br><span class="line">    timestamp  <span class="keyword">string</span></span><br><span class="line">    hash       <span class="keyword">string</span></span><br><span class="line">    prevHash   <span class="keyword">string</span></span><br><span class="line">    difficulty <span class="keyword">int</span></span><br><span class="line">    nonce      <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> BlockChain <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Mutex</span><br><span class="line">    blocks []Block</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(bc *BlockChain)</span> <span class="title">AddBlock</span><span class="params">(block Block)</span></span> &#123;</span><br><span class="line">    bc.Lock()</span><br><span class="line">    <span class="keyword">defer</span> bc.Unlock()</span><br><span class="line">    bc.blocks = <span class="built_in">append</span>(bc.blocks, block)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> blockchain BlockChain</span><br></pre></td></tr></table></figure>
-<h2 id="Proof-of-Work"><a href="#Proof-of-Work" class="headerlink" title="Proof of Work"></a>Proof of Work</h2><p>生成区块的过程就相当于打磨珍珠的过程，只有符合要求的珍珠才能最终被加入到珍珠项链中去，那么话说回来生成区块的过程是怎么样的呢，对于一个特定的区块，需要不断改变其中一个值（nonce），这里的 <code>nonce</code> 值从0开始逐渐递增，然后计算特定 <code>nonce</code> 对应的区块哈希值，只有哈希值符合相应的要求之后，才能说这个区块是有效的，才能被加入到区块链中，生成区块的过程也被叫做挖矿。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">generateBlock</span><span class="params">(oldBlock Block, difficulty <span class="keyword">int</span>)</span> <span class="title">Block</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> newBlock Block</span><br><span class="line"></span><br><span class="line">    newBlock.idx = oldBlock.idx + <span class="number">1</span></span><br><span class="line">    newBlock.timestamp = time.Now().String()</span><br><span class="line">    newBlock.prevHash = oldBlock.hash</span><br><span class="line">	  newBlock.difficulty = diff</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; ; i++ &#123;</span><br><span class="line">        hex := fmt.Sprintf(<span class="string">"%x"</span>, i)</span><br><span class="line">        newBlock.nonce = hex</span><br><span class="line">        <span class="keyword">if</span> !isHashValid(calculateHash(newBlock), newBlock.difficulty) &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            fmt.Println(calculateHash(newBlock), <span class="string">" work done!"</span>)</span><br><span class="line">            newBlock.Hash = calculateHash(newBlock)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> newBlock</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">calculateHash</span><span class="params">(block Block)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    record := strconv.Itoa(block.idx) + block.timestamp + block.prevHash + block.difficulty + block.nonce</span><br><span class="line">    h := sha256.New()</span><br><span class="line">    h.Write([]<span class="keyword">byte</span>(record))</span><br><span class="line">    hashed := h.Sum(<span class="literal">nil</span>)</span><br><span class="line">    <span class="keyword">return</span> hex.EncodeToString(hashed)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>那么什么样的区块才是有效的呢，简单来说就是对于一个哈希值，其开头部分都是0就可以了（0越多，难度越高）。像这种，找到答案很困难但验证答案却非常轻松的算法就是 <code>Proof of Work</code> 的精髓。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">isHashValid</span><span class="params">(hash <span class="keyword">string</span>, difficulty <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    prefix := strings.Repeat(<span class="string">"0"</span>, difficulty)</span><br><span class="line">    <span class="keyword">return</span> strings.HasPrefix(hash, prefix)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="一个难度逐渐递增的区块链"><a href="#一个难度逐渐递增的区块链" class="headerlink" title="一个难度逐渐递增的区块链"></a>一个难度逐渐递增的区块链</h2><p>下面实现了一个难度逐渐递增的区块链，运行时就会发现产生区块的时间间隔越来越长，因为 <code>CPU</code> 需要经过更多的计算才能找到符合条件的哈希值。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    difficulty := <span class="number">1</span></span><br><span class="line">    genesisBlock := Block&#123;&#125;</span><br><span class="line">    genesisBlock = Block&#123;</span><br><span class="line">        idx:        <span class="number">0</span>, </span><br><span class="line">        timestamp:  time.Now().String(), </span><br><span class="line">        hash:       calculateHash(genesisBlock),</span><br><span class="line">        prevHash:   <span class="string">""</span>, </span><br><span class="line">        difficulty: difficulty, </span><br><span class="line">        nonce:      <span class="string">""</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    blockchain.AddBlock(genesisBlock)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> block Block</span><br><span class="line">    block = genesisBlock</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        block = generateBlock(block, diff)</span><br><span class="line">        difficulty++</span><br><span class="line">        blockchain.AddBlock(block)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/11/ChatChatChat/index.html b/2018/06/11/ChatChatChat/index.html
deleted file mode 100644
index b9f2cc2..0000000
--- a/2018/06/11/ChatChatChat/index.html
+++ /dev/null
@@ -1,253 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Chat Chat Chat | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="承认吧，你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈，却还是没有发现合适的人的时候，今天我们就来写一个随机配对聊天程序，解决广大单身狗寂寞时想要找人聊天的需求吧。 为了让聊天不那么 gay ，我们的聊天程序会让异性匹配聊天，用户通过客户端连接到聊天程序服务器 localhost:8080 ，例如使用 netcat 通过 nc localhost 8080 命令连接聊天程序服务器，服务器会根据你">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Chat Chat Chat">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/11/ChatChatChat/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="承认吧，你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈，却还是没有发现合适的人的时候，今天我们就来写一个随机配对聊天程序，解决广大单身狗寂寞时想要找人聊天的需求吧。 为了让聊天不那么 gay ，我们的聊天程序会让异性匹配聊天，用户通过客户端连接到聊天程序服务器 localhost:8080 ，例如使用 netcat 通过 nc localhost 8080 命令连接聊天程序服务器，服务器会根据你">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:44:07.665Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Chat Chat Chat">
-<meta name="twitter:description" content="承认吧，你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈，却还是没有发现合适的人的时候，今天我们就来写一个随机配对聊天程序，解决广大单身狗寂寞时想要找人聊天的需求吧。 为了让聊天不那么 gay ，我们的聊天程序会让异性匹配聊天，用户通过客户端连接到聊天程序服务器 localhost:8080 ，例如使用 netcat 通过 nc localhost 8080 命令连接聊天程序服务器，服务器会根据你">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-ChatChatChat"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Chat Chat Chat
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-11T07:09:34.000Z" itemprop="datePublished">
-        Jun 11, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>承认吧，你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈，却还是没有发现合适的人的时候，今天我们就来写一个随机配对聊天程序，解决广大单身狗寂寞时想要找人聊天的需求吧。</p>
-<p>为了让聊天不那么 <code>gay</code> ，我们的聊天程序会让异性匹配聊天，用户通过客户端连接到聊天程序服务器 <code>localhost:8080</code> ，例如使用 <code>netcat</code> 通过 <code>nc localhost 8080</code> 命令连接聊天程序服务器，服务器会根据你的性别匹配异性聊天。</p>
-<p>在实现方面，为了达到异性相互聊天的目标，我们创建两个通道，分别是 <code>boy</code> 通道和 <code>girl</code> 通道，并通过 <code>net.Listen</code> 方法监听 <code>8080</code> 端口，对于每个连接我们起一个 <code>goroutine</code> 进行匹配操作。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> boy = <span class="built_in">make</span>(<span class="keyword">chan</span> io.ReadWriteCloser)</span><br><span class="line"><span class="keyword">var</span> girl = <span class="built_in">make</span>(<span class="keyword">chan</span> io.ReadWriteCloser)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    l, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">"localhost:8080"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        c, err := l.Accept()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">go</span> match(c)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>match</code> 方法会首先询问你的性别，如果是男生则匹配女生聊天，反之亦然。如果当前只有一个男生连进来，程序会执行第一个 <code>select</code> 中的 <code>case boy &lt;- c:</code> 条件，由于 <code>boy</code> 通道是 <code>unbuffered channel</code> ，直到有女生进来之前该操作都会阻塞。如果此时进来一个女生，程序会执行第二个<code>select</code> 操作，由于 <code>girl</code> 通道也是 <code>unbuffered channel</code> ，所以<code>case girl &lt;- c:</code> 语句也会阻塞，但此时 <code>case p := &lt;-boy:</code> 会被执行，这时候就可以通过 <code>chat</code> 方法让两个 <code>net.Conn</code> 相互交流了。<code>match</code> 方法实现的逻辑就达到了异性交流的目的了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">match</span><span class="params">(c io.ReadWriteCloser)</span></span> &#123;</span><br><span class="line">    fmt.Fprint(c, <span class="string">"Are you a boy or a girl? "</span>)</span><br><span class="line">    <span class="keyword">var</span> sex <span class="keyword">string</span></span><br><span class="line">    fmt.Fscanln(c, &amp;sex)</span><br><span class="line">    <span class="keyword">if</span> strings.HasPrefix(<span class="string">"boy"</span>, sex) &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> boy &lt;- c: </span><br><span class="line">        <span class="keyword">case</span> p := &lt;-girl:</span><br><span class="line">            chat(p, c)</span><br><span class="line">        &#125;     </span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> strings.HasPrefix(<span class="string">"girl"</span>, sex) &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> girl &lt;- c:</span><br><span class="line">        <span class="keyword">case</span> p := &lt;-boy:</span><br><span class="line">            chat(p, c)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上面的 <code>chat</code> 方法依赖 <code>cp</code> 方法 ，该方法封装了 <code>io.Copy</code> 方法，主要就是为了当任意一方结束聊天时发送一个 <code>err</code> 到我们的 <code>errc</code> ，以关闭双方的连接。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">cp</span><span class="params">(w io.Writer, r io.Reader, errc <span class="keyword">chan</span>&lt;- error)</span></span> &#123;</span><br><span class="line">    _, err := io.Copy(w, r)</span><br><span class="line">    errc &lt;- err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>chat</code> 方法通过两个 <code>goroutine</code> ，<code>go cp(a, b, errc)</code>  和 <code>go cp(b, a, errc)</code> 使a和b这两个 <code>net.Conn</code> 相互发送消息，如果任意一方结束聊天， <code>errc</code> 通道就会返回一个 <code>error</code> 值，a和b就会被关闭，此时聊天结束。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">chat</span><span class="params">(a, b io.ReadWriteCloser)</span></span> &#123;</span><br><span class="line">    fmt.Fprintln(a, <span class="string">"Found one! say hi"</span>)</span><br><span class="line">    fmt.Fprintln(b, <span class="string">"Found one! say hi"</span>)</span><br><span class="line">    errc := <span class="built_in">make</span>(<span class="keyword">chan</span> error, <span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> cp(a, b, errc) </span><br><span class="line">    <span class="keyword">go</span> cp(b, a, errc)</span><br><span class="line">    <span class="keyword">if</span> err := &lt;- errc; err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">    a.Close()</span><br><span class="line">    b.Close()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/12/Calculate24/index.html b/2018/06/12/Calculate24/index.html
deleted file mode 100644
index 32e57d1..0000000
--- a/2018/06/12/Calculate24/index.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Calculate 24 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="算24点还是挺考验一个人的心算能力的，作为一个数学比较差劲的人，每次和别人玩24点总是会慢一个节拍，可以说是非常伤自尊了。不过虽然心算算不过别人，我们可以写一个自动计算24点的程序和别人比嘛，嘻嘻。 expression tree 我们可以利用表达式树来确定运算的优先级，进而确定运算的顺序，表达式树属于二叉树，其叶结点存储运算数（ val ），非叶子结点存储运算符 op （ +，-，*，/ ）及运">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Calculate 24">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/12/Calculate24/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="算24点还是挺考验一个人的心算能力的，作为一个数学比较差劲的人，每次和别人玩24点总是会慢一个节拍，可以说是非常伤自尊了。不过虽然心算算不过别人，我们可以写一个自动计算24点的程序和别人比嘛，嘻嘻。 expression tree 我们可以利用表达式树来确定运算的优先级，进而确定运算的顺序，表达式树属于二叉树，其叶结点存储运算数（ val ），非叶子结点存储运算符 op （ +，-，*，/ ）及运">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Exp-tree-ex-11.svg/500px-Exp-tree-ex-11.svg.png">
-<meta property="og:updated_time" content="2018-06-26T08:44:01.357Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Calculate 24">
-<meta name="twitter:description" content="算24点还是挺考验一个人的心算能力的，作为一个数学比较差劲的人，每次和别人玩24点总是会慢一个节拍，可以说是非常伤自尊了。不过虽然心算算不过别人，我们可以写一个自动计算24点的程序和别人比嘛，嘻嘻。 expression tree 我们可以利用表达式树来确定运算的优先级，进而确定运算的顺序，表达式树属于二叉树，其叶结点存储运算数（ val ），非叶子结点存储运算符 op （ +，-，*，/ ）及运">
-<meta name="twitter:image" content="https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Exp-tree-ex-11.svg/500px-Exp-tree-ex-11.svg.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Calculate24"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Calculate 24
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-12T06:53:49.000Z" itemprop="datePublished">
-        Jun 12, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>算24点还是挺考验一个人的心算能力的，作为一个数学比较差劲的人，每次和别人玩24点总是会慢一个节拍，可以说是非常伤自尊了。不过虽然心算算不过别人，我们可以写一个自动计算24点的程序和别人比嘛，嘻嘻。</p>
-<h2 id="expression-tree"><a href="#expression-tree" class="headerlink" title="expression tree"></a>expression tree</h2><p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Exp-tree-ex-11.svg/500px-Exp-tree-ex-11.svg.png" alt="ExpressionTree"></p>
-<p>我们可以利用表达式树来确定运算的优先级，进而确定运算的顺序，表达式树属于二叉树，其叶结点存储运算数（ <code>val</code> ），非叶子结点存储运算符 <code>op</code> （ <code>+，-，*，/</code> ）及运算结果（ <code>val = l.val op r.val</code> ）。每个节点都有指向其左子节点（ <code>l</code> ）和右子节点（ <code>r</code> ）的指针，叶节点中这两个指针均为空。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> node <span class="keyword">struct</span> &#123;</span><br><span class="line">    l    *node</span><br><span class="line">    r    *node</span><br><span class="line">    op   <span class="keyword">rune</span></span><br><span class="line">    val  <span class="keyword">float64</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *node)</span> <span class="title">set</span><span class="params">(l, r *node, op <span class="keyword">rune</span>)</span></span> &#123;</span><br><span class="line">    n.l  = l</span><br><span class="line">    n.r  = r</span><br><span class="line">    n.op = op</span><br><span class="line">    <span class="keyword">switch</span> op &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'+'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val + n.r.val)</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'-'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val - n.r.val)</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'*'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val * n.r.val)</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'/'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val / n.r.val)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *node)</span> <span class="title">String</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n.op != <span class="keyword">rune</span>(<span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> fmt.Sprintf(<span class="string">" %c "</span>, n.op)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"%d"</span>, <span class="keyword">int</span>(n.val))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="build-tree"><a href="#build-tree" class="headerlink" title="build tree"></a>build tree</h2><p>由于存在运算优先级的原因，所以在运算数和运算符都相同的情况下当其运算顺序不同时得出的表达式树的形态也不同，例如 <code>(1 + 8) * (7 - 13)</code>  与 <code>1 + 8 * 7 - 13</code> 的运算顺序是不同的，<code>(1 + 8) * (7 - 13)</code>  对应的是下面第一棵树的形态， <code>1 + 8 * 7 - 13</code> 对应的是下面第四棵树的形态。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">    x               x               x                x               x</span><br><span class="line">   / \             / \             / \              / \             / \</span><br><span class="line">  x   x           x   x           x   x            x   x           x   x</span><br><span class="line"> / \ / \             / \             / \          / \             / \</span><br><span class="line">x  x x  x           x   x           x   x        x   x           x   x</span><br><span class="line">                   / \                 / \          / \         / \</span><br><span class="line">                  x   x               x   x        x   x       x   x</span><br></pre></td></tr></table></figure>
-<p>为了得出所有的可能结果，我们需要构建所有不同形态的表达式树，<code>buildAllTrees</code> 利用递归方法来建树，例如给定 <code>3，4，5，6</code> 这四个数，可以构建出上面5种形态的树。 <code>3，4，5，6</code> 作为参数传入，然后将数组分割为两个部分，例如上面的 <code>3，4，5，6</code> 可以分割为 <code>3</code> 和 <code>4，5，6</code> 或者 <code>3，4</code> 和 <code>5，6</code> 或者 <code>3，4，5</code> 和 <code>6</code> ，然后对这两个部分分别再进行递归建树操作，当数组长度为1时也就是当 <code>len(s) == 1</code> 作为递归函数退出的条件，此时返回一个叶节点，按照这样的方式最终可以得到所有可能形态的树的根节点。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">buildAllTrees</span><span class="params">(s []<span class="keyword">int</span>)</span> []*<span class="title">node</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(s) == <span class="number">1</span> &#123;</span><br><span class="line">       tree := &amp;node&#123;result: <span class="keyword">float64</span>(s[<span class="number">0</span>])&#125;</span><br><span class="line">       <span class="keyword">return</span> []*node&#123;tree&#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    treelist := []*node&#123;&#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="built_in">len</span>(s); i++ &#123;</span><br><span class="line">        left := s[:i]</span><br><span class="line">        right := s[i:]</span><br><span class="line">        leftTrees := buildAllTrees(left)</span><br><span class="line">        rightTrees := buildAllTrees(right)</span><br><span class="line">        <span class="keyword">for</span> _, l := <span class="keyword">range</span> leftTrees &#123;</span><br><span class="line">            <span class="keyword">for</span> _, r := <span class="keyword">range</span> rightTrees &#123;</span><br><span class="line">                combinedTree := build(l, r)</span><br><span class="line">                treelist = <span class="built_in">append</span>(treelist, combinedTree...)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> treelist</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>因为存在四种运算符，例如利用 <code>a</code> 和 <code>b</code> 这两个节点构建树的时候，可以有 <code>a+b</code> ， <code>a-b</code> ， <code>a*b</code> ， <code>a/b</code> 这四种可能，所以要分别列举。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">build</span><span class="params">(l, r *node)</span> []*<span class="title">node</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> list []*node</span><br><span class="line">    tree1 := &amp;node&#123;&#125;</span><br><span class="line">    tree1.set(l, r, <span class="string">'+'</span>)</span><br><span class="line">    list = <span class="built_in">append</span>(list, tree1)</span><br><span class="line">    tree2 := &amp;node&#123;&#125;</span><br><span class="line">    tree2.set(l, r, <span class="string">'-'</span>)</span><br><span class="line">    list = <span class="built_in">append</span>(list, tree2)</span><br><span class="line">    tree3 := &amp;node&#123;&#125;</span><br><span class="line">    tree3.set(l, r, <span class="string">'*'</span>)</span><br><span class="line">    list = <span class="built_in">append</span>(list, tree3)</span><br><span class="line">    <span class="keyword">if</span> r.result != <span class="number">0.0</span> &#123;</span><br><span class="line">        tree4 := &amp;node&#123;&#125;</span><br><span class="line">        tree4.set(l, r, <span class="string">'/'</span>)</span><br><span class="line">        list = <span class="built_in">append</span>(list, tree4)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> list</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>我们可以通过中序遍历表达式树来遍历输出构建的表达式，由于上面我们定义了每个节点的 <code>String</code> 方法，如果节点为运算符，则输出其 <code>op</code> 的值，如果节点为叶结点，则输出其 <code>val</code> 值。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">in</span><span class="params">(root *node)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> n.op != <span class="keyword">rune</span>(<span class="number">0</span>) &#123;</span><br><span class="line">        fmt.Print(<span class="string">"("</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    in(root.l)</span><br><span class="line">    fmt.Print(n.String())</span><br><span class="line">    in(root.r)</span><br><span class="line">    <span class="keyword">if</span> n.op != <span class="keyword">rune</span>(<span class="number">0</span>) &#123;</span><br><span class="line">        fmt.Print(<span class="string">")"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="permutation"><a href="#permutation" class="headerlink" title="permutation"></a>permutation</h2><p>上面的方法是对一个数组其固定的顺序构建表达式树，例如 <code>3，4，5，6</code> 。为了获得所有的运算表达式，我们需要对数组的所有排列组合进行表达式树的构建，例如对 <code>6，5，4，3</code> ，<code>5，6，4，3</code> 这样的排列组合构建表达式树。也就是说除了树形态不同的这点区别之外，还要注意叶结点值存储顺序不同的带来的可能（可能会导致重复）。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Perm</span><span class="params">(a []<span class="keyword">int</span>, f <span class="keyword">func</span>([]<span class="keyword">int</span>)</span>)</span> &#123;</span><br><span class="line">    perm(a, f, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">perm</span><span class="params">(a []<span class="keyword">int</span>, f <span class="keyword">func</span>([]<span class="keyword">int</span>)</span>, <span class="title">i</span> <span class="title">int</span>)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> i &gt; <span class="built_in">len</span>(a) &#123;</span><br><span class="line">        f(a)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    perm(a, f, i+<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">for</span> j := i + <span class="number">1</span>; j &lt; <span class="built_in">len</span>(a); j++ &#123;</span><br><span class="line">        a[i], a[j] = a[j], a[i]</span><br><span class="line">        perm(a, f, i+<span class="number">1</span>)</span><br><span class="line">        a[i], a[j] = a[j], a[i]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="main"><a href="#main" class="headerlink" title="main"></a>main</h2><p>在主函数中我们每隔五秒钟获得一个随机的扑克牌数字，然后对于该组数字所有的排列组合分别构建表达式树，对每棵构建好的树判断其根节点的值是否接近于24（由于涉及到除法操作，所以有小数点），如果接近，则将其表达式通过中序遍历输出，这样就可以得出一组数字所有24点的可能了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        s := rand24()</span><br><span class="line">        fmt.Println(s)</span><br><span class="line">        Perm(s, <span class="function"><span class="keyword">func</span><span class="params">(a []<span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">            treelist := buildAllTrees(a)</span><br><span class="line">            <span class="keyword">for</span> _, root := <span class="keyword">range</span> treelist &#123;</span><br><span class="line">                <span class="keyword">if</span> math.Abs(<span class="number">24</span>-tree.result) &lt; <span class="number">0.000001</span> &#123;</span><br><span class="line">                    in(root)</span><br><span class="line">                    fmt.Println()</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">        time.Sleep(<span class="number">5</span> * time.Second)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">rand24</span><span class="params">()</span> <span class="params">(r []<span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    rand.Seed(time.Now().UnixNano())</span><br><span class="line"></span><br><span class="line">    club    := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    heart   := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    spade   := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    diamond := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> all []<span class="keyword">int</span></span><br><span class="line">    all = <span class="built_in">append</span>(all, spade...)</span><br><span class="line">    all = <span class="built_in">append</span>(all, heart...)</span><br><span class="line">    all = <span class="built_in">append</span>(all, diamond...)</span><br><span class="line">    all = <span class="built_in">append</span>(all, club...)</span><br><span class="line"></span><br><span class="line">    r = <span class="built_in">make</span>([]<span class="keyword">int</span>, <span class="number">4</span>)</span><br><span class="line"></span><br><span class="line">    exist = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            x := rand.Int() % <span class="built_in">len</span>(all)</span><br><span class="line">            <span class="keyword">if</span> !exist[x] &#123;</span><br><span class="line">                exist[x] = <span class="literal">true</span></span><br><span class="line">                r[i] = all[x]</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/13/Ligatures/index.html b/2018/06/13/Ligatures/index.html
deleted file mode 100644
index d4a7023..0000000
--- a/2018/06/13/Ligatures/index.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Ligatures | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="!!! From: https://github.com/tonsky/FiraCode !!! problemProgrammers use a lot of symbols, often encoded with several characters. For the human brain, sequences like -&amp;gt;, &amp;lt;= or := are single logic">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Ligatures">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/13/Ligatures/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="!!! From: https://github.com/tonsky/FiraCode !!! problemProgrammers use a lot of symbols, often encoded with several characters. For the human brain, sequences like -&amp;gt;, &amp;lt;= or := are single logic">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://github.com/tonsky/FiraCode/raw/master/showcases/all_ligatures.png">
-<meta property="og:image" content="https://github.com/tonsky/FiraCode/raw/master/showcases/go.png">
-<meta property="og:image" content="https://github.com/tonsky/FiraCode/raw/master/showcases/swift.png">
-<meta property="og:image" content="https://github.com/tonsky/FiraCode/raw/master/showcases/ruby.png">
-<meta property="og:image" content="https://github.com/tonsky/FiraCode/raw/master/showcases/javascript.png">
-<meta property="og:updated_time" content="2018-06-26T08:46:37.189Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Ligatures">
-<meta name="twitter:description" content="!!! From: https://github.com/tonsky/FiraCode !!! problemProgrammers use a lot of symbols, often encoded with several characters. For the human brain, sequences like -&amp;gt;, &amp;lt;= or := are single logic">
-<meta name="twitter:image" content="https://github.com/tonsky/FiraCode/raw/master/showcases/all_ligatures.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Ligatures"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Ligatures
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-13T05:20:38.000Z" itemprop="datePublished">
-        Jun 13, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>!!! From: <code>https://github.com/tonsky/FiraCode</code> !!!</p>
-<h2 id="problem"><a href="#problem" class="headerlink" title="problem"></a>problem</h2><p>Programmers use a lot of symbols, often encoded with several characters. For the human brain, sequences like -&gt;, &lt;= or := are single logical tokens, even if they take two or three characters on the screen. Your eye spends a non-zero amount of energy to scan, parse and join multiple characters into a single logical one. Ideally, all programming languages should be designed with full-fledged Unicode symbols for operators, but that’s not the case yet.</p>
-<p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/all_ligatures.png" alt="all_ligatures"></p>
-<h2 id="installation"><a href="#installation" class="headerlink" title="installation"></a>installation</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> brew tap caskroom/fonts</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> brew cask install font-fira-code</span></span><br></pre></td></tr></table></figure>
-<h2 id="visual-studio-code"><a href="#visual-studio-code" class="headerlink" title="visual studio code"></a>visual studio code</h2><p>Add <code>&quot;editor.fontLigatures&quot;: true</code> to <code>settings.json</code> :</p>
-<p>To open <code>settings.json</code> , from the File menu choose Preferences, Settings or use keyboard shortcut  <code>Cmd</code> + <code>,</code> . Then paste the following lines and save the file.</p>
-<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"editor.fontFamily"</span>: <span class="string">"Fira Code"</span>,</span><br><span class="line"><span class="string">"editor.fontLigatures"</span>: <span class="literal">true</span></span><br></pre></td></tr></table></figure>
-<h2 id="what-it-looks-like"><a href="#what-it-looks-like" class="headerlink" title="what it looks like"></a>what it looks like</h2><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/go.png" alt="go"></p>
-<h3 id="Swift"><a href="#Swift" class="headerlink" title="Swift"></a>Swift</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/swift.png" alt="swift"></p>
-<h3 id="Ruby"><a href="#Ruby" class="headerlink" title="Ruby"></a>Ruby</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/ruby.png" alt="ruby"></p>
-<h3 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/javascript.png" alt="js"></p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/14/TimingWheel/index.html b/2018/06/14/TimingWheel/index.html
deleted file mode 100644
index 26d3f2c..0000000
--- a/2018/06/14/TimingWheel/index.html
+++ /dev/null
@@ -1,259 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Timing Wheel | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="当我们自己编写服务端程序时候，可能需要新建大量的定时器，对每个 TCP 连接设置连接超时，面对成千上万的客户端连接，如果傻傻地为每一个连接分配一个计时器的话，那么 10k 个连接就对应 10k 的计时器，10w 个连接就对应 10w 个计时器，这种方法显然是比较消耗内存的。 对于需要大量定时器的情况，由于许多定时器是在相近的时间超时的，或者说在一个时间范围内到时的，如果对时间精度没有那么近乎苛刻">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Timing Wheel">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/14/TimingWheel/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="当我们自己编写服务端程序时候，可能需要新建大量的定时器，对每个 TCP 连接设置连接超时，面对成千上万的客户端连接，如果傻傻地为每一个连接分配一个计时器的话，那么 10k 个连接就对应 10k 的计时器，10w 个连接就对应 10w 个计时器，这种方法显然是比较消耗内存的。 对于需要大量定时器的情况，由于许多定时器是在相近的时间超时的，或者说在一个时间范围内到时的，如果对时间精度没有那么近乎苛刻">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://www.confluent.io/wp-content/uploads/2016/08/TimingWheels1.png">
-<meta property="og:updated_time" content="2018-06-26T08:47:39.796Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Timing Wheel">
-<meta name="twitter:description" content="当我们自己编写服务端程序时候，可能需要新建大量的定时器，对每个 TCP 连接设置连接超时，面对成千上万的客户端连接，如果傻傻地为每一个连接分配一个计时器的话，那么 10k 个连接就对应 10k 的计时器，10w 个连接就对应 10w 个计时器，这种方法显然是比较消耗内存的。 对于需要大量定时器的情况，由于许多定时器是在相近的时间超时的，或者说在一个时间范围内到时的，如果对时间精度没有那么近乎苛刻">
-<meta name="twitter:image" content="https://www.confluent.io/wp-content/uploads/2016/08/TimingWheels1.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-TimingWheel"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Timing Wheel
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-14T01:20:25.000Z" itemprop="datePublished">
-        Jun 14, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><img src="https://www.confluent.io/wp-content/uploads/2016/08/TimingWheels1.png" alt="timingwheel"></p>
-<p>当我们自己编写服务端程序时候，可能需要新建大量的定时器，对每个 <code>TCP</code> 连接设置连接超时，面对成千上万的客户端连接，如果傻傻地为每一个连接分配一个计时器的话，那么 <code>10k</code> 个连接就对应 <code>10k</code> 的计时器，<code>10w</code> 个连接就对应 <code>10w</code> 个计时器，这种方法显然是比较消耗内存的。</p>
-<p>对于需要大量定时器的情况，由于许多定时器是在相近的时间超时的，或者说在一个时间范围内到时的，如果对时间精度没有那么近乎苛刻的要求的话，我们可以利用这个特性将多个同一时间段的计时器整合成一个来使用，这样的话就可以极大程度上降低内存的消耗，例如现在有 <code>3，4，5，6</code> 四个连接，它们均会在后面的3到4秒内超时，我们可以采用一种方法使它们共用一个计数器，并当时间点到来时，它们均可以被通知到。</p>
-<h2 id="closed-channel"><a href="#closed-channel" class="headerlink" title="closed channel"></a>closed channel</h2><p>也就是说，我们需要一个机制来重复利用某一个计时器，换句话说，当时间点到来时，我们需要一种广播的机制让等待该计时器的都能被通知到。</p>
-<p>为此需要利用 <code>golang</code> 中通道的几个特性，我们通过一个例子来理解一下，在下面的函数中 <code>make</code> 了一个 <code>unbuffered channel</code> ch，还新起了3个 <code>goroutine</code> ，每个<code>goroutine</code> 会执行 <code>fmt.Println(&quot;start &quot;, i)</code> ，但等它们都执行到 <code>&lt;-ch</code> 语句时，由于没有其他 <code>goroutine</code> 执行 <code>ch &lt;- struct{}{}</code> 操作，所以3个 <code>goroutine</code> 都会阻塞，当 <code>time.Sleep(1 * time.Second)</code> 结束时，我们利用 <code>close(ch)</code> ，此操作相当于向每个 <code>goroutine</code> 进行 <code>ch &lt;- struct{}{}</code> ，此时阻塞解除，每个 <code>goroutine</code> 都可以继续执行 <code>fmt.Println(&quot;end &quot;, i)</code> 。也就是说 <code>close(ch)</code> 相当于一个广播操作。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    ch := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="number">3</span>; i++ &#123;</span><br><span class="line">        i := i</span><br><span class="line">        <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">            fmt.Println(<span class="string">"start "</span>, i)</span><br><span class="line">            &lt;-ch</span><br><span class="line">            fmt.Println(<span class="string">"end "</span>, i)</span><br><span class="line">        &#125;()</span><br><span class="line">    &#125;</span><br><span class="line">    time.Sleep(<span class="number">1</span> * time.Second)</span><br><span class="line">    <span class="built_in">close</span>(ch)</span><br><span class="line">    <span class="keyword">select</span> &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>上面的例子利用到了通道的的第一个特性和第三个特性。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. The expression blocks until a value is available. </span><br><span class="line">2. Receiving from a nil channel blocks forever. </span><br><span class="line">3. A receive operation on a closed channel can always proceed immediately, yielding the element type’s zero value after any previously sent values have been received.</span><br></pre></td></tr></table></figure>
-<h2 id="timing-wheel"><a href="#timing-wheel" class="headerlink" title="timing wheel"></a>timing wheel</h2><p>那么上面的例子和我们要实现的东西有什么联系呢，其实联系非常大，我们可以给每一个需要进行定时操作的 <code>goroutine</code> 一个 <code>unbuffered channel</code><br>，并且给予在相同时间点超时的 <code>goroutine</code> 以同样的通道。然后我们自己维护一个 <code>ticker</code> ，这个 <code>ticker</code> 每隔固定的时间，将相应的通道关闭，这相当于一个广播操作，这样每个等待此广播的 <code>goroutine</code> 都会收到消息，也就可以继续执行下去了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> TimingWheel <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Mutex</span><br><span class="line"></span><br><span class="line">    interval   time.Duration</span><br><span class="line">    maxTimeout time.Duration </span><br><span class="line">    </span><br><span class="line">    ticker     *time.Ticker</span><br><span class="line">    cs         []<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    pos        <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line">    stop       <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(interval time.Duration, buckets <span class="keyword">int</span>)</span> *<span class="title">TimingWheel</span></span> &#123;</span><br><span class="line">    w := &amp;TimingWheel&#123;</span><br><span class="line">        interval:   interval,</span><br><span class="line">        maxTimeout: interval * time.Duration(buckets),</span><br><span class="line">        ticker:     time.NewTicker(interval),</span><br><span class="line">        cs :        <span class="built_in">make</span>([]<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, buckets),</span><br><span class="line">        pos:        <span class="number">0</span>,</span><br><span class="line">        stop:       <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;),</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> w.cs &#123;</span><br><span class="line">        w.cs[i] = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">go</span> w.run()</span><br><span class="line">    <span class="keyword">return</span> w</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>光说可能有一点抽象，下面我们来看一下具体的实现，<code>TimingWheel</code> 结构体相当于模拟一个秒表，其中的 <code>ticker</code> 就相当于一个秒针，同时我们还维护了一个通道数组 <code>cs</code> （其存储结构为顺序存储，而其逻辑结构则是一个圆环），作为定时器使用，<code>ticker</code> 每隔固定的 <code>interval</code> ，会让指针向前移动一个单位（ <code>pos++</code> ），并将该位置存储的通道关闭，也就相同于定时器返回，这种方法实现的定时器相对来说增加了定时器的利用率，降低了内存的消耗。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">run</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> &lt;-w.ticker.C:</span><br><span class="line">            w.tick()</span><br><span class="line">        <span class="keyword">case</span> &lt;-w.stop:</span><br><span class="line">            w.ticker.Stop()</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">tick</span><span class="params">()</span></span> &#123;</span><br><span class="line">    w.Lock()</span><br><span class="line">    last := w.cs[w.pos]</span><br><span class="line">    w.cs[w.pos] = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">     </span><br><span class="line">    w.pos = (w.pos + <span class="number">1</span>) % <span class="built_in">len</span>(w.cs)</span><br><span class="line">    w.Unlock()    </span><br><span class="line">    <span class="built_in">close</span>(last)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>After</code> 方法为我们提供一个定时器，如果 <code>timeout</code> 数值太大无法落在 <code>timing wheel</code> 的一个周期的时间范围内，则报错，如果 <code>timeout</code> 在正常范围内，则返回对应位置的通道，当该通道超时时，上面的 <code>tick</code> 方法就会将该通道关闭，相应的 <code>goroutine</code> 就可以收到通知了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">After</span><span class="params">(timeout time.Duration)</span> &lt;-<span class="title">chan</span> <span class="title">struct</span></span> &#123;&#125; &#123;</span><br><span class="line">    <span class="keyword">if</span> timeout &gt;= w.maxTimeout &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"timeout too long"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    idx := <span class="keyword">int</span>(timeout / w.interval)</span><br><span class="line">    <span class="keyword">if</span> idx &gt; <span class="number">0</span> &#123;</span><br><span class="line">        idx--</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    w.Lock()</span><br><span class="line">    idx = (w.pos + idx) % <span class="built_in">len</span>(w.cs)</span><br><span class="line">    b := w.cs[idx]</span><br><span class="line">    w.Unlock()</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">return</span> b</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">Stop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="built_in">close</span>(w.exit)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/15/Snappy/index.html b/2018/06/15/Snappy/index.html
deleted file mode 100644
index 0b55fd4..0000000
--- a/2018/06/15/Snappy/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Snappy | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Snappy 是 Google 开发的压缩和解压缩的库，最初使用 C++ 编写，后来又造了一个 golang 版本的轮子。由于目前该压缩算法还没有放到 go 的标准库中去，所以需要通过 go get -u github.com/golang/snappy 安装。 与其他常见的压缩算法相比，Snappy 存在的目的并不是为了获得最大程度的压缩比，正如其名字所言，它旨在保持合理的压缩比的同时最大限度地">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Snappy">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/15/Snappy/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Snappy 是 Google 开发的压缩和解压缩的库，最初使用 C++ 编写，后来又造了一个 golang 版本的轮子。由于目前该压缩算法还没有放到 go 的标准库中去，所以需要通过 go get -u github.com/golang/snappy 安装。 与其他常见的压缩算法相比，Snappy 存在的目的并不是为了获得最大程度的压缩比，正如其名字所言，它旨在保持合理的压缩比的同时最大限度地">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:49.515Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Snappy">
-<meta name="twitter:description" content="Snappy 是 Google 开发的压缩和解压缩的库，最初使用 C++ 编写，后来又造了一个 golang 版本的轮子。由于目前该压缩算法还没有放到 go 的标准库中去，所以需要通过 go get -u github.com/golang/snappy 安装。 与其他常见的压缩算法相比，Snappy 存在的目的并不是为了获得最大程度的压缩比，正如其名字所言，它旨在保持合理的压缩比的同时最大限度地">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Snappy"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Snappy
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-15T09:00:01.000Z" itemprop="datePublished">
-        Jun 15, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><code>Snappy</code> 是 <code>Google</code> 开发的压缩和解压缩的库，最初使用 <code>C++</code> 编写，后来又造了一个 <code>golang</code> 版本的轮子。由于目前该压缩算法还没有放到 <code>go</code> 的标准库中去，所以需要通过 <code>go get -u github.com/golang/snappy</code> 安装。</p>
-<p>与其他常见的压缩算法相比，<code>Snappy</code> 存在的目的并不是为了获得最大程度的压缩比，正如其名字所言，它旨在保持合理的压缩比的同时最大限度地提高压缩和解压缩的速度。</p>
-<p><code>Snappy</code> 对数据处理速度上做了很大的优化，但它并不是没有缺点，相对于其他算法来说，<code>Snappy</code> 压缩得到的文件体积会更大一点。如果你更在意压缩速度而不是压缩比的话，<code>Snappy</code> 可能会是一个很好的选择。</p>
-<h2 id="compression"><a href="#compression" class="headerlink" title="compression"></a>compression</h2><p>下面，我们对比一下 <code>Snappy</code> 压缩算法和其他两种常见的压缩算法（ <code>zlib</code> 和 <code>gzip</code> ）的性能。首先，我们定一个 <code>Compressor</code> 接口，并使 <code>Zlib</code> ，<code>Gzip</code> 和 <code>Snappy</code> 这三个结构体均实现它。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Zlib <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"><span class="keyword">type</span> Gzip <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"><span class="keyword">type</span> Snappy <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Compressor <span class="keyword">interface</span> &#123;</span><br><span class="line">    Compress(io.Writer, io.Reader) error</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="zlib"><a href="#zlib" class="headerlink" title="zlib"></a>zlib</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(_ *Zlib)</span> <span class="title">Compress</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    zw, err := zlib.NewWriterLevel(w, zlib.BestSpeed)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> zw.Close()</span><br><span class="line"></span><br><span class="line">    _, err = io.Copy(zw, r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="gzip"><a href="#gzip" class="headerlink" title="gzip"></a>gzip</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(_ *Gzip)</span> <span class="title">Compress</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> gw.Close()</span><br><span class="line"></span><br><span class="line">    _, err = io.Copy(gw, r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="snappy"><a href="#snappy" class="headerlink" title="snappy"></a>snappy</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(_ *Snappy)</span> <span class="title">compress</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    sw := snappy.NewBufferedWriter(w)</span><br><span class="line">    <span class="keyword">defer</span> sw.Close()</span><br><span class="line"></span><br><span class="line">    _, err := io.Copy(sw, r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="performance"><a href="#performance" class="headerlink" title="performance"></a>performance</h2><p>对于压缩的性能，可以从压缩比和压缩时间这两点进行衡量。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    f, err := os.Open(<span class="string">"somebigfile"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fGzip, _ := os.Create(<span class="string">"gzip"</span>)</span><br><span class="line">    fZlib, _ := os.Create(<span class="string">"zlib"</span>)</span><br><span class="line">    fSnappy, _ := os.Create(<span class="string">"snappy"</span>)</span><br><span class="line"></span><br><span class="line">    cs := <span class="keyword">map</span>[compressor]io.Writer&#123;</span><br><span class="line">        &amp;Gzip&#123;&#125;:   fGzip,</span><br><span class="line">        &amp;Zlib&#123;&#125;:   fZlib,</span><br><span class="line">        &amp;Snappy&#123;&#125;: fSnappy,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> c, v := <span class="keyword">range</span> cs &#123;</span><br><span class="line">        t := time.Now()</span><br><span class="line">        err := c.compress(v, f)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            fmt.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">        d := time.Since(t)</span><br><span class="line">        fmt.Printf(<span class="string">"method: %s, time spend: %.02f, ratio: %.05f%%\n"</span>, </span><br><span class="line">        v.Name(), </span><br><span class="line">        d.Seconds(), </span><br><span class="line">        compressionRatio(f, v))</span><br><span class="line">        f.Seek(<span class="number">0</span>, <span class="number">0</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">compressionRatio</span><span class="params">(f1, f2 *os.File)</span> <span class="title">float64</span></span> &#123;</span><br><span class="line">    f1s, _ := f1.Stat()</span><br><span class="line">    f1size := f1s.Size()</span><br><span class="line">    f2s, _ := f2.Stat()</span><br><span class="line">    f2size := f2s.Size()</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">float64</span>(f2size) / <span class="keyword">float64</span>(f1size) * <span class="number">100</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Snappy</code> 在速度上来说比 <code>zlib</code> 和 <code>gzip</code> 快得多，但文件相对要大 <code>20%</code> 到 <code>100%</code>。在 <code>64</code> 位模式的 <code>Core i7</code> 处理器上，<code>Snappy</code> 可以达到 <code>250~500</code> 兆每秒的压缩速度，可以说是非常惊人了。 </p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ go run main.go</span><br><span class="line">method:   gzip, time spend: 8.38s, ratio:  7.576%</span><br><span class="line">method:   zlib, time spend: 9.13s, ratio:  7.576%</span><br><span class="line">method: snappy, time spend: 1.96s, ratio: 18.813%</span><br></pre></td></tr></table></figure>
-<p>相比其他的压缩库，<code>Snappy</code> 能在保持特定的压缩率下拥有惊人的压缩速度，压缩普通文本文件的速度是其他库的 <code>1.5-1.7</code> 倍，HTML能达到 <code>2-4</code> 倍，但是对于 <code>JPEG</code>、<code>PNG</code> 以及其他的已压缩的数据，压缩速度不会有明显改善。</p>
-
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/17/WorldCup/index.html b/2018/06/17/WorldCup/index.html
deleted file mode 100644
index 1fbedd1..0000000
--- a/2018/06/17/WorldCup/index.html
+++ /dev/null
@@ -1,251 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>World Cup | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="四年一度的世界杯最近正在俄罗斯如火如荼的进行，昨天看了西班牙🇪🇸对葡萄牙🇵🇹的比赛，C罗真的是太帅了，帽子戏法，不过作为一个伪球迷-真程序员，准备写一点和世界杯有关的东西，想想用机器学习预测比赛结果好像并没有什么卵用，于是就写一个最简单的搬砖程序来提醒自己比赛时间吧。最终效果如下所示，典型的 MVC 。 1234567891011121314Costa Rica">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="World Cup">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/17/WorldCup/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="四年一度的世界杯最近正在俄罗斯如火如荼的进行，昨天看了西班牙🇪🇸对葡萄牙🇵🇹的比赛，C罗真的是太帅了，帽子戏法，不过作为一个伪球迷-真程序员，准备写一点和世界杯有关的东西，想想用机器学习预测比赛结果好像并没有什么卵用，于是就写一个最简单的搬砖程序来提醒自己比赛时间吧。最终效果如下所示，典型的 MVC 。 1234567891011121314Costa Rica">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:47:20.459Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="World Cup">
-<meta name="twitter:description" content="四年一度的世界杯最近正在俄罗斯如火如荼的进行，昨天看了西班牙🇪🇸对葡萄牙🇵🇹的比赛，C罗真的是太帅了，帽子戏法，不过作为一个伪球迷-真程序员，准备写一点和世界杯有关的东西，想想用机器学习预测比赛结果好像并没有什么卵用，于是就写一个最简单的搬砖程序来提醒自己比赛时间吧。最终效果如下所示，典型的 MVC 。 1234567891011121314Costa Rica">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-WorldCup"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      World Cup
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-17T07:18:49.000Z" itemprop="datePublished">
-        Jun 17, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>四年一度的世界杯最近正在俄罗斯如火如荼的进行，昨天看了西班牙🇪🇸对葡萄牙🇵🇹的比赛，C罗真的是太帅了，帽子戏法，不过作为一个伪球迷-真程序员，准备写一点和世界杯有关的东西，想想用机器学习预测比赛结果好像并没有什么卵用，于是就写一个最简单的搬砖程序来提醒自己比赛时间吧。最终效果如下所示，典型的 <code>MVC</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">Costa Rica                       <span class="number">0</span> - <span class="number">0</span>                           Serbia</span><br><span class="line">------------------------------------------------------------------------</span><br><span class="line">⚽  Will be played <span class="number">4</span> hours from now</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Germany                          <span class="number">0</span> - <span class="number">0</span>                           Mexico</span><br><span class="line">------------------------------------------------------------------------</span><br><span class="line">⚽  Will be played <span class="number">7</span> hours from now</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Brazil                           <span class="number">0</span> - <span class="number">0</span>                      Switzerland</span><br><span class="line">------------------------------------------------------------------------</span><br><span class="line">⚽  Will be played <span class="number">10</span> hours from now</span><br></pre></td></tr></table></figure>
-<h2 id="Model"><a href="#Model" class="headerlink" title="Model"></a>Model</h2><p>比赛相关的数据可以从 <code>http://worldcup.sfg.io/</code> 获取，我们使用结构体定义数据模型，注意结构体中的数据字段必须为大写，否则无法正确 <code>Unmarshal</code>，如果想要使结构体中的字段与 <code>json</code> 中的字段不同，可以额外增加 <code>tag</code> 来说明。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> match <span class="keyword">struct</span> &#123;</span><br><span class="line">    Time     <span class="keyword">string</span> <span class="string">`json:"time,omitempty"`</span></span><br><span class="line">    DateTime <span class="keyword">string</span> <span class="string">`json:"datetime,omitempty"`</span></span><br><span class="line">    HomeTeam team   <span class="string">`json:"home_team,ommitempty"`</span></span><br><span class="line">    AwayTeam team   <span class="string">`json:"away_team,omitempty"`</span></span><br><span class="line">    Winner   <span class="keyword">string</span> <span class="string">`json:"winner,omitempty"`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> team <span class="keyword">struct</span> &#123;</span><br><span class="line">    Country <span class="keyword">string</span> <span class="string">`json:"country,omitempty"`</span></span><br><span class="line">    Code    <span class="keyword">string</span> <span class="string">`json:"code,omitempty"`</span></span><br><span class="line">    Goals   <span class="keyword">int</span>    <span class="string">`json:"goals,omitempty"`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">fetch</span><span class="params">(endpoint)</span> <span class="params">([]match, error)</span></span> &#123;</span><br><span class="line">    url := fmt.Sprintf(<span class="string">"http://worldcup.sfg.io/%s"</span>, endpoint)</span><br><span class="line">    res, err := http.Get(url)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> res.Body.Close()</span><br><span class="line">    b, err := ioutil.ReadAll(res.Body)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> matches []match</span><br><span class="line">    err = json.Unmarshal(b, &amp;matches)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> matches, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="View"><a href="#View" class="headerlink" title="View"></a>View</h2><p>因为我们的 <code>layout</code> 相对比较复杂，所以 <code>View</code> 部分代码也最多，但难度不大，就是繁琐，主要注意几点，彩色字体输出，不同情况下进度条的展示效果和各个字段所在的位置。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> status <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    PAST status = <span class="literal">iota</span></span><br><span class="line">    NOW</span><br><span class="line">    FUTURE</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ScreenWidth = <span class="number">72</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    START = <span class="string">"\x1b[32m"</span></span><br><span class="line">    END   = <span class="string">"\x1b[0m"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">colorize</span><span class="params">(s <span class="keyword">string</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> START + s + END</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">multiply</span><span class="params">(c <span class="keyword">rune</span>, n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> cs []<span class="keyword">rune</span></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; n; i++ &#123;</span><br><span class="line">        cs = <span class="built_in">append</span>(cs, c)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">string</span>(cs)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">prettify</span><span class="params">(m match)</span> <span class="title">string</span></span> &#123;</span><br><span class="line"></span><br><span class="line">    t, _ := time.Parse(time.RFC3339, m.DateTime)</span><br><span class="line">    diff := <span class="keyword">int</span>(time.Now().Sub(t).Seconds())</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> status status</span><br><span class="line">    <span class="keyword">switch</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> diff &gt; <span class="number">60</span>*<span class="number">90</span>:</span><br><span class="line">        status = PAST</span><br><span class="line">    <span class="keyword">case</span> diff &lt; <span class="number">0</span>:</span><br><span class="line">        status = FUTURE</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        status = NOW</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    percentage := <span class="number">0</span></span><br><span class="line">    matchStatus := <span class="string">""</span></span><br><span class="line">    on := <span class="literal">false</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> status &#123; </span><br><span class="line">    <span class="keyword">case</span> PAST:</span><br><span class="line">        percentage = <span class="number">100</span></span><br><span class="line">        <span class="keyword">var</span> result <span class="keyword">string</span></span><br><span class="line">        <span class="keyword">if</span> m.Winner == <span class="string">"Draw"</span> &#123;</span><br><span class="line">            result = <span class="string">"Draw"</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            result = fmt.Sprintf(<span class="string">"%s won"</span>, m.Winner)</span><br><span class="line">        &#125;</span><br><span class="line">        matchStatus = fmt.Sprintf(<span class="string">"Played %s. %s"</span>, humanize.Time(t), result)</span><br><span class="line">        on = <span class="literal">true</span></span><br><span class="line">    <span class="keyword">case</span> NOW:</span><br><span class="line">        percentage = <span class="keyword">int</span>(diff / <span class="number">60</span> / <span class="number">90</span> * <span class="number">100</span>)</span><br><span class="line">        matchStatus = fmt.Sprintf(<span class="string">"Being played now: %s minutes gone"</span>, humanize.Time(t))</span><br><span class="line">        on = <span class="literal">true</span></span><br><span class="line">    <span class="keyword">case</span> FUTURE:</span><br><span class="line">        percentage = <span class="number">0</span></span><br><span class="line">        matchStatus = fmt.Sprintf(<span class="string">"Will be played %s"</span>, humanize.Time(t))</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    home := m.HomeTeam</span><br><span class="line">    away := m.AwayTeam</span><br><span class="line"></span><br><span class="line">    s, e := <span class="string">""</span>, <span class="string">""</span></span><br><span class="line">    <span class="keyword">if</span> on &#123;</span><br><span class="line">        s = start</span><br><span class="line">        e = end</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"    %s%-32s %d - %d %32s%s\n    %s\n    \u26BD  %s\n"</span>,</span><br><span class="line">        s,home.Country,home.Goals,away.Goals,away.Country,e,</span><br><span class="line">        progressBar(percentage),</span><br><span class="line">        matchStatus,</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">progressBar</span><span class="params">(percentage <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> bar <span class="keyword">string</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> percentage &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">        bar = multiply(<span class="string">'-'</span>, ScreenWidth)</span><br><span class="line">    <span class="keyword">case</span> <span class="number">100</span>:</span><br><span class="line">        bar = colorize(multiply(<span class="string">'-'</span>, ScreenWidth))</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        completed := <span class="keyword">int</span>(<span class="keyword">float64</span>(ScreenWidth) / <span class="number">100.0</span> * <span class="keyword">float64</span>(percentage))</span><br><span class="line">        bar = colorize(multiply(<span class="string">'-'</span>, completed<span class="number">-1</span>)+<span class="string">"o"</span>) + multiply(<span class="string">'-'</span>, ScreenWidth-completed)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> bar</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Controller"><a href="#Controller" class="headerlink" title="Controller"></a>Controller</h2><p><code>Controller</code> 部分就是将 <code>Model</code> 部分和 <code>view</code> 部分代码整合在一起。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    matches, err := fetch(<span class="string">"matches/today"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i, match := <span class="keyword">range</span> matches &#123;</span><br><span class="line">        <span class="keyword">if</span> i == <span class="number">0</span> &#123;</span><br><span class="line">            fmt.Println()</span><br><span class="line">        &#125;</span><br><span class="line">        fmt.Println(prettify(match))</span><br><span class="line">        <span class="keyword">if</span> i != <span class="built_in">len</span>(matches)<span class="number">-1</span> &#123;</span><br><span class="line">            fmt.Println()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/18/imgcat/index.html b/2018/06/18/imgcat/index.html
deleted file mode 100644
index c01327f..0000000
--- a/2018/06/18/imgcat/index.html
+++ /dev/null
@@ -1,255 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>imgcat | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在 iTerm2 中我们可以直接查看图片，是不是有点酷炫。  为了使图片能够正确的展示，我们需要使数据满足特定的协议格式。 1ESC ] 1337 ; File = [optional arguments] : base-64 encoded file contents ^G 按照上面的格式我们将数据分为 header ，body 和 footer 三个部分，而 header 和 footer 相">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="imgcat">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/18/imgcat/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在 iTerm2 中我们可以直接查看图片，是不是有点酷炫。  为了使图片能够正确的展示，我们需要使数据满足特定的协议格式。 1ESC ] 1337 ; File = [optional arguments] : base-64 encoded file contents ^G 按照上面的格式我们将数据分为 header ，body 和 footer 三个部分，而 header 和 footer 相">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://www.iterm2.com/images/inline_image_sparky_demo.png">
-<meta property="og:updated_time" content="2018-06-26T08:46:17.739Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="imgcat">
-<meta name="twitter:description" content="在 iTerm2 中我们可以直接查看图片，是不是有点酷炫。  为了使图片能够正确的展示，我们需要使数据满足特定的协议格式。 1ESC ] 1337 ; File = [optional arguments] : base-64 encoded file contents ^G 按照上面的格式我们将数据分为 header ，body 和 footer 三个部分，而 header 和 footer 相">
-<meta name="twitter:image" content="https://www.iterm2.com/images/inline_image_sparky_demo.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-imgcat"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      imgcat
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-18T14:02:51.000Z" itemprop="datePublished">
-        Jun 18, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>在 <code>iTerm2</code> 中我们可以直接查看图片，是不是有点酷炫。</p>
-<p><img src="https://www.iterm2.com/images/inline_image_sparky_demo.png" alt="imgcat"></p>
-<p>为了使图片能够正确的展示，我们需要使数据满足特定的协议格式。</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ESC ] 1337 ; File = [optional arguments] : base-64 encoded file contents ^G</span><br></pre></td></tr></table></figure>
-<p>按照上面的格式我们将数据分为 <code>header</code> ，<code>body</code> 和 <code>footer</code> 三个部分，而 <code>header</code> 和 <code>footer</code> 相对固定，我们使用 <code>strings.NewReader</code> 封装返回一个 <code>io.Reader</code> ，而中间变化的 <code>base64</code> 编码的数据，我们需要利用 <code>base64.NewEncoder</code> 来对输入的数据进行编码，最后将三个部分利用 <code>io.MultiReader</code> 整合成一个 <code>io.Reader</code> ，然后利用 <code>io.Copy</code> 将数据传输到 <code>w</code> 中，然而 <code>base64.NewEncoder</code> 返回的是一个 <code>io.WriteCloser</code> ，而我们想要的是一个 <code>io.Reader</code> ，这种转化我们可以借助 <code>io.Pipe()</code> 实现，<code>io.Pipe()</code> 会返回一个 <code>PipeReader</code> 和一个  <code>PipeWriter</code> ，当有数据往 <code>PipeWriter</code> 中写时，<code>PipeReader</code> 就可以获得相应的数据，通过这种方式，我们就可以间接地将一个 <code>Writer</code> 转换为一个 <code>Reader</code> 来使用了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">copy</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    header := strings.NewReader(<span class="string">"\033 ] 1337 ; File = inline=1 : "</span>)</span><br><span class="line">    footer := strings.NewReader(<span class="string">"\a\n"</span>)</span><br><span class="line">    </span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> pw.Close()</span><br><span class="line">        wc := base64.NewEncoder(base64.StdEncoding, pw)</span><br><span class="line">        _, err := io.Copy(wc, r)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            pw.CloseWithError(err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">   </span><br><span class="line">        <span class="keyword">if</span> err := wc.Close(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            pw.CloseWithError(err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">   </span><br><span class="line">    mr := io.MultiReader(header, pr, footer)</span><br><span class="line">    _, err := io.Copy(w, mr)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>为了在下面的 <code>imgcat</code> 方法中使用 <code>io.Copy</code> 接口，我们需要自己实现一个 <code>io.Writer</code> ，在 <code>NewWriter</code> 函数中我们返回自己 <code>writer</code> 结构体，并且同时起了一个<code>goroutine</code> 来获取 <code>PipeWriter</code> 写的数据，同理，<code>PipeWriter</code> 中写入的数据可以从相应的 <code>PipeReader</code> 获取。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> imgcat</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> writer <span class="keyword">struct</span> &#123;</span><br><span class="line">    pw   *io.PipeWriter</span><br><span class="line">    done <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *writer)</span> <span class="title">Write</span><span class="params">(p []<span class="keyword">byte</span>)</span> <span class="params">(<span class="keyword">int</span>, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> w.pw.Write(p)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *writer)</span> <span class="title">Close</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> err := w.pw.Close(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    &lt;-w.done</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewWriter</span><span class="params">(w io.Writer)</span> <span class="title">io</span>.<span class="title">WriteCloser</span></span> &#123;</span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line">    wc := &amp;writer&#123;pw, <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)&#125;</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> <span class="built_in">close</span>(w.done)</span><br><span class="line">        err := <span class="built_in">copy</span>(w, pr)</span><br><span class="line">        pr.CloseWithError(err)</span><br><span class="line">    &#125;()</span><br><span class="line">   <span class="keyword">return</span> wc</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在 <code>imgcat</code> 方法中主要是通过 <code>io.Copy</code> 将路径 <code>path</code> 对应的文件拷贝到我们上面的 <code>Writer</code> 中，<code>NewWriter</code> 指定 <code>os.Stdout</code> 作为我们的输出。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">imgcat</span><span class="params">(path <span class="keyword">string</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    f, err := os.Open(path)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> f.Close()</span><br><span class="line"></span><br><span class="line">    wc := imgcat.NewWriter(os.Stdout)</span><br><span class="line">    <span class="keyword">if</span> _, err = io.Copy(wc, f); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> wc.Close()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(os.Args) != <span class="number">2</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> </span><br><span class="line">    &#125;</span><br><span class="line">    err := imgcat(os.Args[<span class="number">1</span>])</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/19/Pipeline/index.html b/2018/06/19/Pipeline/index.html
deleted file mode 100644
index 422ce27..0000000
--- a/2018/06/19/Pipeline/index.html
+++ /dev/null
@@ -1,257 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Pipeline | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="在介绍 io.Pipe 之前，我们先来看一段非常简单的代码，如果现在需要向服务器发送一个 POST 请求，按流程一步步来，首先构建一个消息结构体，然后将该结构体编码成 json 格式的数据，并将该数据暂时存储在 buf 中，最后利用 http.Post 发送该请求，轻松愉快。 12345678910111213141516171819202122232425type message struct">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Pipeline">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/19/Pipeline/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="在介绍 io.Pipe 之前，我们先来看一段非常简单的代码，如果现在需要向服务器发送一个 POST 请求，按流程一步步来，首先构建一个消息结构体，然后将该结构体编码成 json 格式的数据，并将该数据暂时存储在 buf 中，最后利用 http.Post 发送该请求，轻松愉快。 12345678910111213141516171819202122232425type message struct">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="http://insideenergy.org/wp-content/uploads/2017/05/DAPL-Pipeline-2-1170x775.jpg">
-<meta property="og:updated_time" content="2018-06-26T08:48:31.242Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Pipeline">
-<meta name="twitter:description" content="在介绍 io.Pipe 之前，我们先来看一段非常简单的代码，如果现在需要向服务器发送一个 POST 请求，按流程一步步来，首先构建一个消息结构体，然后将该结构体编码成 json 格式的数据，并将该数据暂时存储在 buf 中，最后利用 http.Post 发送该请求，轻松愉快。 12345678910111213141516171819202122232425type message struct">
-<meta name="twitter:image" content="http://insideenergy.org/wp-content/uploads/2017/05/DAPL-Pipeline-2-1170x775.jpg">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Pipeline"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Pipeline
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-19T08:39:47.000Z" itemprop="datePublished">
-        Jun 19, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p><img src="http://insideenergy.org/wp-content/uploads/2017/05/DAPL-Pipeline-2-1170x775.jpg" alt="pipeline"></p>
-<p>在介绍 <code>io.Pipe</code> 之前，我们先来看一段非常简单的代码，如果现在需要向服务器发送一个 <code>POST</code> 请求，按流程一步步来，首先构建一个消息结构体，然后将该结构体编码成 <code>json</code> 格式的数据，并将该数据暂时存储在 <code>buf</code> 中，最后利用 <code>http.Post</code> 发送该请求，轻松愉快。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> message <span class="keyword">struct</span> &#123;</span><br><span class="line">    Name <span class="keyword">string</span></span><br><span class="line">    Age  <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    m := &amp;message&#123;Name: <span class="string">"yiyangyi"</span>, Age: <span class="number">23</span>&#125;</span><br><span class="line">    <span class="keyword">var</span> buf bytes.Buffer</span><br><span class="line">    err := json.NewEncoder(&amp;buf).Encode(m)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    resp, err := http.Post(<span class="string">"example.com"</span>, <span class="string">"application/json"</span>, &amp;buf)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)     </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line">    </span><br><span class="line">    b, err := ioutil.ReadAll(resp.Body)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Println(<span class="keyword">string</span>(b))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>但是，上面的代码存在一个问题，就是我们需要分配一个缓存区（ <code>bytes.Buffer</code> ）存储编码后的数据，为了节省内存，能不能通过一个方法来避免此部分内存的分配呢，解决方法就是我们今天的主角——<code>io.Pipe</code> 。</p>
-<p><code>io.Pipe</code> 执行后会得到一个 <code>PipeReader</code> 和 <code>PipeWriter</code> ，当程序向<code>PipeWriter</code> 中写入数据时，<code>PipeReader</code> 可以同步地收到这部分消息，根据这个特性，我们将 <code>PipeWriter</code> 代替 <code>bytes.Buffer</code> 作为参数 (它们同为 <code>io.Writer</code> ) 传入 <code>json.NewEncoder</code> 中，当我们 <code>Encode</code> 数据时，会直接向 <code>PipeWriter</code> 写入数据，此时 <code>Pipe</code> 的另一边，<code>PipeReader</code> 可以马上收到数据，利用 <code>io.Pipe</code> 我们就避免了中间非必要缓存的分配。</p>
-<p>由于使用 <code>io.Pipe</code> 发送和接收数据是一个同步的过程 (类似于 <code>unbuffered channel</code> )，所以需要让发送和接收在两个 <code>goroutine</code> 中进行，如果它们存在于一个 <code>goroutine</code> 中，会导致程序死锁。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> message <span class="keyword">struct</span> &#123;</span><br><span class="line">    Name <span class="keyword">string</span></span><br><span class="line">    Age  <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;       </span><br><span class="line">        m := &amp;message&#123;Name: <span class="string">"yiyangyi"</span>, Age: <span class="number">23</span>&#125;</span><br><span class="line">        err := json.NewEncoder(pw).Encode(m)</span><br><span class="line">        pw.CloseWithError(err)</span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    resp, err := http.Post(<span class="string">"example.com"</span>, <span class="string">"application/json"</span>, pr)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)     </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"></span><br><span class="line">    b, err := ioutil.ReadAll(resp.Body)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Println(<span class="keyword">string</span>(b))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="io-TeeReader-amp-io-MultiReader-❤️-io-Pipe"><a href="#io-TeeReader-amp-io-MultiReader-❤️-io-Pipe" class="headerlink" title="io.TeeReader &amp; io.MultiReader  ❤️  io.Pipe"></a>io.TeeReader &amp; io.MultiReader  ❤️  io.Pipe</h2><p><code>io.Pipe</code> 经常与 <code>io.TeeReader</code> 和 <code>io.MultiReader</code> 一起使用，下面有两个这样的例子。</p>
-<h3 id="io-Pipe-❤️-io-TeeReader"><a href="#io-Pipe-❤️-io-TeeReader" class="headerlink" title="io.Pipe ❤️ io.TeeReader"></a>io.Pipe ❤️ io.TeeReader</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tr  &lt;--- r -----&gt; pw ------ &gt; pr</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">upload</span><span class="params">(r io.Reader)</span></span> &#123;</span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line">    tr := io.TeeReader(r, pw)</span><br><span class="line"></span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">defer</span> <span class="built_in">close</span>(done)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> pw.Close()</span><br><span class="line">        uploadFile(tr)</span><br><span class="line">        done &lt;- <span class="literal">true</span></span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        webmr := transcode(pr)</span><br><span class="line">        uploadFile(webmr)</span><br><span class="line">        done &lt;- <span class="literal">true</span></span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> c := <span class="number">0</span>; c &lt; <span class="number">2</span>; c++ &#123;</span><br><span class="line">        &lt;-done</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="io-Pipe-❤️-io-MultiReader"><a href="#io-Pipe-❤️-io-MultiReader" class="headerlink" title="io.Pipe ❤️ io.MultiReader"></a>io.Pipe ❤️ io.MultiReader</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;- pr1 &lt;-----&gt; pw1 --\</span><br><span class="line"></span><br><span class="line">&lt;- pr2 &lt;-----&gt; pw2 ----</span><br><span class="line">                        &gt; multiwriter(pw1,pw2,pw3,pw4) &lt;----- r</span><br><span class="line">&lt;- pr3 &lt;-----&gt; pw3 ----</span><br><span class="line"></span><br><span class="line">&lt;- pr4 &lt;-----&gt; pw4 --/</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">TranscodeAll</span><span class="params">(r io.Reader)</span></span> &#123;</span><br><span class="line">    mp4R, mp4W   := io.Pipe()</span><br><span class="line">    oggR, oggW   := io.Pipe()</span><br><span class="line">    wavR, wavW   := io.Pipe()</span><br><span class="line">    webmR, webmW := io.Pipe()</span><br><span class="line"></span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">defer</span> <span class="built_in">close</span>(done)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> transcodeMP4(mp4R, done)</span><br><span class="line">    <span class="keyword">go</span> transcodeOgg(oggR, done)</span><br><span class="line">    <span class="keyword">go</span> transcodeWav(wavR, done)</span><br><span class="line">    <span class="keyword">go</span> transcodeWebM(webmR, done)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> mp4W.Close() </span><br><span class="line">        <span class="keyword">defer</span> oggW.Close()</span><br><span class="line">        <span class="keyword">defer</span> wavW.Close()</span><br><span class="line">        <span class="keyword">defer</span> webmW.Close()</span><br><span class="line"></span><br><span class="line">        mw := io.MultiWriter(mp4W, oggW, wavW, webmW)</span><br><span class="line">        io.Copy(mw, r)</span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> c := <span class="number">0</span>; c &lt; <span class="number">4</span>; c++ &#123;</span><br><span class="line">        &lt;-done</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/20/grep/index.html b/2018/06/20/grep/index.html
deleted file mode 100644
index 3370897..0000000
--- a/2018/06/20/grep/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>grep | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="最近看到 golang 语法中一个非常有趣的基本组合 chan chan ，为了加深自己的理解，想多看几个使用案例，于是去 $GOPATH 下面的文件去找，但是一个个文件找肯定不现实，于是借助 grep 帮我们进行搜索，grep 的使用非常简单，但是如果在不了解 grep 使用的情况下，自己实现一个类似的搜索功能应该也不是很难，今天就让我们来看看 grep 的使用和 golang 版本的简单实现吧">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="grep">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/20/grep/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="最近看到 golang 语法中一个非常有趣的基本组合 chan chan ，为了加深自己的理解，想多看几个使用案例，于是去 $GOPATH 下面的文件去找，但是一个个文件找肯定不现实，于是借助 grep 帮我们进行搜索，grep 的使用非常简单，但是如果在不了解 grep 使用的情况下，自己实现一个类似的搜索功能应该也不是很难，今天就让我们来看看 grep 的使用和 golang 版本的简单实现吧">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:45:51.416Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="grep">
-<meta name="twitter:description" content="最近看到 golang 语法中一个非常有趣的基本组合 chan chan ，为了加深自己的理解，想多看几个使用案例，于是去 $GOPATH 下面的文件去找，但是一个个文件找肯定不现实，于是借助 grep 帮我们进行搜索，grep 的使用非常简单，但是如果在不了解 grep 使用的情况下，自己实现一个类似的搜索功能应该也不是很难，今天就让我们来看看 grep 的使用和 golang 版本的简单实现吧">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-grep"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      grep
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-20T06:07:24.000Z" itemprop="datePublished">
-        Jun 20, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>最近看到 <code>golang</code> 语法中一个非常有趣的基本组合 <code>chan chan</code> ，为了加深自己的理解，想多看几个使用案例，于是去 <code>$GOPATH</code> 下面的文件去找，但是一个个文件找肯定不现实，于是借助 <code>grep</code> 帮我们进行搜索，<code>grep</code> 的使用非常简单，但是如果在不了解 <code>grep</code> 使用的情况下，自己实现一个类似的搜索功能应该也不是很难，今天就让我们来看看 <code>grep</code> 的使用和 <code>golang</code> 版本的简单实现吧。</p>
-<h2 id="usr-bin-grep"><a href="#usr-bin-grep" class="headerlink" title="/usr/bin/grep"></a>/usr/bin/grep</h2><p><code>grep</code> 命令的基本语法如下所示。</p>
-<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ grep <span class="string">'chan'</span> file</span><br><span class="line">$ grep <span class="string">'chan chan'</span> file1 file2</span><br><span class="line">$ grep [option] <span class="string">'chan chan'</span> file1 file2</span><br></pre></td></tr></table></figure>
-<p>除了列出文件名之外，我们还可以使用通配符搜索当前目录中所有文件。</p>
-<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ grep <span class="string">'chan chan'</span> *</span><br></pre></td></tr></table></figure>
-<h3 id="search-sub-directories-recursively-using-grep"><a href="#search-sub-directories-recursively-using-grep" class="headerlink" title="search sub directories recursively using grep"></a>search sub directories recursively using grep</h3><p>使用 <code>grep</code> 加上 <code>-r</code> 或者 <code>-R</code> 选项可以递归搜索当前目录下的所有文件。</p>
-<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ grep -r <span class="string">'chan chan'</span> *</span><br><span class="line">$ grep -R <span class="string">'chan chan'</span> *</span><br></pre></td></tr></table></figure>
-<h3 id="examples"><a href="#examples" class="headerlink" title="examples"></a>examples</h3><p>例如，以下命令将会输出当前目录中所有文件及其所有子目录中包含单词 <code>chan chan</code>  的每一行。</p>
-<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ grep -r <span class="string">'chan chan'</span> *</span><br></pre></td></tr></table></figure>
-<h2 id="my-own-grep"><a href="#my-own-grep" class="headerlink" title="my own grep"></a>my own grep</h2><p>如果要自己实现，在不考虑性能的情况下， 只需要实现两个功能，一是文件夹的递归遍历，二就是模式匹配，下面我们实现一个最简单的 <code>grep</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    haystack = flag.String(<span class="string">"path"</span>, <span class="string">""</span>, <span class="string">"file path to search in"</span>)</span><br><span class="line">    needle = flag.String(<span class="string">"search"</span>, <span class="string">""</span>, <span class="string">"search string to look for"</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    flag.Parse()</span><br><span class="line">    fi, err := os.Stat(*haystack)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> fi.Mode().IsDir() &#123;</span><br><span class="line">        *haystack = strings.TrimRight(*haystack, <span class="string">"/"</span>) + <span class="string">"/"</span></span><br><span class="line">        dfs(*haystack, *needle)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        log.Fatal(<span class="string">"path must be a dir"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="depth-first-search"><a href="#depth-first-search" class="headerlink" title="depth first search"></a>depth first search</h3><p>我们利用深度优先搜索来遍历相关文件，如果当前对应的 <code>path</code> 为目录（ <code>file.Mode().IsDir()</code> ），则递归调用搜索方法，如果 <code>path</code> 为普通文件（ <code>file.Mode().IsRegular()</code> ），则利用下面的 <code>grep</code> 方法扫描该文件。直到所有文件均被遍历。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">dfs</span><span class="params">(path, search <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    files, err := ioutil.ReadDir(path)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> _, file := <span class="keyword">range</span> files &#123;</span><br><span class="line">        fullpath := path + file.Name(<span class="number">0</span></span><br><span class="line">        <span class="keyword">if</span> file.Mode().IsDir() &#123;</span><br><span class="line">            dfs(fullpath+<span class="string">"/"</span>, search)</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> file.Mode().IsRegular() &#123;</span><br><span class="line">            grep(fullpath, search)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="grep-individual-using-scanner"><a href="#grep-individual-using-scanner" class="headerlink" title="grep individual using scanner"></a>grep individual using scanner</h3><p>对于每一个 <code>fullpath</code> 对应的文件，我们利用 <code>bufio.NewScanner</code> 构建一个扫描仪，并进行逐行扫描，然后判断要搜索的文字（ <code>search</code> ）是否存在于该行中，如果存在（ <code>strings.Contains</code> ），则在命令行中输出。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">grep</span><span class="params">(fullpath, search <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    f, err := os.Open(fullpath)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    scanner := bufio.NewScanner(f)</span><br><span class="line">    <span class="keyword">for</span> scanner.Scan() &#123;</span><br><span class="line">        line := scanner.Text()</span><br><span class="line">        <span class="keyword">if</span> strings.Contains(line, search) &#123;</span><br><span class="line">            fmt.Println(fullpath, <span class="string">" "</span>, line)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/21/SkipList/index.html b/2018/06/21/SkipList/index.html
deleted file mode 100644
index c9348b6..0000000
--- a/2018/06/21/SkipList/index.html
+++ /dev/null
@@ -1,260 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Skip List | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="跳表是一种建立在普通链表基础上的概率数据结构，为什么说是概率呢，因为跳表会根据概率在原始链表上构建后续的链表层，每个额外的链表层包含的元素数量更少，但每个元素都是原始链表中已经拥有的，这使得跳表在搜索时不用像链表一样一个一个元素的寻找，而是跳过一些元素，这就是跳表名字的由来，正是因为略过了一些元素，所以大大增加了搜索的速度。  利用跳表可以构建 kv 数据库的索引，例如 leveldb 中的索引就">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Skip List">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/21/SkipList/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="跳表是一种建立在普通链表基础上的概率数据结构，为什么说是概率呢，因为跳表会根据概率在原始链表上构建后续的链表层，每个额外的链表层包含的元素数量更少，但每个元素都是原始链表中已经拥有的，这使得跳表在搜索时不用像链表一样一个一个元素的寻找，而是跳过一些元素，这就是跳表名字的由来，正是因为略过了一些元素，所以大大增加了搜索的速度。  利用跳表可以构建 kv 数据库的索引，例如 leveldb 中的索引就">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://ds055uzetaobb.cloudfront.net/image_optimizer/968e3d82130f4bfa9a1574b1537c840a1787c919.png">
-<meta property="og:updated_time" content="2018-06-26T08:47:54.101Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Skip List">
-<meta name="twitter:description" content="跳表是一种建立在普通链表基础上的概率数据结构，为什么说是概率呢，因为跳表会根据概率在原始链表上构建后续的链表层，每个额外的链表层包含的元素数量更少，但每个元素都是原始链表中已经拥有的，这使得跳表在搜索时不用像链表一样一个一个元素的寻找，而是跳过一些元素，这就是跳表名字的由来，正是因为略过了一些元素，所以大大增加了搜索的速度。  利用跳表可以构建 kv 数据库的索引，例如 leveldb 中的索引就">
-<meta name="twitter:image" content="https://ds055uzetaobb.cloudfront.net/image_optimizer/968e3d82130f4bfa9a1574b1537c840a1787c919.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-SkipList"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Skip List
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-21T12:53:24.000Z" itemprop="datePublished">
-        Jun 21, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>跳表是一种建立在普通链表基础上的概率数据结构，为什么说是概率呢，因为跳表会根据概率在原始链表上构建后续的链表层，每个额外的链表层包含的元素数量更少，但每个元素都是原始链表中已经拥有的，这使得跳表在搜索时不用像链表一样一个一个元素的寻找，而是跳过一些元素，这就是跳表名字的由来，正是因为略过了一些元素，所以大大增加了搜索的速度。</p>
-<p><img src="https://ds055uzetaobb.cloudfront.net/image_optimizer/968e3d82130f4bfa9a1574b1537c840a1787c919.png" alt="SkipList"></p>
-<p>利用跳表可以构建 <code>kv</code> 数据库的索引，例如 <code>leveldb</code> 中的索引就是利用跳表来构建的，跳表相对其他索引数据结构例如红黑树，b树等有实现相对简单，但查询效率高的特点，其空间复杂度为 <code>O(n)</code> ，时间复杂度为 <code>O(logn)</code> 。</p>
-<h2 id="跳表的组成元素"><a href="#跳表的组成元素" class="headerlink" title="跳表的组成元素"></a>跳表的组成元素</h2><p>与链表类似，跳表也是由一系列节点组成，每个节点我们用 <code>Element</code> 结构体表示，每个节点会存储一个 <code>kv</code> 对， 除了 <code>kv</code> 对之外，还包含一个 <code>elementNode</code> 结构体，该结构体其实就是一个指针数组，在单向链表中，指针有且只有一个，在跳表中，可以存在多个指向后续节点的指针，用于遍历时加速跳跃使用，这个指针数组是跳表的核心，使用 <code>next []*Element</code> 表示。</p>
-<p>在表示完跳表的基本元素之后，我们还需要考虑一个完整跳表的数据结构，类与普通的链表类似，我们需要一个跳表头，这里用 <code>elementNode</code> 表示，由于跳表在构建时新元素的高度是不确定的，所以我们需要一个 <code>rand.Source</code> 帮助我们决定元素的高度，并限制高度小于最高高度 <code>maxLevel</code> ，这里整个跳表的质量与随机性有相当大的关系，构建得到的跳表随机性越强，搜索速度越快。</p>
-<p>还有我们需要 <code>prevNodesCache []*elementNode</code> 来存储被查找节点的之前的节点，这个刚开始理解起来有一点复杂，因为被查找节点每一层的前一个元素都是不同的，每一个之前的元素可以用一个 <code>*elementNode</code> 来表示，由于每个节点可能存在多层指针，所以这里用一个数组来表示 <code>[]*elementNode</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> elementNode <span class="keyword">struct</span> &#123;</span><br><span class="line">    next []*Element</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Element <span class="keyword">struct</span> &#123;</span><br><span class="line">    elementNode</span><br><span class="line">    key   <span class="keyword">float64</span></span><br><span class="line">    value <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> SkipList <span class="keyword">struct</span> &#123;</span><br><span class="line">    elementNode</span><br><span class="line">    maxLevel       <span class="keyword">int</span></span><br><span class="line">    Length         <span class="keyword">int</span></span><br><span class="line">    randSource     rand.Source</span><br><span class="line">    mutex          sync.RWMutex</span><br><span class="line">    prevNodesCache []*elementNode</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(maxLevel <span class="keyword">int</span>)</span> *<span class="title">SkipList</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> maxLevel &lt; <span class="number">1</span> || maxLevel &gt; <span class="number">64</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"max level should be less than 64 and greater than 1"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> &amp;SkipList&#123;</span><br><span class="line">        elementNode: elementNode&#123;next: <span class="built_in">make</span>([]*Element, maxLevel)&#125;,</span><br><span class="line">        maxLevel: maxLevel,</span><br><span class="line">        randSource: rand.New(rand.NewSource(time.Now().UnixNano())),</span><br><span class="line">        prevNodesCache: <span class="built_in">make</span>([]*elementNode, maxLevel),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="跳表的基本操作"><a href="#跳表的基本操作" class="headerlink" title="跳表的基本操作"></a>跳表的基本操作</h2><p>在插入和删除特定节点时，我们需要获取该节点之前的所有元素节点， <code>getPrevElementNodes</code> 从跳表的头节点（ <code>list.elementNode</code> ）出发，并从最高层开始，确定 <code>key</code> 对应的元素在该层对应的前一个<code>elementNode</code> ，然后存储在 <code>prevNodesCache</code> 中（ <code>prevs[i] = prev</code> ），这样一直查找直到最底层。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">getPrevElementNodes</span><span class="params">(key <span class="keyword">float64</span>)</span> []*<span class="title">elementNode</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> prev *elementNode = &amp;list.elementNode</span><br><span class="line">    <span class="keyword">var</span> next *Element</span><br><span class="line"></span><br><span class="line">    prevs := list.prevNodesCache</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := list.maxLevel - <span class="number">1</span>; i &gt;=<span class="number">0</span>; i-- &#123;</span><br><span class="line">        next = prev.next[i]</span><br><span class="line">        <span class="keyword">for</span> next != <span class="literal">nil</span> &amp;&amp; key &gt; next.key &#123;</span><br><span class="line">            prev = &amp;next.elementNode</span><br><span class="line">            next = next.next[i]</span><br><span class="line">        &#125;</span><br><span class="line">        prevs[i] = prev</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> prevs</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">randLevel</span><span class="params">()</span> <span class="params">(level <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> list.randSource.Intn(list.maxLevel)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="Get"><a href="#Get" class="headerlink" title="Get"></a>Get</h3><p><code>Get</code> 方法的本质就是一个走楼梯的过程，但是这里每个阶梯的高度和宽度并非确定，开始从楼梯的最高层出发（ <code>i := list.maxLevel - 1</code> ），每次对前方同一层的阶梯（ <code>next = prev.next[i]</code> ）进行试探，如果前方阶梯不为空（ <code>next != nil</code> ），且符合特定要求（ <code>key &gt; next.key</code> ）则继续在这一层走，否则直接进入下一层（ <code>i--</code> ），直到找到为止，最后判断此阶梯不为空（ <code>next != nil</code> ）且该阶梯保存的值和要找的值相同时，返回该阶梯。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">Get</span><span class="params">(key <span class="keyword">float64</span>)</span> *<span class="title">Element</span></span> &#123;</span><br><span class="line">    list.mutex.Lock()</span><br><span class="line">    <span class="keyword">defer</span> list.mutex.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> prev *elementNode = &amp;list.elementNode</span><br><span class="line">    <span class="keyword">var</span> next *Element</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := list.maxLevel - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i-- &#123;</span><br><span class="line">        next = prev.next[i]</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> next != <span class="literal">nil</span> &amp;&amp; key &gt; next.key &#123;</span><br><span class="line">            prev = &amp;next.elementNode</span><br><span class="line">            next = next.next[i]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> next != <span class="literal">nil</span> &amp;&amp; next.key &lt;= key &#123;</span><br><span class="line">        <span class="keyword">return</span> next</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p><code>Set</code> 方法需要使用之前的 <code>getPrevElementNodes</code> 来获取对应 <code>key</code> 之前的元素，如果该元素对应的 <code>key</code> 已经存在，则改变其 <code>value</code> 之后返回，如果不存在，则构建一个新的节点，然后将自己之前的节点的指针和自己之后节点的指针相连，使其前节点指向自己，使自己指向后面的节点。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">Set</span><span class="params">(key <span class="keyword">float64</span>, value <span class="keyword">interface</span>&#123;&#125;)</span> *<span class="title">Element</span></span> &#123;</span><br><span class="line">    list.mutex.Lock()</span><br><span class="line">    <span class="keyword">defer</span> list.mutex.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> element *Element</span><br><span class="line">    prevs := list.getPrevElementNodes(key)</span><br><span class="line">    <span class="keyword">if</span> element = prevs[<span class="number">0</span>].next[<span class="number">0</span>]; element != <span class="literal">nil</span> &amp;&amp; element.key &lt;= key &#123;</span><br><span class="line">        element.value = value</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    element = &amp;Element &#123;</span><br><span class="line">        elementNode: elementNode&#123;</span><br><span class="line">            next: <span class="built_in">make</span>([]*Element, list.randLevel()),</span><br><span class="line">            key: key,</span><br><span class="line">            value: value,</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> element.next &#123;</span><br><span class="line">        element.next[i] = prevs[i].next[i]</span><br><span class="line">        prevs[i].next[i] = element</span><br><span class="line">    &#125;</span><br><span class="line">    list.Length++</span><br><span class="line">    <span class="keyword">return</span> element</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h3 id="Remove"><a href="#Remove" class="headerlink" title="Remove"></a>Remove</h3><p><code>Remove</code> 方法也需要使用 <code>getPrevElementNodes</code> 方法，使自己前面的节点不指向该元素而是指向该元素后面的元素。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">Remove</span><span class="params">(key <span class="keyword">float64</span>)</span> *<span class="title">Element</span></span> &#123;</span><br><span class="line">    list.mutex.Lock()</span><br><span class="line">    <span class="keyword">defer</span> list.mutex.Unlock()</span><br><span class="line">    prevs := list.getPrevElementNodes(key)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> element := prevs[<span class="number">0</span>].next[<span class="number">0</span>]; element != <span class="literal">nil</span> &amp;&amp; element.key &lt;= key &#123;</span><br><span class="line">        <span class="keyword">for</span> k, v := <span class="keyword">range</span> element.next &#123;</span><br><span class="line">            prevs[k].next[k] = v</span><br><span class="line">        &#125;</span><br><span class="line">        list.Length--</span><br><span class="line">        <span class="keyword">return</span> element</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/23/PageViews/index.html b/2018/06/23/PageViews/index.html
deleted file mode 100644
index 32b03b9..0000000
--- a/2018/06/23/PageViews/index.html
+++ /dev/null
@@ -1,248 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Page Views | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="统计网站的页面浏览次数（ Page Views ）是分析网站的重要参数之一。由于多个用户发送的请求很可能是同时进行的，所以这里涉及到并发操作时对变量的保护问题。 mutex在统计页面浏览次数时，我们可以使用一个变量 pageView 来表示页面的浏览次数，并用一个 mutex 锁来保护变量存取。 12345678910111213141516var (    pageView int    mut">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Page Views">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/23/PageViews/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="统计网站的页面浏览次数（ Page Views ）是分析网站的重要参数之一。由于多个用户发送的请求很可能是同时进行的，所以这里涉及到并发操作时对变量的保护问题。 mutex在统计页面浏览次数时，我们可以使用一个变量 pageView 来表示页面的浏览次数，并用一个 mutex 锁来保护变量存取。 12345678910111213141516var (    pageView int    mut">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-06-26T08:48:33.155Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Page Views">
-<meta name="twitter:description" content="统计网站的页面浏览次数（ Page Views ）是分析网站的重要参数之一。由于多个用户发送的请求很可能是同时进行的，所以这里涉及到并发操作时对变量的保护问题。 mutex在统计页面浏览次数时，我们可以使用一个变量 pageView 来表示页面的浏览次数，并用一个 mutex 锁来保护变量存取。 12345678910111213141516var (    pageView int    mut">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-PageViews"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Page Views
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-23T15:08:44.000Z" itemprop="datePublished">
-        Jun 23, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>统计网站的页面浏览次数（ <code>Page Views</code> ）是分析网站的重要参数之一。由于多个用户发送的请求很可能是同时进行的，所以这里涉及到并发操作时对变量的保护问题。</p>
-<h2 id="mutex"><a href="#mutex" class="headerlink" title="mutex"></a>mutex</h2><p>在统计页面浏览次数时，我们可以使用一个变量 <code>pageView</code> 来表示页面的浏览次数，并用一个 <code>mutex</code> 锁来保护变量存取。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    pageView <span class="keyword">int</span></span><br><span class="line">    mutex sync.Mutex</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    mutex.Lock()</span><br><span class="line">    pageView++</span><br><span class="line">    mutex.Unlock()</span><br><span class="line">    fmt.Fprintf(w, <span class="string">"&lt;h1&gt;%v&lt;/h1&gt;"</span>, pageView)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    http.HandleFunc(<span class="string">"/"</span>, handler)</span><br><span class="line">    http.ListenAndServe(<span class="string">"localhost:8080"</span>, <span class="literal">nil</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="channel"><a href="#channel" class="headerlink" title="channel"></a>channel</h2><p>除了使用互斥锁来保护变量之外，我们来可以使用 <code>golang</code> 中特有的<code>unbuffered channel</code> 来获取页面浏览次数，我们在 <code>main</code> 函数中起一个 <code>goroutine</code> 来生产递增的 <code>nextID</code> ，每个 <code>nextID &lt;- i</code> 发送操作均会阻塞直到一个 <code>goroutine</code> 启动时通过 <code>&lt;-nextID</code> 来接收，这里因为使用了<code>unbuffered channel</code> ，所以保证了整个过程的原子性。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> nextID = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    fmt.Fprintf(w, <span class="string">"&lt;h1&gt;%v&lt;/h1&gt;"</span>, &lt;-nextID)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    http.HandleFunc(“/”, handler)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> i := <span class="number">0</span>; ; i++ &#123;</span><br><span class="line">            nextID &lt;- i</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">    http.ListenAndServe(<span class="string">"localhost:8080"</span>, <span class="literal">nil</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/25/Trie/index.html b/2018/06/25/Trie/index.html
deleted file mode 100644
index 9ebb89c..0000000
--- a/2018/06/25/Trie/index.html
+++ /dev/null
@@ -1,264 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Trie | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="假设我们要实现一个类似于有道词典这样的字典，开始时使用哈希表来存储键值对，后来在实现前缀搜索，模糊匹配等相关功能时，发现使用哈希表作为底层存储的数据结构有一个致命的缺点，基于哈希表的前缀搜索，模糊匹配实现难度非常之大，所以决定换一种数据结构来存储数据。下面我们来介绍一下 Trie 树， Trie 树也叫字典树，它非常适合我们上面说的场景，作为一种树形结构，还经常被用于统计，排序和保存大量的字符串等">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Trie">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/25/Trie/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="假设我们要实现一个类似于有道词典这样的字典，开始时使用哈希表来存储键值对，后来在实现前缀搜索，模糊匹配等相关功能时，发现使用哈希表作为底层存储的数据结构有一个致命的缺点，基于哈希表的前缀搜索，模糊匹配实现难度非常之大，所以决定换一种数据结构来存储数据。下面我们来介绍一下 Trie 树， Trie 树也叫字典树，它非常适合我们上面说的场景，作为一种树形结构，还经常被用于统计，排序和保存大量的字符串等">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://cdn-images-1.medium.com/max/1600/1*f89l46VKjKPgnecqOw4V_w.png">
-<meta property="og:updated_time" content="2018-06-26T08:47:30.860Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Trie">
-<meta name="twitter:description" content="假设我们要实现一个类似于有道词典这样的字典，开始时使用哈希表来存储键值对，后来在实现前缀搜索，模糊匹配等相关功能时，发现使用哈希表作为底层存储的数据结构有一个致命的缺点，基于哈希表的前缀搜索，模糊匹配实现难度非常之大，所以决定换一种数据结构来存储数据。下面我们来介绍一下 Trie 树， Trie 树也叫字典树，它非常适合我们上面说的场景，作为一种树形结构，还经常被用于统计，排序和保存大量的字符串等">
-<meta name="twitter:image" content="https://cdn-images-1.medium.com/max/1600/1*f89l46VKjKPgnecqOw4V_w.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Trie"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Trie
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-25T14:25:54.000Z" itemprop="datePublished">
-        Jun 25, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>假设我们要实现一个类似于有道词典这样的字典，开始时使用哈希表来存储键值对，后来在实现前缀搜索，模糊匹配等相关功能时，发现使用哈希表作为底层存储的数据结构有一个致命的缺点，基于哈希表的前缀搜索，模糊匹配实现难度非常之大，所以决定换一种数据结构来存储数据。下面我们来介绍一下 <code>Trie</code> 树， <code>Trie</code> 树也叫字典树，它非常适合我们上面说的场景，作为一种树形结构，还经常被用于统计，排序和保存大量的字符串等场景。</p>
-<p><img src="https://cdn-images-1.medium.com/max/1600/1*f89l46VKjKPgnecqOw4V_w.png" alt="trie"></p>
-<h2 id="data-structure"><a href="#data-structure" class="headerlink" title="data structure"></a>data structure</h2><p><code>Trie</code> 是一棵R叉树，可以用于保存大量的字符串，每棵树都有一个根节点（ <code>root</code> ）。非叶节点存储一个 <code>rune</code> ，除了指向父节点的指针 <code>parent</code> 之外，并还包含一系列子节点 <code>children</code> ，使用 <code>map</code> 来存储。叶节点标志着一个字符串的结束，其 <code>term</code> 标记为 <code>true</code> ，叶节点中还可以存储一些元数据（ <code>meta</code> ），来表示该字符串的含义。从根节点开始一直到叶节点就可以形成一个完整的字符串。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Node <span class="keyword">struct</span> &#123;</span><br><span class="line">    val      <span class="keyword">rune</span></span><br><span class="line">    term     <span class="keyword">bool</span></span><br><span class="line">    depth    <span class="keyword">int</span></span><br><span class="line">    meta     <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">    parent   *Node</span><br><span class="line">    children <span class="keyword">map</span>[<span class="keyword">rune</span>]*Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Trie <span class="keyword">struct</span> &#123;</span><br><span class="line">    root *Node</span><br><span class="line">    size <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">()</span> *<span class="title">Trie</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Trie&#123;</span><br><span class="line">        root: &amp;Node&#123;depth: <span class="number">0</span>, children: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">rune</span>]*Node)&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="helper-function"><a href="#helper-function" class="headerlink" title="helper function"></a>helper function</h2><p>为了方便后面的搜索操作，我们需要实现两个 <code>helper function</code> ，第一个就是计算一个字符串的掩码，例如对 <code>apple</code> 计算掩码时，分别对’a’，’p’，’p’，’l’，’e’ 这几个 <code>rune</code> 进行位运算，最后返回一个 <code>uint64</code> ，该掩码在搜索中起着非常重要的作用，因为每个节点都会存储一个掩码（ <code>mask</code> ），我们可以利用该掩码判断该节点及后续字节点存储了什么字符。<code>findNode</code> 方法帮助我们搜索 <code>runes</code> 字符数组中最后一个字符在树中对应的节点。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">maskruneslice</span><span class="params">(rs []<span class="keyword">rune</span>)</span> <span class="title">uint64</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> m <span class="keyword">uint64</span></span><br><span class="line">    <span class="keyword">for</span> _, r := <span class="keyword">range</span> rs &#123;</span><br><span class="line">        m |= <span class="keyword">uint64</span>(<span class="number">1</span>) &lt;&lt; <span class="keyword">uint64</span>(r-<span class="string">'a'</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> m</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">findNode</span><span class="params">(node *Node, runes []<span class="keyword">rune</span>)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(runes) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> node</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    n, ok := node.Children()[runes[<span class="number">0</span>]]</span><br><span class="line">    <span class="keyword">if</span> !ok &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> nrunes []<span class="keyword">rune</span></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(runes) &gt; <span class="number">1</span> &#123;</span><br><span class="line">        nrunes = runes[<span class="number">1</span>:]</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        nrunes = runes[<span class="number">0</span>:<span class="number">0</span>]</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> findNode(n, nrunes)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Basic-Operation"><a href="#Basic-Operation" class="headerlink" title="Basic Operation"></a>Basic Operation</h2><p><code>Trie</code> 树的基本操作有三个，<code>Add</code> ，<code>Find</code> 和 <code>Del</code> 。</p>
-<p><code>Add</code> 方法将 <code>key</code> 字符串加入到树中。对于每一个要加入树中的字符串中的 <code>rune</code> ， 我们构造一个节点，如果相应的 <code>rune</code> 已经存在，此时只需要更新其 <code>mask</code> 值，如果该 <code>rune</code> 不存在，则构建一个中间节点 <code>node = node.NewChild(r, bitmask, nil, false)</code> ，在所有中间节点都构建完毕之后，我们构建一个叶节点结束 <code>Add</code> 操作，叶节点的 <code>val</code> 值设为 <code>nul</code> ，<code>term</code> 为 <code>true</code> ，并存储相应的元数据 <code>meta</code> 。 </p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> nul = <span class="number">0x0</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Add</span><span class="params">(key <span class="keyword">string</span>, meta <span class="keyword">interface</span>)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    t.size++</span><br><span class="line">    runes := []<span class="keyword">rune</span>(key)</span><br><span class="line">    bitmask := maskruneslice(runes)</span><br><span class="line">    node := t.root</span><br><span class="line">    node.mask |= bitmask</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> runes &#123;</span><br><span class="line">        r := runes[i]</span><br><span class="line">        bitmask := maskruneslice(runes[i:])</span><br><span class="line">        <span class="keyword">if</span> n, ok := node.children[r]; ok &#123;</span><br><span class="line">            node = n</span><br><span class="line">            node.mask |= bitmask</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            node = node.NewChild(r, bitmask, <span class="literal">nil</span>, <span class="literal">false</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    node = node.NewChild(nul, <span class="number">0</span>, meta, <span class="literal">true</span>)</span><br><span class="line">    <span class="keyword">return</span> node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">NewChild</span><span class="params">(val <span class="keyword">rune</span>, bitmask <span class="keyword">uint64</span>, meta <span class="keyword">interface</span>&#123;&#125;, term <span class="keyword">bool</span>)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    node := &amp;Node&#123;</span><br><span class="line">        val: val,</span><br><span class="line">        bitmask: bitmask,</span><br><span class="line">        term: term,</span><br><span class="line">        meta: meta,</span><br><span class="line">        parent: n,</span><br><span class="line">        children: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">rune</span>]*Node),</span><br><span class="line">        depth: n.depth + <span class="number">1</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    n.children[val] = node</span><br><span class="line">    n.mask |= bitmask</span><br><span class="line">    <span class="keyword">return</span> node</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Find</code> 方法判断一个特定的字符串是否出现在该树中，我们先通过 <code>findNode</code> 找到相应的 <code>node</code> ，<code>Find</code> 方法用于查找一个完整的字符串，例如我们要查找 <code>app</code> ，但树中只有 <code>apple</code> 这个字符串，所以 <code>findNode</code> 调用时应该返回说不存在 <code>app</code> 这个字符串。当查找 <code>app</code> 这个字符串时，<code>findNode</code> 方法会返回最后一个 <code>p</code> 对应的节点，但这并不说明 <code>app</code> 存在于树中，我们还需要判断该节点是否为叶节点 <code>node.term == true</code> ，如果不是叶节点，则返回 <code>nil</code> 。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Find</span><span class="params">(key <span class="keyword">string</span>)</span> <span class="params">(*Node, <span class="keyword">bool</span>)</span></span> &#123;</span><br><span class="line">    node := findNode(t.Root(), []<span class="keyword">rune</span>(key))</span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, <span class="literal">false</span></span><br><span class="line">    &#125;</span><br><span class="line">    node, ok := node.Children()[nul]</span><br><span class="line">    <span class="keyword">if</span> !ok || !node.term &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, <span class="literal">false</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> node, <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>Remove</code> 方法同样通过 <code>findNode</code> 方法找到相应的节点，然后从该节点向根节点的方向依次删除相应的 <code>rune</code> ，主要目的是为了更新每个中间节点的<code>mask</code> 值。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Remove</span><span class="params">(key <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> (</span><br><span class="line">        i <span class="keyword">int</span></span><br><span class="line">        rs = []<span class="keyword">rune</span>(key)</span><br><span class="line">        node = findNode(t.Root(), []<span class="keyword">rune</span>(key))</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    t.size--</span><br><span class="line">    <span class="keyword">for</span> n := node.Parent(); p != <span class="literal">nil</span>; n = n.Parent() &#123;</span><br><span class="line">        i++</span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(n.Children()) &gt; <span class="number">1</span> &#123;</span><br><span class="line">            r := rs[<span class="built_in">len</span>(rs)-i]</span><br><span class="line">            n.RemoveChild(r)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">RemoveChild</span><span class="params">(r <span class="keyword">rune</span>)</span></span> &#123;</span><br><span class="line">    <span class="built_in">delete</span>(n.children, r)</span><br><span class="line">    <span class="keyword">for</span> nd := n.parent; nd != <span class="literal">nil</span>; nd = nd.parent &#123;</span><br><span class="line">        nd.mask ^= nd.mask</span><br><span class="line">        nd.mask |= <span class="keyword">uint64</span>(<span class="number">1</span>) &lt;&lt; <span class="keyword">uint64</span>(nd.val - <span class="string">'a'</span>)</span><br><span class="line">        <span class="keyword">for</span> _, c := <span class="keyword">range</span> nd.children &#123;</span><br><span class="line">            nd.mask |= c.mask</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Collect"><a href="#Collect" class="headerlink" title="Collect"></a>Collect</h2><p>有时候我们搜索单词的时候只记得该单词的前缀，例如我们要搜索 <code>append</code> 这个单词，但是我们只记得 <code>app</code> 这个前缀，我们可以使用 <code>collect</code> 方法帮我们收集所有 <code>app</code> 开头的单词，换句话说就是特定节点下面所有可能的叶节点的集合，开始收集时我们构造一个队列，该队列中仅有 <code>node</code> 一个节点，然后使用广度优先搜索的方式（层序遍历），首先将队列中的第一个节点出队，然后将该节点所有的子节点加入该队列中，如果节点为叶节点，则从该叶节点开始一直向上遍历到根节点的下一层节点（ <code>p.depth == 1</code> ），直到完成所有单词的收集为止。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">collect</span><span class="params">(node *Node)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> (</span><br><span class="line">        keys []<span class="keyword">string</span></span><br><span class="line">        n    *Node</span><br><span class="line">        i    <span class="keyword">int</span></span><br><span class="line">    )</span><br><span class="line">    nodes := []*Node&#123;node&#125;</span><br><span class="line">    <span class="keyword">for</span> l := <span class="built_in">len</span>(nodes); l != <span class="number">0</span>; l = <span class="built_in">len</span>(nodes) &#123;</span><br><span class="line">        i := l - <span class="number">1</span></span><br><span class="line">        n = nodes[i]</span><br><span class="line">        nodes = nodes[:i]</span><br><span class="line">        <span class="keyword">for</span> _, c := <span class="keyword">range</span> n.children &#123;</span><br><span class="line">            nodes = <span class="built_in">append</span>(nodes, c)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> n.term &#123;</span><br><span class="line">            word := <span class="string">""</span></span><br><span class="line">            <span class="keyword">for</span> p := n.parent; p.depth != <span class="number">0</span>; p = p.parent &#123;</span><br><span class="line">                word = <span class="keyword">string</span>(p.val) + word</span><br><span class="line">            &#125;</span><br><span class="line">            keys = <span class="built_in">append</span>(keys, word)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> keys</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="Fuzzy-Collect"><a href="#Fuzzy-Collect" class="headerlink" title="Fuzzy Collect"></a>Fuzzy Collect</h2><p>除了比较准确的前缀匹配之外，有时候我们可能还需要模糊匹配，再举 <code>append</code> 这个单词为例子，我们可能只记得这个单词包含了 <code>apd</code> 这样的模式，使用 <code>Trie</code> 树我们可以非常轻松地实现模糊匹配功能，<code>fuzzycollect</code> 同样利用层序遍历，在每一个循环开始时，对队列中的第一个节点进行出队操作，如果相应的掩码不包含在正在遍历的节点中 <code>(p.node.mask &amp; m) != m</code> ，说明其后面的节点中不包含所有 <code>partial</code> 中包含的 <code>rune</code> 值，直接进入下一个循环 ，如果 <code>p.idx == len(partial)</code> ，说明我们找到了与 <code>partial</code> 相匹配的一个单词，此时进行 <code>collect</code> 操作 。最后同样需要将该节点的子节点加入队列中以进行下一轮的层序遍历。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> potentialSubtree <span class="keyword">struct</span> &#123;</span><br><span class="line">    idx <span class="keyword">int</span></span><br><span class="line">    node *Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">fuzzycollect</span><span class="params">(node *Node, partial []<span class="keyword">rune</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> (</span><br><span class="line">        m    <span class="keyword">uint64</span></span><br><span class="line">        i    <span class="keyword">int</span></span><br><span class="line">        p    potentialSubtree</span><br><span class="line">        keys []<span class="keyword">string</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    potential := []potentialSubtree&#123;potentialSubtree&#123;<span class="number">0</span>, node&#125;&#125;</span><br><span class="line">    <span class="keyword">for</span> l := <span class="built_in">len</span>(potential); l &gt; <span class="number">0</span>; l = <span class="built_in">len</span>(potential) &#123;</span><br><span class="line">        i := l - <span class="number">1</span></span><br><span class="line">        p = potential[i]</span><br><span class="line">        potential = potential[:i]</span><br><span class="line">        m = maskruneslice(partial[p.idx:])</span><br><span class="line">        <span class="keyword">if</span> (p.node.mask &amp; m) != m &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> p.node.val == partial[p.idx] &#123;</span><br><span class="line">            p.idx++</span><br><span class="line">            <span class="keyword">if</span> p.idx == <span class="built_in">len</span>(partial) &#123;</span><br><span class="line">                keys = <span class="built_in">append</span>(keys, collect(p.node)...)</span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> _, c := <span class="keyword">range</span> p.node.children &#123;</span><br><span class="line">            potential = <span class="built_in">append</span>(potential, potentialSubtree&#123;node: c, idx: p.idx&#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> keys</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="search"><a href="#search" class="headerlink" title="search"></a>search</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ByKeys []<span class="keyword">string</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a ByKeys)</span> <span class="title">Len</span><span class="params">()</span> <span class="title">int</span></span>           &#123; <span class="keyword">return</span> <span class="built_in">len</span>(a) &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a ByKeys)</span> <span class="title">Swap</span><span class="params">(i, j <span class="keyword">int</span>)</span></span>      &#123; a[i], a[j] = a[j], a[i] &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a ByKeys)</span> <span class="title">Less</span><span class="params">(i, j <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123; <span class="keyword">return</span> <span class="built_in">len</span>(a[i]) &lt; <span class="built_in">len</span>(a[j]) &#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">HasKeysWithPrefix</span><span class="params">(key <span class="keyword">string</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    node := findNode(t.Root(), []<span class="keyword">rune</span>(key))</span><br><span class="line">    <span class="keyword">return</span> node != <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t Trie)</span> <span class="title">FuzzySearch</span><span class="params">(pre <span class="keyword">string</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    keys := fuzzycollect(t.Root(), []<span class="keyword">rune</span>(pre))</span><br><span class="line">    sort.Sort(ByKeys(keys))</span><br><span class="line">    <span class="keyword">return</span> keys</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t Trie)</span> <span class="title">PrefixSearch</span><span class="params">(pre <span class="keyword">string</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    node := findNode(t.Root(), []<span class="keyword">rune</span>(pre))</span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> collect(node)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Keys</span><span class="params">()</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> t.PrefixSearch(<span class="string">""</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/26/CGO/index.html b/2018/06/26/CGO/index.html
deleted file mode 100644
index 89f243f..0000000
--- a/2018/06/26/CGO/index.html
+++ /dev/null
@@ -1,285 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>CGO | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="cgo is an amazing technology which allows Go programs to interoperate with C libraries. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="CGO">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/26/CGO/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="cgo is an amazing technology which allows Go programs to interoperate with C libraries. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-07-03T12:18:05.760Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="CGO">
-<meta name="twitter:description" content="cgo is an amazing technology which allows Go programs to interoperate with C libraries. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-CGO"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      CGO
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-26T08:34:33.000Z" itemprop="datePublished">
-        Jun 26, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>cgo is an amazing technology which allows Go programs to interoperate with C libraries. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package.</p>
-<p>C code and Go code live in two different universes, cgo traverses the boundary between them. The transition is not free and depending on where it exists in your code, the cost could be inconsequential, or substantial.  </p>
-<p>There are some cases where cgo is unavoidable, most notably where you have to interoperate with a graphics driver or windowing system what is only available as a binary blob.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> rand</span><br><span class="line"></span><br><span class="line"><span class="comment">// #include &lt;stdlib.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Random</span><span class="params">()</span> <span class="title">int</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> r C.long = C.random()</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">int</span>(r)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Seed</span><span class="params">(i <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    C.srandom(C.<span class="keyword">uint</span>(i))  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="cgo-directives"><a href="#cgo-directives" class="headerlink" title="cgo directives"></a>cgo directives</h2><p>cgo is not a language nor a compiler. It’s a Foreign Function Interface (FFI), a mechanism we can use in Go to invoke functions and services written in a different language, specifically C.</p>
-<p>The comment block right above the import “C” instruction is called a “preamble” and can contain actual C code, in this case an header inclusion. Once imported, the “C” pseudo-package lets us “jump” to the foreign code. You can build the example by invoking go build, the same as if it was plain Go.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include &lt;stdio.h&gt;</span></span><br><span class="line"><span class="comment">// #include &lt;errno.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br></pre></td></tr></table></figure>
-<p>CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS, LDFLAGS may be defined with pseudo <code>#cgo</code> directives within these comments to tweak the behavior of the C, C++ or Fortran compiler. Values defined in multiple directives are concatenated together. The directive can include a list of build constraints limiting its effect to systems satisfying one of the constraints.</p>
-<p>cgo recognizes this comment. Any lines starting with <code>#cgo</code> followed by a space character are removed; these become directives for cgo. The remaining lines are used as a header when compiling the C parts of the package. In this case those lines are just a single <code>#include</code> statement, but they can be almost any C code. The <code>cgo</code> directives are used to provide flags for the compiler and linker when building the C parts of the package.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo CFLAGS: -DPNG_DEBUG=1</span></span><br><span class="line"><span class="comment">// #cgo amd64 386 CFLAGS: -D86=1</span></span><br><span class="line"><span class="comment">// #cgo LDFLAGS: -lpng</span></span><br><span class="line"><span class="comment">// #include &lt;png.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br></pre></td></tr></table></figure>
-<p>Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config tool using a ‘#cgo pkg-config:’ directive followed by the package names. For example:</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo pkg-config: png cairo</span></span><br><span class="line"><span class="comment">// #include &lt;png.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo LDFLAGS -L$&#123;SRCDIR&#125;/libs -l foo</span></span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo LDFLAGS -L/go/src/foo/libs -l foo</span></span><br></pre></td></tr></table></figure>
-<p><code>-L</code> is the path to the directories containing the libraries. A search path for libraries.<br><code>-l</code> is the name of the library you want to link to.</p>
-<p>For instance, if you want to link to the library  <code>~/libs/libabc.a</code>  you’d add:</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-L$(HOME)/libs -labc</span><br></pre></td></tr></table></figure>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">| file                            | compiler          |</span><br><span class="line">| ------------------------------- |:-----------------:|</span><br><span class="line">| xxx.c, xxx.s, xxx.S             | C compiler        |</span><br><span class="line">| xxx.cc, xxx.cpp, xxx.cxx        | C++ compiler      |</span><br><span class="line">| xxx.f, xxx.F, xxx.for, xxx.f90  | fortran compiler  |</span><br><span class="line"></span><br><span class="line">Any .h, .hh, .hpp or .hxx files will not be compiled separately, but if these header files are changed, the C and C++ files will be recompiled.</span><br></pre></td></tr></table></figure>
-<h2 id="tips-about-pkg-config"><a href="#tips-about-pkg-config" class="headerlink" title="tips about pkg-config"></a>tips about pkg-config</h2><p>pkg-config: return metainformation about installed libraries.</p>
-<p>The <code>pkg-config</code> program is used to retrieve information about installed libraries in the system. It is typically used to compile and link against one or more libraries. Here is a typical usage scenario in a Makefile:</p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">program: program.c</span><br><span class="line">    cc program.c `pkg-config --cflags --libs gnomeui`</span><br></pre></td></tr></table></figure>
-<p><code>pkg-config</code> retrieves information about packages from special metadata files. These files are named after the package, and has a <code>.pc</code> extension. On most systems, <code>pkg-config</code> looks in <code>/usr/lib/pkgconfig</code> , <code>/usr/share/pkgconfig</code> , <code>/usr/local/lib/pkgconfig</code> and <code>/usr/local/share/pkgconfig</code> for these files. It will additionally look in the colon-separated (on Windows, semi-colon-separated) list of directories specified by the <code>PKG_CONFIG_PATH</code> environment variable.</p>
-<p>The package name specified on the <code>pkg-config</code> command line is defined to be the name of the metadata file, minus the <code>.pc</code> extension. If a library can install multiple versions simultaneously, it must give each version its own name (for example, GTK 1.2 might have the package name “gtk+” while GTK 2.0 has “gtk-2.0”).</p>
-<p>In addition to specifying a package name on the command line, the full path to a given <code>.pc</code> file may be given instead. This allows a user to directly query a particular <code>.pc</code> file.</p>
-<p><code>/usr/local/lib/pkgconfig/libuv.pc</code></p>
-<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">prefix=/usr/local/Cellar/libuv/1.20.0</span><br><span class="line">exec_prefix=$&#123;prefix&#125;</span><br><span class="line">libdir=$&#123;exec_prefix&#125;/lib</span><br><span class="line">includedir=$&#123;prefix&#125;/include</span><br><span class="line"></span><br><span class="line">Name: libuv</span><br><span class="line">Version: 1.20.0</span><br><span class="line">Description: multi-platform support library with a focus on asynchronous I/O.</span><br><span class="line">URL: http://libuv.org/</span><br><span class="line"></span><br><span class="line">Libs: -L$&#123;libdir&#125; -luv -lphread -ldl</span><br><span class="line">Cflags: -I$&#123;includedir&#125;</span><br></pre></td></tr></table></figure>
-<h2 id="basic-data-type-conversion"><a href="#basic-data-type-conversion" class="headerlink" title="basic data type conversion"></a>basic data type conversion</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">| C                   | Go              |</span><br><span class="line">| ------------------- |:---------------:|</span><br><span class="line">| <span class="keyword">char</span>                | C.<span class="keyword">char</span>          |</span><br><span class="line">| <span class="keyword">signed</span> <span class="keyword">char</span>         | C.schar         |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">char</span>       | C.uchar         |</span><br><span class="line">| <span class="keyword">short</span>               | C.<span class="keyword">short</span>         |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">short</span>      | C.ushort        |</span><br><span class="line">| <span class="keyword">int</span>                 | C.<span class="keyword">int</span>           |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">int</span>        | C.uint          |</span><br><span class="line">| <span class="keyword">long</span>                | C.<span class="keyword">long</span>          |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">long</span>       | C.ulong         |</span><br><span class="line">| <span class="keyword">long</span> <span class="keyword">long</span>           | C.longlong      |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="keyword">long</span>  | C.ulonglong     |</span><br><span class="line">| <span class="keyword">float</span>               | C.<span class="keyword">float</span>         |</span><br><span class="line">| <span class="keyword">double</span>              | C.<span class="keyword">double</span>        |</span><br><span class="line">| <span class="keyword">complex</span> <span class="keyword">float</span>       | C.complexfloat  |</span><br><span class="line">| <span class="keyword">complex</span> <span class="keyword">double</span>      | C.complexdouble |</span><br><span class="line">| <span class="keyword">long</span> <span class="keyword">long</span>           | C.longlong      |</span><br><span class="line">| <span class="keyword">void</span> *              | unsafe.Pointer  |</span><br><span class="line">| <span class="keyword">__int128_t</span>          | [<span class="number">16</span>]byte        |</span><br><span class="line">| <span class="keyword">__uint128_t</span>         | [<span class="number">16</span>]byte        |</span><br><span class="line">| few special C types | uintptr         |</span><br></pre></td></tr></table></figure>
-<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">| C                | Go                |</span><br><span class="line">| ---------------- |:-----------------:|</span><br><span class="line">| <span class="keyword">sizeof</span>(T)        | C.sizeof_T        |</span><br><span class="line">| <span class="keyword">sizeof</span>(struct T) | C.sizeof_struct_T |</span><br><span class="line">| <span class="class"><span class="keyword">struct</span> <span class="title">X</span>         | <span class="title">C</span>.<span class="title">struct_X</span>        |</span></span><br><span class="line"><span class="class">| <span class="title">union</span> <span class="title">X</span>          | <span class="title">C</span>.<span class="title">union_X</span>         |</span></span><br><span class="line"><span class="class">| <span class="title">enum</span> <span class="title">X</span>           | <span class="title">C</span>.<span class="title">enum_X</span>          |</span></span><br></pre></td></tr></table></figure>
-<h2 id="string-conversion-between-C-and-Go"><a href="#string-conversion-between-C-and-Go" class="headerlink" title="string conversion between C and Go"></a>string conversion between C and Go</h2><p>Unlike Go, C doesn’t have an explicit string type. Strings in C are represented by a zero-terminated array of chars. Conversion between Go and C strings is done with the C.CString, C.GoString, and C.GoStringN functions. These conversions make a copy of the string data.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Go string to C string</span></span><br><span class="line"><span class="comment">// The C string is allocated in the C heap using malloc.</span></span><br><span class="line"><span class="comment">// It is the caller's responsibility to arrange for it to be</span></span><br><span class="line"><span class="comment">// freed, such as by calling C.free (be sure to include stdlib.h if C.free is needed).</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">C</span>.<span class="title">CString</span><span class="params">(<span class="keyword">string</span>)</span> *<span class="title">C</span>.<span class="title">char</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">// <span class="title">Go</span> []<span class="title">byte</span> <span class="title">slice</span> <span class="title">to</span> <span class="title">C</span> <span class="title">array</span></span></span><br><span class="line"><span class="function">// <span class="title">The</span> <span class="title">C</span> <span class="title">array</span> <span class="title">is</span> <span class="title">allocated</span> <span class="title">in</span> <span class="title">the</span> <span class="title">C</span> <span class="title">heap</span> <span class="title">using</span> <span class="title">malloc</span>.</span></span><br><span class="line"><span class="function">// <span class="title">It</span> <span class="title">is</span> <span class="title">the</span> <span class="title">caller</span>'<span class="title">s</span> <span class="title">responsibility</span> <span class="title">to</span> <span class="title">arrange</span> <span class="title">for</span> <span class="title">it</span> <span class="title">to</span> <span class="title">be</span></span></span><br><span class="line"><span class="function">// <span class="title">freed</span>, <span class="title">such</span> <span class="title">as</span> <span class="title">by</span> <span class="title">calling</span> <span class="title">C</span>.<span class="title">free</span> <span class="params">(be sure to include stdlib.h <span class="keyword">if</span> C.free is needed)</span>.</span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">C</span>.<span class="title">CBytes</span><span class="params">([]<span class="keyword">byte</span>)</span> <span class="title">unsafe</span>.<span class="title">Pointer</span></span></span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// C string to Go string</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">C</span>.<span class="title">GoString</span><span class="params">(*C.char)</span> <span class="title">string</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">// <span class="title">C</span> <span class="title">data</span> <span class="title">with</span> <span class="title">explicit</span> <span class="title">length</span> <span class="title">to</span> <span class="title">Go</span> <span class="title">string</span></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">C</span>.<span class="title">GoStringN</span><span class="params">(*C.char, C.<span class="keyword">int</span>)</span> <span class="title">string</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">// <span class="title">C</span> <span class="title">data</span> <span class="title">with</span> <span class="title">explicit</span> <span class="title">length</span> <span class="title">to</span> <span class="title">Go</span> []<span class="title">byte</span></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">C</span>.<span class="title">GoBytes</span><span class="params">(unsafePinter, C.<span class="keyword">int</span>)</span> []<span class="title">byte</span></span></span><br></pre></td></tr></table></figure>
-<h2 id="memory-management"><a href="#memory-management" class="headerlink" title="memory management"></a>memory management</h2><p>Memory allocations made by C code are not known to Go’s memory manager. When you create a C string with C.CString (or any C memory allocation) you must remember to free the memory when you’re done with it by calling C.free.</p>
-<p>The call to C.CString returns a pointer to the start of the char array, so before the function exits we convert it to an unsafe.Pointer and release the memory allocation with C.free. A common idiom in cgo programs is to defer the free immediately after allocating (especially when the code that follows is more complex than a single function call), as in this rewrite of Print:</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Print</span><span class="params">(s <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    cs := C.CString(s)</span><br><span class="line">    <span class="keyword">defer</span> C.free(unsafe.Pointer(cs))</span><br><span class="line">    C.fputs(cs, (*C.FILE)(C.stdout))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p> A standard way to do this follows.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include &lt;stdlib.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"unsafe"</span></span><br><span class="line">...</span><br><span class="line">    <span class="keyword">var</span> cmsg *C.char = C.CString(<span class="string">"hi"</span>)</span><br><span class="line">    <span class="keyword">defer</span> C.free(unsafe.Pointer(cmsg))</span><br><span class="line">    <span class="comment">// do something with the C string</span></span><br></pre></td></tr></table></figure>
-<h2 id="handle-C-return-error-in-Go"><a href="#handle-C-return-error-in-Go" class="headerlink" title="handle C return error in Go"></a>handle C return error in Go</h2><p>Any C function (even void functions) may be called in a multiple assigned context to retrieve both the return value (if any) and the C errno variable as an error (use _ to skip the result value if the function returns void). For example.</p>
-<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">The sqrt() function compute the non-negative square root of x</span></span><br><span class="line"><span class="comment">sqrt(-0) returns -0</span></span><br><span class="line"><span class="comment">sqrt(x) returns a NaN and generates a domain error for x &lt; 0</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;math.h&gt;</span></span></span><br><span class="line"><span class="keyword">double</span></span><br><span class="line"><span class="built_in">sqrt</span>(<span class="keyword">double</span> x);</span><br></pre></td></tr></table></figure>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">n, err := C.sqrt(<span class="number">-1</span>)</span><br><span class="line">_, err = C.voidFunc()</span><br></pre></td></tr></table></figure>
-<h2 id="call-Go-code-in-C-code"><a href="#call-Go-code-in-C-code" class="headerlink" title="call Go code in C code"></a>call Go code in C code</h2><p>Using //export in a file places a restriction on the preamble: since it is copied into two different C. Output files, it must not contain any definitions, only declarations.</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//export MyFunction</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">MyFunction</span><span class="params">(arg1, arg2 <span class="keyword">int</span>, arg3 <span class="keyword">string</span>)</span> <span class="title">int64</span></span> &#123;...&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//export MyFunction2</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">MyFunction2</span><span class="params">(arg1, arg2 <span class="keyword">int</span>, arg3 <span class="keyword">string</span>)</span> <span class="params">(<span class="keyword">int64</span>, *C.char)</span></span> &#123;...&#125;</span><br></pre></td></tr></table></figure>
-<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">extern</span> int64 <span class="title">MyFunction</span><span class="params">(<span class="keyword">int</span> arg1, <span class="keyword">int</span> arg2, GoString arg3)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">extern</span> struct MyFunction2_return <span class="title">MyFunction2</span><span class="params">(<span class="keyword">int</span> arg1, <span class="keyword">int</span> arg2, GoString arg3)</span></span>;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/06/27/Graphviz/index.html b/2018/06/27/Graphviz/index.html
deleted file mode 100644
index 8241c02..0000000
--- a/2018/06/27/Graphviz/index.html
+++ /dev/null
@@ -1,256 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Graphviz | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="最近看了许多比较酷炫的数据结构的实现，例如 Trie ， Skip List ，B-Tree 等，看代码的时候经常会想，要是有什么工具可以帮助我们将内存中的结构体绘制出来就好了，搜了一下 github ，发现早已经有大佬帮我们实现过了。 下面以二叉搜索树为例，来看一下如何使用 graphviz 绘制内存中的结构体。二叉树的定义非常简单，每个节点都有一个左节点和右节点，用于指向自己的左子树和右子树。">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="Graphviz">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/06/27/Graphviz/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="最近看了许多比较酷炫的数据结构的实现，例如 Trie ， Skip List ，B-Tree 等，看代码的时候经常会想，要是有什么工具可以帮助我们将内存中的结构体绘制出来就好了，搜了一下 github ，发现早已经有大佬帮我们实现过了。 下面以二叉搜索树为例，来看一下如何使用 graphviz 绘制内存中的结构体。二叉树的定义非常简单，每个节点都有一个左节点和右节点，用于指向自己的左子树和右子树。">
-<meta property="og:locale" content="default">
-<meta property="og:image" content="https://image.ibb.co/bPod9o/output.png">
-<meta property="og:updated_time" content="2018-06-27T13:45:10.019Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Graphviz">
-<meta name="twitter:description" content="最近看了许多比较酷炫的数据结构的实现，例如 Trie ， Skip List ，B-Tree 等，看代码的时候经常会想，要是有什么工具可以帮助我们将内存中的结构体绘制出来就好了，搜了一下 github ，发现早已经有大佬帮我们实现过了。 下面以二叉搜索树为例，来看一下如何使用 graphviz 绘制内存中的结构体。二叉树的定义非常简单，每个节点都有一个左节点和右节点，用于指向自己的左子树和右子树。">
-<meta name="twitter:image" content="https://image.ibb.co/bPod9o/output.png">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-Graphviz"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      Graphviz
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-06-27T13:37:09.000Z" itemprop="datePublished">
-        Jun 27, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>最近看了许多比较酷炫的数据结构的实现，例如 <code>Trie</code> ， <code>Skip List</code> ，<code>B-Tree</code> 等，看代码的时候经常会想，要是有什么工具可以帮助我们将内存中的结构体绘制出来就好了，搜了一下 <code>github</code> ，发现早已经有大佬帮我们实现过了。</p>
-<p>下面以二叉搜索树为例，来看一下如何使用 <code>graphviz</code> 绘制内存中的结构体。二叉树的定义非常简单，每个节点都有一个左节点和右节点，用于指向自己的左子树和右子树。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Node <span class="keyword">struct</span> &#123;</span><br><span class="line">    val   <span class="keyword">int</span></span><br><span class="line">    left  *Node</span><br><span class="line">    right *Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">Insert</span><span class="params">(val <span class="keyword">int</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> errors.New(<span class="string">"Cannot insert a value into a nil tree"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">switch</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> val == n.val:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    <span class="keyword">case</span> val &lt; n.val:</span><br><span class="line">        <span class="keyword">if</span> n.left == <span class="literal">nil</span> &#123;</span><br><span class="line">            n.left = &amp;Node&#123;val: val&#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> n.left.Insert(val)</span><br><span class="line">    <span class="keyword">case</span> val &gt; n.val:</span><br><span class="line">        <span class="keyword">if</span> n.right == <span class="literal">nil</span> &#123;</span><br><span class="line">            n.right = &amp;Node&#123;val: val&#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> n.right.Insert(val)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Tree <span class="keyword">struct</span> &#123;</span><br><span class="line">    Root  *Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Tree)</span> <span class="title">Insert</span><span class="params">(val <span class="keyword">int</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> t.root == <span class="literal">nil</span> &#123;</span><br><span class="line">        t.Root = &amp;Node&#123;val: val&#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> t.Root.Insert(value)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>在 <code>main</code> 函数中我们构造一个二叉树，并向该树中随意插入一些值，最后我们使用 <code>memviz.Map(os.Stdout, &amp;tree)</code> 将该树对应的 <code>DOT</code> 形态输出到标准输出中。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">"github.com/bradleyjkemp/memviz"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    tree := &amp;Tree&#123;&#125;</span><br><span class="line">    values := []<span class="keyword">int</span>&#123;<span class="number">4</span>, <span class="number">2</span>, <span class="number">6</span>, <span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>&#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(values); i++ &#123;</span><br><span class="line">        err := tree.Insert(values[i])</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Fatal(<span class="string">"Error inserting value '"</span>, values[i], <span class="string">"': "</span>, err)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    memviz.Map(os.Stdout, &amp;tree)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>利用 <code>unix pipe</code> 将 <code>go run main.go</code> 得到的结果输入到 <code>dot</code> 命令中。</p>
-<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ go run main.go | dot -Tpng -o output.png | open output.png</span><br></pre></td></tr></table></figure>
-<p><img src="https://image.ibb.co/bPod9o/output.png" alt="graphviz"></p>
-<p> <code>dot</code> 命令相当于 <code>graphviz</code> 的一个子命令，它专门用于绘制有向图，除了 <code>dot</code> 之外，还有 <code>neato</code> ，<code>twopi</code> ，<code>circo</code> ，<code>fdp</code> ，<code>sfdp</code> ，<code>patchword</code> 和<code>osage</code> ，它们的用法与 <code>dot</code> 完全一致，只是它们的用处稍稍不同，例如 <code>neato</code> 比较适合用来绘制无向图。</p>
-<p>下面我们来看一下（ <code>memviz.Map(os.Stdout, &amp;tree)</code> ）的实现，该函数的实现主要依靠 <code>golang</code> 中的反射机制（ <code>reflect</code> ），利用 <code>reflect</code> 可以在运行时审查元素的类型，然后根据其类型，构造符合 <code>dot</code> 的语法的模版就行了。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Map</span><span class="params">(w io.Writer, is ...<span class="keyword">interface</span>&#123;&#125;)</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> iVals []reflect.Value</span><br><span class="line">    <span class="keyword">for</span> _, i := <span class="keyword">range</span> is &#123;</span><br><span class="line">        iVal := reflect.ValueOf(i)</span><br><span class="line">        <span class="keyword">if</span> !iVal.CanAddr() &#123;</span><br><span class="line">            <span class="keyword">if</span> iVal.Kind() != reflect.Ptr &amp;&amp; iVal.Kind() != reflect.Interface &#123;</span><br><span class="line">                fmt.Fprint(w, <span class="string">"error: cannot map unaddressable value"</span>)</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">             &#125;</span><br><span class="line">             iVal = iVal.Elem()</span><br><span class="line">        &#125;</span><br><span class="line">        iVals = <span class="built_in">append</span>(iVals, iVal)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    m := &amp;mapper&#123;</span><br><span class="line">        w,</span><br><span class="line">        <span class="keyword">map</span>[nodeKey]nodeID&#123;nilKey: <span class="number">0</span>&#125;,</span><br><span class="line">        <span class="keyword">map</span>[nodeKey]<span class="keyword">string</span>&#123;nilKey: <span class="string">"nil"</span>&#125;,</span><br><span class="line">        <span class="number">2</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fmt.Fprintln(w, <span class="string">"digraph structs &#123;"</span>)</span><br><span class="line">    fmt.Fprintln(w, <span class="string">"  node [shape=Mrecord];"</span>)</span><br><span class="line">    <span class="keyword">for</span> _, iVal := <span class="keyword">range</span> iVals &#123;</span><br><span class="line">        m.mapValue(iVal, <span class="number">0</span>, <span class="literal">false</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Fprintln(w, <span class="string">"&#125;"</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/2018/07/01/BarberShop/index.html b/2018/07/01/BarberShop/index.html
deleted file mode 100644
index 903a68b..0000000
--- a/2018/07/01/BarberShop/index.html
+++ /dev/null
@@ -1,258 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>BarberShop | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="理发师问题是操作系统中一个非常经典的同步问题，假设理发店里有一位理发师，一把理发椅和5把供等候理发的顾客坐的椅子。如果当前没有顾客，则理发师躺在理发椅上睡觉，如果有顾客前来，他必须唤醒理发师，如果理发师正在理发但又有顾客前来，如果有空位置可坐，顾客就坐下来等待，否则则离开。 下面我们使用 golang 中的 for select 机制结合 goroutine 和 channel 来解决这个问题。">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="article">
-<meta property="og:title" content="BarberShop">
-<meta property="og:url" content="https://oceanoverflow.github.io/2018/07/01/BarberShop/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="理发师问题是操作系统中一个非常经典的同步问题，假设理发店里有一位理发师，一把理发椅和5把供等候理发的顾客坐的椅子。如果当前没有顾客，则理发师躺在理发椅上睡觉，如果有顾客前来，他必须唤醒理发师，如果理发师正在理发但又有顾客前来，如果有空位置可坐，顾客就坐下来等待，否则则离开。 下面我们使用 golang 中的 for select 机制结合 goroutine 和 channel 来解决这个问题。">
-<meta property="og:locale" content="default">
-<meta property="og:updated_time" content="2018-07-02T10:48:13.921Z">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="BarberShop">
-<meta name="twitter:description" content="理发师问题是操作系统中一个非常经典的同步问题，假设理发店里有一位理发师，一把理发椅和5把供等候理发的顾客坐的椅子。如果当前没有顾客，则理发师躺在理发椅上睡觉，如果有顾客前来，他必须唤醒理发师，如果理发师正在理发但又有顾客前来，如果有空位置可坐，顾客就坐下来等待，否则则离开。 下面我们使用 golang 中的 for select 机制结合 goroutine 和 channel 来解决这个问题。">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <article id="post-BarberShop"
-  class="article white-box article-type-post"
-  itemscope itemprop="blogPost">
-
-  <header class="article-header">
-    <h1 class="article-title" itemprop="name">
-      BarberShop
-    </h1>
-    <div class="article-meta">
-      Posted on 
-      <time class="article-time" datetime="2018-07-01T09:34:34.000Z" itemprop="datePublished">
-        Jul 1, 2018
-      </time>
-    </div>
-  </header>
-
-  <div class="article-entry" itemprop="articleBody">
-    <p>理发师问题是操作系统中一个非常经典的同步问题，假设理发店里有一位理发师，一把理发椅和5把供等候理发的顾客坐的椅子。如果当前没有顾客，则理发师躺在理发椅上睡觉，如果有顾客前来，他必须唤醒理发师，如果理发师正在理发但又有顾客前来，如果有空位置可坐，顾客就坐下来等待，否则则离开。</p>
-<p>下面我们使用 <code>golang</code> 中的 <code>for select</code> 机制结合 <code>goroutine</code> 和 <code>channel</code> 来解决这个问题。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    CUTTING_TIME = <span class="number">20</span></span><br><span class="line">    BARBERS_COUNT = <span class="number">1</span></span><br><span class="line">    HALL_SITS_AMOUNT = <span class="number">5</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Barber <span class="keyword">struct</span> &#123;</span><br><span class="line">    name <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Client <span class="keyword">struct</span> &#123;</span><br><span class="line">    name <span class="keyword">int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p><code>clientProducer</code> 模拟顾客前来，每隔一段随机的时间，前来一位顾客，<code>cutHear</code> 模拟理发师理发过程，理发结束时，向 <code>finished</code> 通道发送一个 <code>barber</code> ，表示该理发师已经空闲。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">clientProducer</span><span class="params">(clients <span class="keyword">chan</span> *Client)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        time.Sleep(time.Duration(rand.Intn(<span class="number">28</span>) + <span class="number">7</span>)</span><br><span class="line">        clients &lt;- &amp;Client&#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">cutHear</span><span class="params">(barber *Barber, client *Client, finished <span class="keyword">chan</span> *Barber)</span></span> &#123;</span><br><span class="line">    fmt.Printf(<span class="string">"%v cutting hear for %v\n"</span>, barber.name, client.name)</span><br><span class="line">    time.Sleep(CUTTING_TIME * time.Millisecond)</span><br><span class="line">    finished &lt;- barber</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<ol>
-<li>若一顾客进入理发店，理发师正在为别人理发，且等待室有空椅子，该顾客就找张椅子按顺序坐下；</li>
-<li>若一顾客进入理发店，理发师正在为别人理发，且所有椅子都被占用了，该顾客马上离开。</li>
-<li>若一顾客进入理发店，理发师在睡觉，则叫醒理发师为该顾客理发；</li>
-<li>如果理发师工作完，发现还有在等待的顾客，则呼唤顾客前来理发。</li>
-<li>若没有要理发的顾客，则理发师去睡觉；</li>
-</ol>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BarberShop</span><span class="params">(clients &lt;-<span class="keyword">chan</span> *Client)</span></span> &#123;</span><br><span class="line">    freeBarbers := []*Barber&#123;&#125;</span><br><span class="line">    waitingClient := []*Client&#123;&#125;</span><br><span class="line">    syncBarberChan := <span class="built_in">make</span>(<span class="keyword">chan</span> *Barber)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; BARBERS_COUNT; i++ &#123;</span><br><span class="line">        freeBarbers = <span class="built_in">append</span>(freeBarbers, &amp;Barber&#123;&#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> client := &lt;-clients:</span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">len</span>(freeBarbers) == <span class="number">0</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> <span class="built_in">len</span>(waitingClient) &lt; HALL_SITS_AMOUNT &#123;</span><br><span class="line">                    waitingClient = <span class="built_in">append</span>(waitingClient, client)</span><br><span class="line">                    fmt.Printf(<span class="string">"Client is waiting in hall (%v)\n"</span>, <span class="built_in">len</span>(waitingClient))</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    fmt.Println(<span class="string">"No free space for client"</span>)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                barber := freeBarbers[<span class="number">0</span>]</span><br><span class="line">                freeBarbers := freeBarbers[<span class="number">1</span>:]</span><br><span class="line">                fmt.Println(<span class="string">"Client goes to barber"</span>)</span><br><span class="line">                <span class="keyword">go</span> cutHear(barber, client, syncBarberChan)</span><br><span class="line">            &#125;</span><br><span class="line">        <span class="keyword">case</span> barber := &lt;-syncBarberChan:</span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">len</span>(waitingClient) &gt; <span class="number">0</span> &#123;</span><br><span class="line">                client := waitingClient[<span class="number">0</span>]</span><br><span class="line">                waitingClient = waitingClient[<span class="number">1</span>:]</span><br><span class="line">                fmt.Printf(<span class="string">"Take client from room (%v)\n"</span>, <span class="built_in">len</span>(waitingClient))</span><br><span class="line">                <span class="keyword">go</span> cutHear(barber, client, syncBarberChan)</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                fmt.Println(<span class="string">"Barber idle"</span>)</span><br><span class="line">                freeBarbers = <span class="built_in">append</span>(freeBarbers, barbers)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-<p>我们在 <code>main</code> 函数中起两个 <code>goroutine</code> ，分别代表顾客进程和理发师进程，理发师在工作8小时后退出，<code>clients</code> 通道作为两个 <code>goroutine</code> 沟通的媒介，类似于生产者和消费者模式。</p>
-<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    clients := <span class="built_in">make</span>(<span class="keyword">chan</span> *Client)</span><br><span class="line">    <span class="keyword">go</span> clientProducer(clients)</span><br><span class="line">    <span class="keyword">go</span> BarberShop(clients)</span><br><span class="line">    time.Sleep(<span class="number">8</span> * time.Hour)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-  </div>
-  
-  <div class="article-tags">
-    
-  </div>
-    
-  
-
-</article>
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/AboutMe.md b/AboutMe.md
new file mode 100644
index 0000000..70b786d
--- /dev/null
+++ b/AboutMe.md
@@ -0,0 +1 @@
+// TODO
diff --git a/BloomFilter.md b/BloomFilter.md
new file mode 100644
index 0000000..03734e6
--- /dev/null
+++ b/BloomFilter.md
@@ -0,0 +1,106 @@
+# Bloom Filter
+  当我们写爬虫应用的时候，有一件事情是值得我们仔细考虑的，在抓取网上数据的时候，我们的爬虫会沿着当前爬取的网页中的链接继续进行深度优先搜索或者广度优先
+搜索，但是很显然，这些链接形成的拓扑图肯定不是一个有向无环图，所以肯定会重复抓取某些网页，这肯定不是我们所想要的，为了避免重复抓取导致的返工，我们不加
+思索的增加了一个 `map` 来存储当前已经被抓取过的url，这在要求抓取的url数量较少的时候或许是一个不错的解决方案，但是一旦我们要抓取亿级别的url数量时
+（在现在这种自媒体爆发的时代还是很正常的一件事情），假设我们要抓取的url平均大小是20字节，那么不考虑其他开销，1亿个url需要消耗的内存就是20GB，这显然
+是不现实的。我们需要一种更加优化的解决方案。
+
+  上述的问题可以抽象为，给定一个元素E，问它是否存在于给定的集合S中，上述使用 `map` 的存储导致空间开销过大的主要原因就是我们需要存储原来的url，那有
+没有一种方法不存储每条消息而可以知晓它是否存在于特定的集合中呢，答案就是 `Bloom Filter`。
+
+  `Bloom Filter` 是一个空间和时间都非常高效的数据结构，它解决的问题也非常简单，就是用于查询特定元素是否存在于某个集合当中，但是这种高效是引入错误率
+的基础上的高效，下面我们引入 `BloomFilter` 的两个特性。
+
+* False Positive 
+
+  `Bloom Filter` 可能会出现 `False Positive` 的概率，就是指查询特定元素E是否存在于集合E中，真实情况是E不存在，但是 `Bloom Filter` 却出现了
+误判，当 `Bloom Filter` 存储的元素越多，出现误判的概率也就会越大（一般来说会把误判率控制在可以接受的范围内），这是由 `Bloom Filter` 本身的特性
+造成的。
+* False Negative
+
+  `False Negative` 指的是元素E本来存在于集合S中，但是 `Bloom Filter`却出现误判，认为元素E并不存在于集合S中，这种情况是绝对不会出现的，这也是由
+`Bloom Filter` 本身的特性决定的。
+
+  `Bloom Filter`实现的思路非常简单，它主要由两个元素组成。
+1. 一张位图，决定了 `BloomFilter` 在空间上是高效的。
+2. 多个哈希函数，决定了 `BloomFilter` 是查询时间上是高效的，理论上的时间复杂度是 `O(1)`。
+
+  下面这张图就大概描述了 `Bloom Filter` 实现的大致思路，我们来简单过一遍。
+
+  假设当前由集合 `S: {x, y, z}` ，我们需要查询元素w是否存在于集合S中，第一步应该是位图的构建，位图开始是是一张全部为0的数组，当第一个元素x进入时，
+程序会通过 `Bloom Filter` 的所有哈希函数计算出哈希函数对应的哈希值，并将哈希值对应位图的相应位置都设置为1，y和z同理，也就是说此时位图的某些地方已经
+被设置为1了，但是其余地方都是0。此时我们需要查询元素w是否存在于集合S中，先利用 `Bloom Filter` 的所有哈希函数计算出相应的哈希值，并利用哈希值查询对
+应的位图中元素是否都为1，如果都为1，那么则说明元素w可能存在于该集合中，但是只要有一个位置为0，就可以直接判定该元素不存在于该集合中。
+
+![alt text](https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Bloom_filter.svg/649px-Bloom_filter.svg.png)
+
+  下面是 `Bloom Filter` 的简单实现，`bitmap` 就是位图，`k` 是哈希函数的个数，`n` 是当前存储的元素的个数，当然这里存储的意思并不是把整个元素存储下
+来，而是在位图中进行标记的意思，`m` 是整个 `Bloom Filter` 或者说位图的大小。
+
+```golang
+type BloomFilter struct {
+    bitmap []bool
+    k      int
+    n      int
+    m      int
+    hashfn hash.Hash64
+}
+
+func NewBloomFilter(numHashFuncs, bfSize int) *BloomFilter {
+    bf := new(BloomFilter)
+    bf.bitmap = make([]bool, bfSize)
+    bf.k, bf.m = numHashFuncs, bfSize
+    bf.n = 0
+    bf.hashfn = fnv.New64()
+}
+```
+
+  `getHash` 就是利用 `Bloom Filter` 中事先定义的哈希函数计算对应的多个哈希值，这里可以挑选抗碰撞性较好的哈希函数来提高我们程序的鲁棒性。
+
+```golang
+func (bf *BloomFilter) getHash(b []byte) (uint32, uint32) {
+    bf.hashfn.Reset()
+    bf.hashfn.Write(b)
+    hash64 := bf.hashfn.Sum64()
+    h1 := uint32(hash64 & ((1 << 32) - 1))
+    h2 := uint32(hash64 >> 32)
+    return h1, h2
+}
+```
+
+  `Add` 将元素 e 加入 `Bloom Filter` 中。
+
+```golang
+func (bf *BloomFilter) Add(e []byte) {
+    h1, h2 := bf.getHash(e)
+    for i := 0; i < bf.k; i++ {
+        ind := (h1 + uint32(i)*h2) % uint32(bf.m)
+        bf.bitmap[ind] = true
+    }
+    bf.n++
+}
+```
+
+  `Check` 检查特定元素 e 是否存在于 `Bloom Filter` 中。
+
+```golang
+func (bf *BloomFilter) Check(e []byte) bool {
+    h1, h2 := bf.getHash(e)
+    result := true
+    for i := 0; i < bf.k; i++ {
+        ind := (h1 + uint32(i)*h2) % uint32(bf.m)
+        result = result & bf.bitmap[ind]
+    }
+    return result
+}
+```
+
+  函数 `FalsePositiveRate()` 可以计算 `Bloom Filter` 出现 `False Positive` 的概率，这个公式有严格的数学证明，有兴趣的同学可以参考一下它的
+证明过程，我们现在只需要掌握一点就可以了，就是它存储的元素个数（n）越多，它出现 `False Positive` 的概率也就越大。但只要调整合适的`m` 和 `k` 的
+值，就可以把错误率控制在可以接受的范围内。
+
+```golang
+func (bf *BloomFilter) FalsePositiveRate() float64 {
+    return math.Pow((1 - math.Exp(-float64(bf.k*bf.n) / float64(bf.m))), float64(bf.k))
+}
+```
diff --git a/CircuitBreaker.md b/CircuitBreaker.md
new file mode 100644
index 0000000..5609171
--- /dev/null
+++ b/CircuitBreaker.md
@@ -0,0 +1,109 @@
+# CircuitBreaker
+
+  我们都知道，如果家中因为启动过多大功率电器而导致电流过大，断路开关就会断开以保护这些电路和电器。在分布式系统中，集群中的某些服务器出现异常还是一件非常
+正常的事情，如果客户端向这些异常的服务器进行 `RPC` 请求的话，这些服务器会因为异常而无法向客户端返回远程方法调用的结果，因为一般来说 `RPC` 是阻塞的，客
+户端会像执行本地方法一样调用 `RPC` ，也就是说客户端会阻塞在这里无法执行 直到该方法本地超时，但由于为了得到正确的结果，客户端可能会反复多次调用该 `RPC`
+，由于在这段时间内远程服务器都可能无法恢复正常，所以就会导致客户端一直调用该方法，但却无法得到结果，这样就会导致资源的浪费。
+
+  为了避免上述情况的发生，我们可以在程序设计中借鉴断路开关的模式，也就是允许被保护的函数在规定上限内执行，如果一旦出现错误的次数超过上限，则下次函数再次
+调用时则直接不让其执行（也就是断路开关直接断开），从而避免系统资源的浪费。但是上述方法存在一个问题，就是一旦总的错误次数超过上限，是不是就说明即使现在远
+程服务器恢复正常，客户端也无法调用了呢。
+
+  解决上述问题也很简单，通过模仿网络中很常见的 `Sliding Window` ，也就是移动窗口，允许在一定时间窗口内出现特定上限个错误，如果在该时间窗口内出现错误
+的次数超过上限，则不再允许该函数执行，直到下一个时间窗口的到来才允许它重新执行。
+
+  下面来设计一个滑动窗口版本的断路开关，我们通过判断一个时间窗口 `window` 内出现的错误次数 `failures` 是否超过 `failureThreshold` 来决定断路开关
+是否应该断开（也就是不让函数继续执行）。
+
+```golang
+type CircuitBreaker struct {
+    lastFailureTime  time.Time
+    failures         uint64
+    failureThreshold uint64
+    window           time.Duration
+}
+
+func NewCircuitBreaker(failureThreshold uint64, window time.Duration) {
+    return &CircuitBreaker{
+        failureThreshold: failureThreshold,
+        window:           window,
+    }
+}
+```
+
+  由于是滑动窗口，我们需要观察在现在的窗口出现错误的次数是否超过我们规定的次数，如果超过，则表示该函数还没有 `ready` ，也就是还不能执行，如果该窗口已经
+过去，那么我们重置（ `reset` ）断路开关中记录的出错次数，以让函数可以重新执行。
+
+```golang
+func (cb *CircuitBreaker) ready() bool {
+    if time.Since(cb.lastFailureTIme) > cb.window {
+        cb.reset()
+        return
+    }
+    failures := atomic.LoadUint64(&cb.failures)
+    return failures < cb.failureThreshold
+}
+
+func (cb *CircuitBreaker) success() {
+    cb.reset()
+}
+
+func (cb *CircuitBreaker) fail() {
+    atomic.AddUint64(&cb.failures, 1)
+    cb.lastFailureTime = time.Now()
+}
+
+func (cb *CircuitBreaker) reset() {
+    atomic.StoreUint64(&cb.failures, 0)
+    cb.lastFailureTime = time.Now()
+}
+```
+
+  也就是说，在 `CircuitBreaker` 保护下，客户端准备调用函数时，会预先检察其是否具备资格，也就是说过去一个时间窗口没有出现超过上限个错误，如果不具备，
+就报 `ErrBreakerOpen` 错误，也就是对应下图中的  `circuit open` ，因为断路开关断开了，自然没有办法继续执行。
+
+  如果具备，则可以让受保护的函数继续执行，但是钥匙它在规定的时间内还没有返回结果，说明出现超时情况，则报 `ErrBreakerTimeout` 错误，并增加错误次数直
+到其达到上限为止。
+
+![Circuit Breaker](https://martinfowler.com/bliki/images/circuitBreaker/sketch.png)
+
+```golang
+var (
+    ErrBreakerOpen = errors.New("breaker open")
+    ErrBreakerTimeout = errors.New("breaker time out")
+)
+
+
+func (cb *CircuitBreaker) Call(fn func() error, d time.Duration) error {
+    var err error
+    if !cb.ready() {
+        return 
+    }
+
+    if d == 0 {
+        err = fn()
+    } else {
+        c := make(chan error, 1)
+        go func() {
+            c <- fn()
+            close(c)
+        }()
+
+        t := time.NewTicker(d)
+        select {
+        case e := <-c:
+            err = e
+        case <-t.C:
+            err = ErrBreakerTimeout
+        }
+        t.Stop()
+    }
+
+    if err == nil {
+        cb.success()
+    } else {
+        cb.fail()
+    } 
+    return err
+}
+```
diff --git a/ConsistentHashing.md b/ConsistentHashing.md
new file mode 100644
index 0000000..190e740
--- /dev/null
+++ b/ConsistentHashing.md
@@ -0,0 +1,134 @@
+# Consistent Hashing
+  
+  比如说我们现在有3台服务器用于存储kv值，分别是 `{s1, s2, s3}` ，而我们用的哈希策略非常简单，例如 `h(x) = ( x^2 + 3 * x + 2 ) % 3` ，也就是
+说当k=1时，对应的v值会被存放在s1上，但如果业务量增加，我们又需要增加一个服务器来均衡负载，此时哈希策略就变成 `h(x) = ( x^2 + 3 * x + 2 ) % 4`
+，那按照这种策略，当k=1的时候，应该是把对应的v值存放在s3上面，然而s3上面并没有存放，为了能够获取到k=1对应的v值，我们就需要将原来三台服务器上的数据
+做一个 `remapping` ，也就是说基本上所有的数据都要进行迁移，在小数据量的情况下这倒没什么问题，但是一旦数据量达到T级别，这种开销将是无法忍受的，所以，
+为了当增删节点时尽量少的数据迁移，我们可以利用一致性哈希这种非常神奇的算法。
+
+  所谓一致性哈希，就是当相应的哈希表调整大小的时候（对应到现实生活中就是服务器增删节点），只有 `K/n` 个数据需要迁移，这里的 `K` 是指键的数量，而 `n`
+则是指所有的卡槽（对应服务器的数量），如果不用一致性哈希而是用传统的哈希表，当哈希表调整的时候，基本所有的键都要进行 `remapping`。
+
+  一致性哈希有几个要点，第一个就是它所有的地址空间会形成一个环，例如它的地址空间是从 `[0, 2^32-1)` ，它的头部和尾部会进行拼接而形成一个环，还有就
+是虚节点的概念，例如下图中我们有`{s1, s2, s3, s4}`这四个节点，但每个节点都会有自己的拷贝（称为虚节点），然后这些复制过的节点群会根据特定的哈希算法
+分布在这个环上面，一般来说都是均匀分布的，而我们要存储的键值对，同样根据与节点相同的哈希算法，算出一个值后，顺时针（或者逆时针）去寻找与自己最近的虚节
+点的位置，找到最近的虚节点后，就将自己存放在对应的节点上，这就是实现一致性哈希的基本思路，下面就让我们来看一下一致性哈希算法的实现吧。
+
+![alt text](https://dajh2p2mfq4ra.cloudfront.net/assets/site-images/system_design/consistent_hashing_virtual.jpg)
+
+## 一致性哈希的实现
+
+  上面我们知道了一致性哈希的核心是一个环，环的地址空间假设是 `[0, 2^32-1)` ，我们可以用一个map记录虚节点对应的环上的位置，位置我们用一个uint32表
+示就可以了，因为是遍历map的时候是随机的，所以我们还需要一个数组来记录环上面虚节点的顺序。
+
+```golang
+type uints []uint32
+
+func (x uints) Len() int { return len(x) }
+func (x uints) Less(i, j int) bool { return x[i] < x[j] }
+func (x uints) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+type Consistent struct {
+    circle map[uint32]string
+    sortedList uints
+    virtualNode int
+    sync.Mutex
+}
+
+func New() *Consistent {
+    return &Consistent{
+        circle: make(map[uint32]string),
+        sortedList: make(uints, 0)
+        virtualNode: 20,
+    }
+}
+```
+
+  虚节点相当于实节点的影分身，例如s2，s2复制为s2-1，s2-2，s2-3。这些原来的节点和复制出来的节点我们可以把它们形象地称为哨兵。
+
+```golang
+func (c *Consistent) KeyNum(key string, num int) string {
+    return key + ":" + fmt.Sprintf("%d", num)
+}
+```
+
+  要想把虚节点对应到一致性哈希的圆环上，我们还需要一个哈希函数用于把我们的哨兵和我们的键值对映射到环上面去。
+
+```golang
+func (c *Consistent) hashKey(key string uint32) {
+    if len(key) < 64 {
+        scratch := make([]byte, 64)
+        copy(scratch[:], key)
+        return crc32.ChecksumIEEE(scratch[:len(key)])
+    }
+    return crc32.ChecksumIEEE([]byte(key))
+}
+```
+
+  之前说了，我们加入的键值对经过哈希后会在环上顺时针寻找离自己最近的虚节点的位置，因为我们之前已经用 `sortedList` 记录了节点在环上的相对顺序了，
+所以就可以利用二分法去查找对应虚节点的位置啦。
+
+```golang
+func (c *Consistent) search(key uint32) int {
+    i := sort.Search(len(c.sortedList), func(x int) bool {
+        return c.sortedList[x] > key
+    })
+    if i >= len(c.sortedList) {
+        i = 0
+    } 
+    return i
+}
+```
+
+  当然了，我们一致性哈希就牛逼的地方就在于当动态增删节点的时候，需要`remapping` 的键值对的数量比较少，动态增删节点无非也就是将该节点影分身后再经过
+哈希操作对应到环上或者进行相应的删除操作，当然还需要对我们的 `sortedList` 重新进行排序来对应增删的虚节点。
+
+```golang
+func (c *Consistent) Add(key string) {
+    c.Lock()
+    defer c.Unlock()
+
+    for n := 0; n < virtualNode; n++ {
+        c.circle[c.hashKey(c.KeyNum(key, n))] = key
+    }
+
+    c.updateList()
+}
+
+func (c *Consistent) Remove(key string) {
+    c.Lock()
+    defer c.Unlock()
+ 
+    for n := 0; n < c.virtualNode; n++ {
+        delete(c.circle, c.hashKey(c.KeyNum(key, n)))
+    }
+
+    c.updateList()
+}
+
+func (c *Consistent) updateList() {
+    list := c.sortedList[:0]
+    for k, _ := range c.circle {
+        list = append(list, k)
+    } 
+    sort.Sort(list)
+    c.sortedList = list
+}
+```
+
+  最后就是当我们新增一个键值对时，我们可以查找对应的节点。
+
+```golang
+func (c *Consistent) Get(name string) (string, error) {
+    c.Lock()
+    defer c.Unlock()
+
+    if len(c.circle) == 0 {
+        return 0, errors.New("empty consistent circle")
+    }
+    key := c.hashKey(name)
+    i := c.search(key)
+    return c.circle[c.sortedList[i]], nil
+}
+```
+
diff --git a/Crawler.md b/Crawler.md
new file mode 100644
index 0000000..bbf673d
--- /dev/null
+++ b/Crawler.md
@@ -0,0 +1,146 @@
+# Crawler
+  
+  爬虫算是练习并发编程的一个非常好的例子了，因为它既不枯燥，难度也不大，而且能在短时间内产出一个有趣的结果。爬虫一般通过某种搜索算法（深度优先搜索或者
+广度优先搜索）在互联网这个海量数据库中去寻找我们感兴趣的东西，如果使用得当的话，爬虫可以极大地提高我们的工作效率。
+
+  那么接下去我们从一个单线程的爬虫程序出发，然后慢慢将它改造成一个并发的爬虫程序。在这里，我们并不关心究竟如何去匹配我们感兴趣的元素(例如使用CSS进行元
+素匹配)，而是给出一个爬虫的基本思路。
+
+  首先，爬虫中非常重要的一个步骤就是匹配当前搜索的网页中的元素，并将符合我们要求的东西下载或保存起来，并且还会记录当前网页中的超链接地址，以便于我们继
+续进行深度优先搜索或者广度优先搜索。一般来说，我们感兴趣的东西都是符合特定规则的，而具体的规则我们可以在单个网页上进行正则匹配来获取，但是，由于不同网
+页的匹配规则并不相同，所以我们定义一个interface来抽象该行为。在这之后无论我们想要爬豆瓣还是新浪微博亦或是其他自己感兴趣的网站，只要重新定义一个结构体
+实现该方法就可以。
+
+  `Fetcher` 这个 `interface` 定义了如下行为，从一个特定的url去取我们感兴趣的内容以及这个网页上的所有的url链接。
+
+```golang
+type Fetcher interface {
+    Fetch(url string) (body string, urls []string, err error)
+}
+```
+
+  例如我们要爬豆瓣网上的东西，我们只要定义好一个结构体，并且实现上述`Fetch` 方法就可以了。所以无论以后你决定改爬别的网站了，再定义如下的结构体并实现
+相应的方法就可以了，这就是为什么上面我们定义了一个 `Fetcher` interface 来抽象这个行为的原因了。
+
+```golang
+type Result struct {
+    body string
+    urls []string
+}
+
+type doubanFetcher struct {
+    map[string]*Result
+    sync.RWMutex
+}
+
+func (f *doubanFetcher) Fetch(url string) (body string, urls []string, err error) {
+     // 这里写具体的匹配逻辑
+}
+```
+
+  爬虫还有一个重点就是搜索的策略，应该是广度优先还是深度优先，但是所有的链接形成为拓扑图并不一定是一个有向无环图，所以我们的爬虫在爬取的过程中可能会遇
+到相同的链接，但是注意这个逻辑同样应在在 `Fetch` 函数中实现。
+
+## 单线程版本实现
+
+  下面我们来看一下单线程深度优先的爬虫应该怎么写。
+
+```golang
+func Crawl(url string, depth int, fetcher Fetcher) {
+    if depth <= 0 {
+        return
+    }
+
+    body, urls, err := fetcher.Fetch(url)
+    if err != nil {
+        fmt.Println(err)
+        return
+    }
+    fmt.Printf("Founf: %s %q\n", url, body)
+    for _, u := range urls {
+        Crawl(u, depth-1, fetcher)
+    }
+    return
+}
+```
+
+  由于是深度优先搜索，所以我们用递归的策略来进行搜索，递归最重要的一点就是递归条件的出口条件，如果递归函数没有出口，那么就是死循环了。这里我们在函数的
+参数中引入一个深度的变量来控制是否应该继续进行递归，如果当前深度小于等于0，则退出。然后用 `fether`  来 `Fetch` 对应的 `url`上的内容，由于使用了接
+口，所以让我们这个函数的实现变得非常的灵活，而不是局限于哪个具体的实现，这就是接口的好处。然后根据当前网页中的链接进行深度优先搜索，
+`Crawl(u, depth-1, fetcher)` ，每搜索一层，深度减一，直到条件不再满足就可以退出了。
+
+  不过上述的爬虫还是单线程的，单线程的效率肯定不高，因为程序大部分时间都是在等待 `I/O`，`CPU` 大部分时间都是空闲的，所以，为了提高 `CPU`的占用率，
+我们应该考虑使用并发。
+
+## 并发版本实现
+
+  在 `golang` 里面写并发程序是相对比较简单的，但是也没有那么简单，下面的实现就是比较tricky的。这里为什么叫它并发而不是多线程呢，是因为`golang` 中
+的 `go` 机制并不是以线程作为基本单位的。
+
+```golang
+func Crawl(url string, depth int, fetcher Fetcher, ret chan string) {
+    defer close(ret)
+    if depth <= 0 {
+        return
+    }
+
+    body, urls, err := fetcher.Fetch(url) 
+    if err != nil {
+        ret <- err.Error()
+        return
+    }
+     
+    ret <- fmt.Sprintf("Found: %s %q", url, body)
+
+    result := make([]chan string, len(urls))
+    for i, u := range urls {
+        result := make(chan string)
+        go Crawl(u, depth-1, fetcher, result)
+    }
+
+    for i := range result {
+        for s := range result[i] {
+            ret <- s
+        }
+    }
+    
+    return
+}
+```
+
+  并发版本和单线程版本的基本框架是一样的，有下面几个区别。
+
+  首先我们定义个一个 `chan string` 也就是一个通道，一般来说，`go` 和`chan` 都是手拉手用在一起的。这个通道用于接受我们爬虫的结果。
+  
+  这个通道在整个函数返回时会关闭，也就是函数最初用的 `defer close(ret)` 。
+
+  当 `fetch.Fetch(url)` 方法返回时，也就是这个网页中的内容已经检索完毕了，我们将结果放到刚才的通道中等待其他地方的程序读取该通道中的内容。
+
+  下面就是函数的精髓了，由于上面通过 `fetch.Fetch(url)` 获得了一个`urls` 数组，因为要进行深度优先搜索，我们为这个 `urls` 中的 `url` 也准备一个
+`chan string` 用于存储它们抓取的内容，然后调用 `go Crawl(u, depth-1, fetcher, result)` 来并发爬取。
+
+  也就是说下面这段函数很快就返回了，但是它们并不一定都已经拿到相应的内容了。
+
+```golang
+for i, u := range urls {
+    result := make(chan string)
+    go Crawl(u, depth-1, fetcher, result)
+}
+```
+
+  所以，我们要等待它们拿回内容，下面代码的意思就是子任务完成后，将它拿到的内容传给上一层的通道中。这个就好比在一个公司中，`CEO` 将任务分别分配给下面
+各个部门的 `Manager` ，然后各个部门的 `Manager` 又细分任务后将任务分给部门下面的各个 `Worker` ，`Worker` 完成自己的任务后，将任务结果传给负责
+自己的 `Manager` ，然后由 `Manager` 再汇报给 `CEO` 。`CEO` 是总任务的分配者同时也是所有结果的收集者。
+
+```golang
+for i := range result {
+    for s := range result[i] {
+        ret <- s
+    }
+}
+```
+
+## 总结
+  
+  并发程序能充分利用现在 `CPU` 的所有核心，它利用单线程程序运行中部分代码段会因为等待 `I/O`（例如发送http请求和等待http答复）而占用 `CPU` 时间的
+特点，同时启动多个 `goroutine` 来最大程度上占用 `CPU` 时间，从而提高程序的运行效率。
diff --git a/Crontab.md b/Crontab.md
new file mode 100644
index 0000000..9b6877d
--- /dev/null
+++ b/Crontab.md
@@ -0,0 +1,60 @@
+# crontab
+  事情的经过是这样子的，室友最近要做一个阿里的项目，大概就是利用软件工程结合机器学习对代码缺陷进行预测分析，现在正处于数据分析阶段，每天都会到github上
+拉一大堆项目，然后用写好的代码啪啪啪分析一通，一般来说代码都要跑很久，一般都是12小时左右才能出结果，而且等它跑完还要继续跑剩下一个项目，但是作为程序员，
+这样的体力活自然应该自动化处理啦，毕竟越厉害的程序员是越懒的。
+
+  所以，这种周期性，性质类似，但是需要大量重复劳动的工作可以写成自动化脚本再结合 `crontab` 来解决。`crontab` 就是为了周期性定时执行任务而生的，再也
+不用盯着电脑屏幕等结果跑完啦，感觉是现在搞AI的人的必备良药呢。
+ 
+  `crontab` 的语法还是挺简单的，但是咋一看还是一脸懵逼的，其实关于`crontab` 只要掌握一点就可以使用它了，就是关于时间语法的定义，因为 `crontab` 就是为了定时执行任务而存在的，所以它有自己的一套语法。
+
+```
+$ * * * * * command_to_execute
+  | | | | |
+  | | | | +- day of week (0 - 7) where sunday is 0 and 7
+  | | | +--- month (1 - 12)
+  | | +----- day (1 - 31)
+  | +------- hour (0 - 23)
+  +--------- minute (0 - 59)
+```
+
+  我们要让某个任务在某个特定的时间点执行，时间无非就是哪个月的哪一天的几点几分或者是星期几该执行这项任务，在 `crontab` 的语法中我们先指定分钟，再次小
+时，接着一个月中的某一天，然后月份，最后星期几。具体的顺序如下：`(min)  (hour)  (day_of_month)  (month)  (day_of_week)`。
+
+## 例子
+  不过上面讲的还是太抽象了，我们来具体举几个例子来掌握crontab的使用吧。
+
+  例如我们已经写好了一个脚本，`make_coffee.sh` ，因为程序员都有午后喝咖啡的习惯，但是咖啡机每次启动都要预热好久，为了让自己少浪费一点时间，就写了一个
+脚本让咖啡机在每天下午两点自己开启进行预热，预热完成，我们就可以直接过去接咖啡了。所以，我们要让 `crontab` 每天下午执行这个脚本，我们应该怎么写呢，按照
+上面的语法，不是很难。
+
+`$ 0 14 * * * /path/to/make_coffee.sh`
+
+  也就是说 `crontab` 每天下午两点会启动咖啡机预热，不过现在有个问题，我们周末并不在公司，只有工作日周一到周五在公司，所以，我们上面的语法还是有点问题
+的，应该让 `crontab` 指定在工作日才运行。
+
+`$ 0 14 * * 1-5 /path/to/make_coffee.sh`
+
+  只要把第五个 `*` 换成 `1-5` 就可以啦，非常简单。
+
+  但是每天喝咖啡可能对身体不太好，那我们改成星期一星期三星期五喝咖啡，其他两天改喝牛奶，那我们应该怎么办呢，将1-5改成 1,3,5 就可以了。
+
+`$ 0 14 * * 1,3,5 /path/to/make_coffee.sh`
+
+  `crontab` 的语法还是有很多的，这里就不一一例举了，我们有一个大致的思路，有了大致的思路，具体问题再去看文档就ok啦。
+
+## crontab管理
+  其实直接在命令行中直接数据 `crontab` 命令并不是一个非常好的习惯，我们最好将这些命令存放在文件中以便持久化的目的，也方便我们进行集中管理，很幸运的是
+，`crontab` 已经为我们提供了这些服务啦。
+
+`$ crontab -e`
+
+  `-e` 可以让我们编辑crontab文件，可以在该文件中定义多个 `crontab` 任务。
+
+`$ crontab -l`
+
+  `-l` 帮助我们查看当前用户定义的所有的 `cron jobs`。
+
+`$ crontab -r`
+
+  `-r` 则会清除当前用户所有的 `cron jobs`。
diff --git a/DecodingDubboProtocol.md b/DecodingDubboProtocol.md
new file mode 100644
index 0000000..75c38a2
--- /dev/null
+++ b/DecodingDubboProtocol.md
@@ -0,0 +1,142 @@
+# Decoding Dubbo Protocol
+  
+  之前看 `shadowsocks` 源码的时候看过好多遍 `SOCKS5` 的 `RFC` ，看的一脸懵逼，不知道这些奇奇怪怪的网络协议究竟该如何理解，后来才发现网络协议也并
+没有那么神秘，无非就是为了让两台计算机使用网络进行通信时能互相理解对方而设定的一系列规则而已。就好像一个中国人和一个法国人聊天，法国人讲法语，而中国人
+用中文，他们自然很难理解对方究竟要表达什么意思，但是如果二者约定同时用两者都会的语言——英语进行交流，那么两者就可以正常交流下去了，因为两者协议了一套规
+则，可以相互理解的规则（这里的规则就是英语）。
+
+  一般来说要是想自己定义一套网络协议，首先需要做的事情就是定义这个协议中特定位置的字段分别代表什么含义，例如下图中的 `Dubbo` 协议，它就规定了一个报文
+中各个字段代表的含义，如下面第一个字节和第二个字节合在一起就叫做一个 `Magic Number` ，以此类推。
+
+![Dubbo](https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png)
+
+  所以，解析网络协议的本质就是去解析一个字节数组，并将它包含的数据转换成特定的含义的过程，下面我们就以解析 `Dubbo` 协议为例，来看一下如何正确地读取字
+节数组中的信息，在这之前，我们先了解一下golang标准库中的两个函数。
+
+  第一个就是 `bytes.NewBuffer(buf []byte) *bytes.Buffer` ，因为我们处理协议本质上就是处理字节数组，使用该函数对字节数组进行封装而不是直接操作字
+节数组的好处自然不用多说。当使用上述函数的时候，返回的 `Buffer` 会以 `buf` 这个字节数组作为它的初始内容，而且在这之后该 `Buffer` 就会全权掌控该字
+节数组（也就是说之后我们不可以再碰 `buf`了）。
+
+  第二个就是 `binary.Read(r io.Reader, order ByteOrder, data interface{}) error`，该函数可以非常方便的将结构化的二进制数据从 `r` 中以固
+定的字节序（ `ByteOrder` ）读到 `data`相应的数据字段中，由于`bytes.Buffer` 实现了`io.Reader` 中的 `Read` 方法，所以它也能作为第一个参数传入
+`binary.Read` 进行使用。
+
+  很多协议的报文都是变长的，为了方便起见，一般都是先解析定长部分的数据，然后再解析其变长部分的数据。
+
+## Dubbo 协议分析
+
+  在正式写协议解析类的代码之前，最好先明确该协议中各个字段的含义，所谓磨刀不误砍柴工嘛。
+  
+![Dubbo](https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-protocol.png)
+
+* Magic 字段，共2字节，包含 `Magic High` 和 `Magic Low` 字段，用于特定标识该报文是否采用 `Dubbo` 协议而存在的，如果是则要求其值等于0xdabb。
+* Req/Res，1比特，用于表示该报文是请求报文还是答复报文，当值为1时说明该报文为请求报文，0时为答复报文。
+* 2way，1比特，当且仅当 `Req/Res` 为1时有效，也就是该报文为请求报文时，指明是否期望服务器返回数据，当值为1时则表示希望服务器返回数据。
+* Event，1比特，标记该报文是否为事件消息，例如心跳消息，则设置为1。
+* Serialization ID，5比特，用于表示变长数据部分序列化的方法，例如当使用 `fastjson` 时它的值为6。
+* Status，1字节，用于表示请求的状态，其值可以是
+
+    * 20 - OK
+    * 30 - CLIENT_TIMEOUT
+    * 31 - SERVER_TIMEOUT
+    * 40 - BAD_REQUEST
+    * 50 - BAD_RESPONSE
+    * 60 - SERVICE_NOT_FOUND
+    * 70 - SERVICE_ERROR
+    * 80 - SERVER_ERROR
+    * 90 - CLIENT_ERROR
+    * 100 -SERVER_THREADPOOL_EXHAUSTED_ERROR
+      
+* Request ID，64比特即8字节，用于唯一标识该请求。
+* Data Length，变长部分的数据长度，4字节长度。
+* Variable Part 报文中数据的变长部分，其使用的序列化方法由上述的`serializationID` 字段决定。
+
+## 解析过程
+
+  由于从 `Magic Number` 到 `Data Length` 这个数据字段，其总长度都是固定的，所以我们可以定义一个 `dubboHeader` 结构体包含这些数据字段，其中各
+个数据字段的类型由协议中各个字段的长度决定，例如 `MagicHigh` 的长度为一个字节，所以我们在结构体中使用一个 `byte` 来表示它就可以了，再比如
+`RequestID` 的长度是8字节，我们可以用 `uint64` 来表示，依次类推。
+
+  由于我们要解析的是一个字节数组，为了后面方便起见，我们使用 `bytes.NewBuffer` 来封装它，这样就可以得到一个 `io.Reader` ，然后再使用
+`binary.Read` 就可以解码得到 `dubboHeader` 这个结构体了。
+
+  当使用 `bytes.Buffer` 的时候需要注意一点，它里面有类似于指针概念，也就是当我们调用 `Read` 方法读取多少字节时，内部的指针 `off` 也会向前移动多
+少字节的长度，所以当我们使用 `binary.Read(buf, binary.BigEndian, &dubboHeader)` ，它就会将内部的指针移动 `len(dubboHeader)` 个长度，这样我们就可以利用
+`buf.Next` 方法获取剩下变长部分的数据啦。
+
+  定长部分解决好之后，我们来看变长部分应该怎么解决，协议中 ` Serialization ID` 字段规定了变长部分数据的序列化方法，例如这里使用 `json` 格式进行序
+列化，所以我们只要获取剩余部分的字节数组，然后调用`json.Unmarshal` 就可以获得剩余部分的数据内容了。
+
+## 完整代码段
+
+  自定义解析过程中可能出现的错误类型
+
+```golang
+var ErrInvalidMagicNumber = errors.New("Invalid Magic Number")
+
+var ErrInvalidDataLength = errors.New("Invalid Data Length")
+
+var ErrUnmarshallingJSON = errors.New("Encounter Error when Unmarshalling JSON")
+```
+
+  自定义变长部分数据对应的结构体，注意，结构体中的数据字段必须为大写，否则使用 `json.Unmarshal` 会出错。
+
+```golang
+type VariablePart struct {
+    DubboVersion     string `json:"DubboVersion"`
+    ServiceName      string `json:"ServiceName"`
+    ServiceMethod    string `json:"ServiceMethod"`
+    MethodName       string `json:"MethodName"`
+    MethodParamTypes string `json:"MethodParamTypes"`
+    MethodArguments  string `json:"MethodArguments"`
+    Attachments      string `json:"Attachments"`
+}
+```
+
+  按协议规则一步步解析字节数组并得到相应的信息。
+
+```golang
+func Parse(b []byte) (*VariablePart, error) {
+    buf := bytes.NewBuffer(b)
+ 
+    var dubboHeader struct {
+        MagicHigh  byte
+        MagicLow   byte
+        Misc       byte
+        Status     byte
+        RequestID  uint64
+        DataLength uint32
+    }
+
+    var err error
+    err = binary.Read(buf, binary.BigEndian, &dubboHeader)
+    if err != nil {
+        return nil, err
+    }
+    if !(dubboHeader.MagicHigh == 0xda && dubboHeader.MagicLow == 0xbb) {
+        return nil, ErrInvalidMagicNumber
+    }
+
+    partBytes := buf.Next(int(dubboHeader.DataLength))
+    if len(partBytes) < int(dubbo.DataLength) {
+        return nil, ErrInvalidDataLength
+    }
+    
+    partBuffer := bytes.NewBuffer(partBytes)
+
+    var variablePart VariablePart
+
+    switch dubboHeader.Misc & 0x1F {
+    case 1:
+        //
+    case 2:
+        //
+    default:
+        err = json.Unmarshal(partBuffer, &variablePart)
+        if err != nil {
+            return nil, ErrUnmarshallingJSON
+        }
+    }
+    return &variablePart, nil
+}
+```
diff --git a/Docker.md b/Docker.md
new file mode 100644
index 0000000..93e64c4
--- /dev/null
+++ b/Docker.md
@@ -0,0 +1,108 @@
+# Docker & Golang
+
+  还记得 `java` 当初响遍大江南北的口号吗，`Write one，run anywhere` ，到了互联网时代，`Docker` 这家公司打出了更为牛逼的口号，`Build，Ship，
+and Run Any App，Anywhere` ，它们两者有类似的地方，都是为了追求各种平台的兼容性和通用性。`java` 的跨平台是因为它在不同平台下有不同的 `jvm` 实现
+，不过它仅仅局限于 `java` 这个生态系统里面，相比之下，`Docker` 的野心就更大了，它并没有给我们把编程语言给限定死了，它提供了一个与操作系统隔离的环境
+，可以让我们写任何应用，而且可以在几乎所有平台下跑。
+
+  具体 `Docker` 的细节这里就不具体探讨了，网上也有一堆文章，今天我们主要看一下如何使用它，也就是如何将我们的应用打包成一个 `Docker` 镜像。
+
+  下面我们要实现的是一个用 `golang` 写的 `http` 服务器，但是这个服务器并不是跑在裸机上，而是跑在 `Docker` 容器中的。顺便一提，`Docker` 也是用
+`golang` 写的哦，是不是感觉很厉害呢。
+
+## 书写自己的应用逻辑
+
+下面定义了我们要实现的 `http` 服务器的前端，无奈直男不会写 `CSS` ，就用 `HTML` 写了一下最基本的提交 `FORM` 表单的功能。
+
+```html
+<html>
+    <head>
+        <title></title>
+    </head>
+    <body>
+        <form action="/hash" method="post">
+            interface: <input type="text" name="interface">
+            method: <input type="text" name="method">
+            parameterTypesString: <input type="text" name="parameterTypesString">
+            parameter: <input type="text" name="parameter">
+            <input type="submit" value="hash">
+        </form>
+    </body>
+</html>
+```
+
+  下面使用了golang中的标准库 `net/http` 和 `html/template` 起一个服务器，我们自己定义的 `hashHandler` 会根据请求的类型分别进行处理，如果是
+`GET` 请求则展示我们的前端界面，如果是 `POST` 请求则处理我们浏览器提交的表单并将表单输出到命令行中。到这里，一个非常简单的 `http` 服务器就写好了。
+
+```golang
+package main
+
+import (
+    "fmt"
+    "html/template"
+    "log"
+    "net/http"
+    "strings"
+)
+
+func hashHandler(w http.ResponseWriter, r *http.Request) {
+    fmt.Println("method: ", r.Method)
+    if r.Method == "GET" {
+        t, _ := template.ParseFiles("hash.tpl")
+        t.Execute(w, nil)
+    } else {
+        r.ParseForm()
+        for k, v := range r.Form {
+            fmt.Printf("key: %s, value: %s\n", k, v)
+        }
+    }
+}
+
+func main() {
+    http.HandleFunc("/hash", hashHandler)
+    err := http.ListenAndServe(":8080", nil)
+    if err != nil {
+        log.Fatal("ListenAndServe: ", err)
+    }
+}
+```
+
+## Dockerfile的撰写
+
+  到现在，就没我们 `golang` 什么事情了，有请我们今天的主角 `Docker` 登场了。为了能让我们的 `http` 服务器在容器中运行，我们需要写一个
+`Dockerfile` ，`Dockerfile` 的作用就是让 `Docker` 知道该如何构建镜像，当然平时大部分时候我们都可以直接用别人打包好的镜像，但是自己会写
+`Dockerfile` 也是一个非常重要的能力哦。
+
+  `FROM` 指令指定了我们的基础镜像是什么，也就是说我们构建的镜像是基于哪个镜像的基础之上的，这里 `golang:alpine` 作为我们的基础镜像。而`COPY` 指
+令则将我们的文件从操作系统中拷贝到容器环境中。`WORKDIR` 命令则制定了在 `Docker` 内部的工作目录，类似于 `cd` 命令，`RUN` 命令在容器中执行指令，这
+里我们把go源文件编译成二进制。`CMD` 指令指定了启动该容器时内部应该执行的命令。当然 `Dockerfile` 的命令还有很多，具体还是参考官方的文档吧。
+
+```dockerfile
+FROM golang:alpine
+COPY . /home
+WORKDIR /home
+RUN go build -o server ./server.go
+CMD /home/server
+```
+
+  写完了 `Dockerfile` ，就可以构建镜像了，不过构建镜像的事情我可干不来，还是交给 `Docker` 去做吧。下面的命令就帮助我们构建一个名为
+`oceanoverflow/server` 的 `golang` 服务器镜像。构建镜像的过程可能会比较花时间，需要耐心等待。
+
+`$ docker build -t oceanoverflow/server .`
+
+## 运行Docker容器
+
+  构建完了我们使用 `docker image ls` 就可以看到我们新构建的镜像啦，最后一步就是起容器服务了。
+
+  `-p` 命令这里将容器内的端口8080映射到操作系统的端口8080上去，如果不指定8080，那我们在自己的操作系统上就无法获取到它提供的服务，所以 `-p` 还是非
+常重要的。
+
+`$ docker run -p 8080:8080 --rm -it go-server`
+
+  如果一切无误，到浏览器中输入 `localhost:8080/hash` 就可以看到我们跑在 `Docker` 里面的 `http` 服务器已经成功地跑起来啦。
+
+## 总结
+  
+  让自己的应用跑在 `Docker` 容器中非常简单，第一步就是构建自己的应用程序的源码，第二步正确编写适应自己业务场景的 `Dockerfile` 然后利用`Docker` 
+自带的功能打包成一个镜像，最后一步就是运行容器了。就这么三步走，可谓是 `Docker`在手，天下我有了。
+
diff --git a/EventProcessEngine.md b/EventProcessEngine.md
new file mode 100644
index 0000000..b01693f
--- /dev/null
+++ b/EventProcessEngine.md
@@ -0,0 +1,167 @@
+# 实现一个事件处理引擎
+
+  在许多情况下，尤其是在搞一致性算法的时候，如何对事件（Event）集中进行处理就变成了一件很重要的事情，下面，我们来介绍如何写一个简单的事件处理引擎，
+并且向上层提供一个简单可用（无脑）的API供其他程序员使用。
+
+  首先我们需要明白我们要对各种各样的事件进行处理，例如，在PBFT中，我们的消息类型有`Preprepare`，`Prepare`，`Commit`，`ViewChange`等等，具体的
+消息类型的定义我们可以使用protobuf来，而无论是什么事件，我们在Golang中我们都可以把它们抽象成一个 `interface{}` 。
+
+```golang
+type Event interface{}
+```
+
+  这里我们定义的`Event`是我们以后围绕着处理的中心，我们继续看。定义完了`Event`，我们还要定义一个`Event`的接受者（Receiver），也就是事物处理的核心。
+  
+```golang
+type Receiver interface {
+    ProcessEvent(e Event) Event
+}
+```
+  
+  在这里我们注意到这是一个`interface`，只要你定义的对象实现了`ProcessEvent`这个方法，那么它就是一个`Receiver`，当然，你自己定义的`ProcessEvent`
+里面才是真正的业务逻辑，这里仅仅提供一个框架而已。
+
+  定义完了事件的接受者，`Receiver`，我们来看下更高层次的管理者`Manager`，如果把`Manager`想象成公司里的领导，那么他负责的事情就是调度，并且指派任务
+给专门的个体也就是我们的`Receiver`去处理。`Receiver`是具体干活的，而`Manager`则是分配任务的。
+
+
+```golang
+type Manager interface {
+    Inject(Event)
+    Queue() <-chan Event
+    SetReceiver(Receiver)
+    Start()
+    Halt()
+} 
+
+type managerImpl {
+    threaded 
+    receiver Receiver
+    events chan Event
+}
+
+type threaded struct {
+    exit chan struct{}
+}
+```
+
+  一个Manager的职能具体有两大点，一就是管理事件的队列（events这个通道），二就是取出队列中的事件，指派接受者（SetReceiver(Receiver)）进行处理
+（Start）。
+```golang
+func (em *managerImpl) Queue() {
+    return em.events
+}
+
+func (em *managerImpl) SetReceiver(receiver Receiver) {
+    em.receiver = receiver
+}
+
+func NewManagerImpl() Manager {
+    return &managerImpl{
+        events: make(chan Event),
+        threaded: threaded{make(chan struct{})}
+    }
+}
+```
+
+```golang
+func (em *managerImpl) Start() {
+    go em.eventLoop()
+}
+```
+  `Manager`的启动就是就是开了一个goroutine对消息进行循环处理，下面来看一下`eventLoop`的实现。
+
+```golang
+func (em *managerImpl) eventLoop() {
+    for {
+        select {
+        case e := <-em.events:
+            em.Inject(e)
+        case <-em.exit:
+            logger.Debug("event told to exit")
+            return
+        }
+    }
+}
+```
+
+  `eventLoop`里面是咋一看是一个死循环，但它还是有出口的，它通过`for select`机制一直去轮询`em.events`和`em.exit`这两个通道，如果`em.exit`这
+个通道有值，则说明该事件处理循环要退出了，这就是程序的一个出口，但如果`em.events`有消息返回，我们则将它插入到我们`manager`的事件队列里等待被处理，
+也就是调用`em.Inject(e)`。
+
+```golang
+func (em *managerImpl) Inject(event Event) {
+    if em.Receiver != nil {
+        SendEvent(em.Receiver, event)
+    }
+}
+```
+
+  `Inject`行为的主体是`manager`，`manager`把任务（event）分配给我们的receiver。
+  
+```golang
+func SendEvent(receiver Receiver, event Event) {
+    next := Event
+    for {
+        next  := receiver.ProcessEvent(next)
+        if next == nil {
+            break
+        }
+    }
+}
+```
+  `SendEvent`函数才是真正干活的主力，它主要就是调用`Receiver`实现定义好的`ProcessEvent`方法，因为处理一个事件后可能会返回另一件事件，所以循环
+处理它直到为空时候返回。看到这里，你可能会不理解处理意见事件会什么会返回另一件事件呢，其实现实中处理完A事件返回B事件的例子有很多，例如在PBFT中，
+处理完`Preprepare`事件，我们赶忙就要开始处理`Prepare`事件了。这种例子还有很多，以后有机会我们再详细介绍。
+
+  上面就是我们整个事件处理的引擎了，不难，但是设计的非常精妙，下面我们来看如何使用它。
+```golang
+type aEvent Event
+type bEvent Event
+type cEvent Event
+
+type Instance struct{
+    manager Manager
+}
+
+func (i *Instance) ProcessEvent(e Event) Event {
+    switch et := e.(type) {
+    case aEvent:
+        fmt.Println("Received A Event, return B Event")
+        return bEvent
+    case bEvent:
+        fmt.Println("Received B Event, return C Event")
+        return cEvent
+    case cEvent:
+        fmt.Println("Received C Event, return nil")
+        return nil
+    default:
+        fmt.Println("Received undefined message type")
+    }
+}
+
+func main() {
+    var i Instance
+    i.manager = NewManagerImpl()
+    i.manager.SetReceiver(i)
+    i.manager.Start()
+
+    i.manager.Queue() <- aEvent
+}
+```
+
+  这里我们定义了三种事件类型，并且定义了一个包含manager的结构体，这个结构体实现了`ProcessEvent`方法，也就是说它实现了`Receiver`这个接口，
+`ProcessEvent`方法里通过判断接收到的event的类型，来进行相应的处理，注意到处理完`aEvent`会返回`bEvent`，这就说我们说的处理完一件事件再返回
+一件事件的例子了。
+
+  在`main`函数中，我们新起一个`Instance`实例，并初始化里面的`manager`，把`manager`的`receiver`设置为自己，因为是`Instance`实现了
+`ProcessEvent`方法，所以说谁实现了`ProcessEvent`方法，`SetReceiver`就设置为谁，最后再用`Start`起一个goroutine不断地处理接收进行的事件。
+
+  在我们向manager管理的事件队列中插入一个`aEvent`事件后，`eventLoop`就会开始处理事件，命令行中应该会依次输出：
+```
+Received A Event, return B Event
+Received B Event, return C Event
+Received C Event, return nil
+```
+
+  这个事件处理引擎的实现非常精妙，还是希望读者可以反复阅读几次。
diff --git a/EventTimer.md b/EventTimer.md
new file mode 100644
index 0000000..fda0326
--- /dev/null
+++ b/EventTimer.md
@@ -0,0 +1,245 @@
+# Event Timer
+
+  还记得我们在 [EventProcessEngine](EventProcessEngine.md) 里讲过的 `Event Manager` 吗，我们这里要实现的 `Event Timer` 其实和那个是
+有点耦合的，本篇博客与[EventProcessEngine](EventProcessEngine.md) 是姊妹篇，如果没有看过的小伙伴建议先看上一篇再来看这一篇。
+
+  关于定时器，golang的标准库已经提供了一个免费的解决方案给我们了 。标准库里的 `Timer` 结构体里包含一个 `<- chan Time` 通道，在经历过一定的时间
+后，该通道就会返回，这样就达到了倒计时的目的，当然还有一个 `Reset` 方法用于重置我们的定时器。
+
+```golang
+type Timer struct {
+    C <- chan Time
+}
+
+func AfterFunc(d Duration, f func()) *Timer 
+
+func NewTimer(d Duration) *Timer
+
+func (t *Timer) Reset(d Duration) bool
+
+func (t *Timer) Stop() bool
+```
+
+  那么为什么要实现一个自己的定时器呢，当然是觉得官方提供的不够用啦。
+
+  先说一说我们的 `EventTimer` 会在哪里用到，例如在分布式系统中，主节点需要向从节点周期性发送心跳消息，以期望从节点可以判定主节点有没有出现宕机
+之类的故障，所以每个从节点都需要设置一个心跳超时的定时器，如果在规定的时间内，从节点接收到了来自主节点的心跳消息，那么从节点将定时器重置，如果没有
+收到，那么从节点会发起申请成为主节点的请求。
+
+  下面例举几个在PBFT算法中定义的几个定时器超时的事件。
+
+```golang
+// viewChangeTimerEvent is sent when the view change timer expires
+type viewChangeTimerEvent struct{}
+
+// viewChangeResendTimerEvent is sent when the view change resend timer expires
+type viewChangeResendTimerEvent struct{}
+
+// batchTimerEvent is sent when the batch timer expires
+type batchTimerEvent struct{}
+```
+
+  所以我们接下来需要实现的定时器需要有两个功能，第一点就是老功能，定时操作，第二点是增加的新功能，当定时器超时将我们预设好的事件发送给我们的事件管理
+器（Event Manager）作进一步处理。
+
+  首先，我们来定义一下我们自己实现的 `Timer` 需要实现的接口，作为一个定时器，第一要务肯定是定时了，所以我们需要它有倒计时的功能，当倒计时结束我们
+发送事先定义好的事件给我们的事件管理器（Event Manager），第二点我们需要在不需要它的时候随时停止它。
+
+```golang
+type Event interface{}
+
+type Timer interface {
+    SoftReset(timeout time.Duration, event Event)
+    Reset(timeout time.Duration, event Event)
+    Stop()
+    Halt()
+}
+
+type threaded struct {
+    exit chan struct{}
+}
+
+type timerImpl struct {
+    threaded 
+    timerChan <- chan time.Time
+    startChan chan *timerStart
+    stopChan  chan struct{}
+    manager   Manager
+}
+
+type timerStart struct {
+    hard     bool
+    event    Event
+    duration time.Duration
+}
+
+func newTimer(manager Manager) Timer {
+    et := &timerImpl{
+        threaded:  threaded{make(chan struct{})},
+        startChan: make(chan *timerStart),
+        stopChan:  make(chan struct{}),
+        manager: manager,
+    }
+    go et.loop()
+    return et
+}
+```
+
+  interface `Timer` 中的 `Reset` 和 `SoftReset` 方法的功能都是让定时器重新开始倒计时，倒计时结束向我们的事件管理器发送事件，然后由事件管理器
+对我们的事件进行集中处理。它们之间的区别就是 `Reset` 会清除掉之前所有定时的事件，而 `SoftReset` 则不会，`Stop` 和 `Halt` 则非常简单，就是停止
+定时器，但`Stop` 会清除掉所有定时的事件。
+
+  `timerImpl`  实现了 `Timer` 接口，这里就可以清楚地看到 `Reset` 和 `SoftReset` 就是向 `startChan` 中发送我们的倒计时事件，也就是和我们
+的定时器申明，在 `timeout` 这么长的时间后，发射一个 `event` 事件。
+
+```golang
+func (t *timerImpl) Reset(timeout time.Duration, event Event) {
+    t.startChan <- &timerStart{
+        duration: timeout,
+        event: event,
+        hard: true,
+    }
+}
+
+func (t *timerImpl) SoftReset(timeout time.Duration, event Event) {
+     t.startChan <- &timerStart{
+         duration: timeout,
+         event: event,
+         hard: false,
+     }
+}
+
+func (t *timerImpl) Stop() {
+    et.stopChan <- struct{}
+}
+
+func (t *timerImpl) Halt() {
+    select {
+    case <-t.threaded.exit:
+        logger.Warning("Attempted to halt a threaded object twice")
+    default:
+        close(t.threaded.exit)
+    }
+}
+```
+
+  接下来我们用工厂模式来新建我们的 `Timer`， 使用工厂模式有很多好处，我们会在另一篇博客中详细讲述它的用法和好处。
+
+```golang
+type TimerFactory interface {
+    CreateTimer() Timer
+}
+
+type timerFactoryImpl struct {
+    manager Manager
+}
+
+func NewTimerFactory(manager Manager) TimerFactory {
+    return &timerFactoryImpl(manager)
+}
+
+func (etf *timerFactoryImpl) CreateTimer() Timer {
+    return newTimer(etf.manager)
+}
+```
+
+  最后我们来看一下定时器最核心的函数 `loop()` 的实现。
+
+```golang
+func (et *timerImpl) loop() {
+	var eventDestChan chan<- Event
+	var event Event
+
+	for {
+		// A little state machine, relying on the fact that nil channels will block on read/write indefinitely
+
+		select {
+    // case 1.
+		case start := <-et.startChan:
+			if et.timerChan != nil {
+				if start.hard {
+					logger.Debug("Resetting a running timer")
+				} else {
+					continue
+				}
+			}
+			logger.Debug("Starting timer")
+			et.timerChan = time.After(start.duration)
+			if eventDestChan != nil {
+				logger.Debug("Timer cleared pending event")
+			}
+			event = start.event
+			eventDestChan = nil
+    // case 2.
+		case <-et.stopChan:
+			if et.timerChan == nil && eventDestChan == nil {
+				logger.Debug("Attempting to stop an unfired idle timer")
+			}
+			et.timerChan = nil
+			logger.Debug("Stopping timer")
+			if eventDestChan != nil {
+				logger.Debug("Timer cleared pending event")
+			}
+			eventDestChan = nil
+			event = nil
+    // case 3.
+		case <-et.timerChan:
+			logger.Debug("Event timer fired")
+			et.timerChan = nil
+			eventDestChan = et.manager.Queue()
+    // case 4.
+		case eventDestChan <- event:
+			logger.Debug("Timer event delivered")
+			eventDestChan = nil
+    // case 5.
+		case <-et.exit:
+			logger.Debug("Halting timer")
+			return
+		}
+	}
+}
+```
+
+  虽然又一点恐怖，还是一步一步来吧。
+
+  首先，说一下大致的思路，`loop()` 方法在开头定义了 `eventDestChan` 通道变量和 `event` 变量分别用于记录事件发送的目的地和事件本身。`loop()` 
+方法使用 `for select` 机制去轮询 `timerImpl` 中定义的几个通道。并且5个case条件中都是等待从通道中读取数据，2和5都是非正常流程，而1，3，4则是
+正常的流程。我们先从非正常流程说起。
+
+  当程序某处调用 `Stop()` 方法时，`stopChan` 里就会有数据 `struct{}` ，`case 2` 就会被执行，我们分别将`timerChan`，`eventDstChan`，
+`event` 设置为nil就可以达到暂停的目的了，非常简单。
+
+  当程序某处调用 `Halt()` 方法时，同样道理， `case 5` 会被执行，整个定时器将会被暂停，然后返回，这里也没有什么难度。
+
+  接下来我们来捋一捋正常的流程也就是倒计时结束时发射事件的流程。一般来说正常的流程无非是程序某处调用了 `Reset()` 或者 `SoftReset()` 方法，那么
+我们的 `startChan` 里面就会有一个 `timerStart` 结构体，此时 `case 1` 就会被执行，然后判断当前时候是否有正在倒计时的时间，如果有并且新事件为
+hard，那么我们可以重置之前的倒计时，如果不是，则进入下一个for循环中。之后我们通过设置 `et.timerChan = time.After(start.duration)` 来真正
+开始倒计时，并且设置倒计时结束后要发生的event，但此时 `eventDestChan` 仍应设置为nil，毕竟倒计时还没有结束呢，超时事件不能马上发射。
+
+  5，4， 3， 2， 1，眼瞧着我们之前设置好的倒计时结束了，那么我们的 `case 3` 就会被紧接着执行了，倒计时结束，说明超时事件已经触发了，但是现在我们
+超时事件究竟应该发送给谁还不知道，通过设置 `eventDestChan = et.manager.Queue()` 就将我们的事件目的地设置为我们的事件管理器，然后通过设置
+`et.timerChan = nil` 就可以暂停我们的定时器了。
+
+  执行完 `case 3`， 注意到我们现在 `event` 和 `eventDstChan` 都已经不为nil了，那么终于可以执行我们的 `case 4` 了，此处才真正地将我们的超时
+事件发送给我们的事件处理的目的地，之后的流程就交给我们的事件管理器（Event Manager）来处理啦。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FSM.md b/FSM.md
new file mode 100644
index 0000000..e95085c
--- /dev/null
+++ b/FSM.md
@@ -0,0 +1,277 @@
+# 实现一个有限状态机
+
+  在实际工程代码当中，常常会用到有限状态机(Finite-state Machine. FSM)，例如在p2p网络中一个节点可能拥有多种状态，有限状态机可以用于表示有限个状态
+及所有可能的状态之间转移的情况。利用有限状态机就可以轻松地解决节点在不同状态之间转移的情况。这种编程模型可以避免丑陋的switch语句。
+
+  以门的开启和关闭举例，一扇门拥有两种状态（state），open和closed，我们将门关上，那它的状态就由open转移到closed，这里我们将open称为初始状态，
+将closed称为目标状态，分别用src和dst表示。而导致状态转移的动作我们称它为事件（event），状态的转移都是由特定事件触发的。
+ 
+```golang
+type EventDesc struct {
+    Name string 
+    Src []string 
+    Dst string  
+}
+
+type Events []EventDesc
+```
+
+  这里Name表示触发状态转移的事件名称，Src是状态转移过程中的初始状态，注意到它是一个数组，因为可以有多个不同的初始状态转移到同一个目标状态，而Dst是
+状态转移过程中的目标状态。上面的结构体就代表了有限状态机中触发状态转移的事件，可以把它理解成一个导火索，有了它，有限状态机才在不同的状态之间跳跃。
+
+  下面我们再来定义有限状态机的结构体，一个有限状态机需要哪些信息呢，首先，肯定需要一个值来标定它现在处于什么状态，也就是有限个状态中它处于哪个阶段，
+还需要一个东西来表示各个状态之间如何转移，如在事件E发生的情况下状态A转移到状态B。还需要一个回调方法集合（callbacks），它可以用于在状态转移发生时需
+要分别调用什么方法。
+
+```golang
+type eKey struct {
+    event string
+    src string
+}
+
+type cKey struct {
+    target string
+    callbackType int
+}
+
+type FSM struct {
+    current string
+    transitions map[eKey]string
+    callbacks map[cKey]string
+    transition func()
+}
+
+```
+
+  还是拿开门关门举例子，当门刚开始的状态是open，那么current=open，我们用手关门，就会查看transitions这个map中open和关门这个动作所对应的目标状态
+是什么，发现是closed，然后在状态转移的过程中还会调用注册过的callback方法。以上就是基本的实现一个FSM的思路。
+
+  下面我们来讨论一下回调方法（callback）的种类。
+  
+```golang
+const (
+    callbackNone int = iota
+    callbackBeforeEvent
+    callbackLeaveState
+    callbackEnterState
+    callbackAfterState
+)
+```
+
+  触发一次状态的导火索是一个特定的事件Event，我们记为E，因为E的发生，状态A变成状态B，所以我们一共可以定义四种回调方法，分别是在事件发生之前和之后，
+也就是callbackBeforeEvent，callbackAfterEvent，还有就是离开初始状态和进入目标状态的回调函数，callbackLeaveState和callbackEnterState。
+
+  而一个callback其实就是一个回调函数 `type Callback func(*Event)` 。
+
+```golang
+func NewFSM(initial string, events []EventDesc, callbacks map[string]Callback) *FSM {
+	var f FSM
+	f.current = initial
+	f.transitions = make(map[eKey]string)
+	f.callbacks = make(map[cKey]Callback)
+
+	// Build transition map and store sets of all events and states.
+	allEvents := make(map[string]bool)
+	allStates := make(map[string]bool)
+	for _, e := range events {
+		for _, src := range e.Src {
+			f.transitions[eKey{e.Name, src}] = e.Dst
+			allStates[src] = true
+			allStates[e.Dst] = true
+		}
+		allEvents[e.Name] = true
+	}
+
+	// Map all callbacks to events/states.
+	for name, c := range callbacks {
+		var target string
+		var callbackType int
+
+		switch {
+		case strings.HasPrefix(name, "before_"):
+			target = strings.TrimPrefix(name, "before_")
+			if target == "event" {
+				target = ""
+				callbackType = callbackBeforeEvent
+			} else if _, ok := allEvents[target]; ok {
+				callbackType = callbackBeforeEvent
+			}
+		case strings.HasPrefix(name, "leave_"):
+			target = strings.TrimPrefix(name, "leave_")
+			if target == "state" {
+				target = ""
+				callbackType = callbackLeaveState
+			} else if _, ok := allStates[target]; ok {
+				callbackType = callbackLeaveState
+			}
+		case strings.HasPrefix(name, "enter_"):
+			target = strings.TrimPrefix(name, "enter_")
+			if target == "state" {
+				target = ""
+				callbackType = callbackEnterState
+			} else if _, ok := allStates[target]; ok {
+				callbackType = callbackEnterState
+			}
+		case strings.HasPrefix(name, "after_"):
+			target = strings.TrimPrefix(name, "after_")
+			if target == "event" {
+				target = ""
+				callbackType = callbackAfterEvent
+			} else if _, ok := allEvents[target]; ok {
+				callbackType = callbackAfterEvent
+			}
+		default:
+			target = name
+			if _, ok := allStates[target]; ok {
+				callbackType = callbackEnterState
+			} else if _, ok := allEvents[target]; ok {
+				callbackType = callbackAfterEvent
+			}
+		}
+
+		if callbackType != callbackNone {
+			f.callbacks[cKey{target, callbackType}] = c
+		}
+	}
+
+	return &f
+}
+```
+
+1. 在new一个FSM的时候，我们先定义它的初始状态current，还有状态机中所有可能的状态迁移情况以及它的回调函数。
+2. 这里我们建立所有可能的状态转移的情况。
+3. 注册回调函数，也就是在事件发生前后，和改变状态的时候的回调函数。
+
+  在初始化完一个FSM之后，也就是说规定了FSM该拥有的所有状态以及状态转移时候应该调用的函数之后，我们来看看如何让这个状态机动起来，我们之前已经知道，
+触发状态机变化的就是外部的特定的事件，所以我们需要灵活地去处理这些事件，来使得我们的状态机可以动起来。
+  
+  在上面我们定义了EventDesc这个结构体，注意到那个结构体是多对一的，也就是多个初始状态对应一个目标状态，我们现在定义一个真正的一对一的事件，这里的
+一对一指的是一个初始状态对应一个目标状态。
+
+```golang
+type Event struct {
+    FSM *FSM
+    Event string
+    Src string
+    Dst string
+    Err error
+    Args []interface{}
+    canceled bool 
+    async bool
+}
+
+```
+
+  所以我们如何调用FSM并且进而使它的状态进行转化并且调用相应预先注册好的回调函数呢，我们通过向FSM实例传送一个event事件，FSM会先判断当前是否正在转移之
+中，也就是 f.transition 是否为nil，若不为nil则说明状态机正在状态转移之中，否则则说明不是，继而综合FSM当前的状态和此次遇到的事件决定目标状态，然后按
+顺序调用回调函数beforeEventCallbacks => leaveStateCallbacks => enterStateCallbacks => afterEventCallbacks。这样一次状态转移就算完成了。
+
+```golang
+func (f *FSM) Event(event string, args ...interface{}) error {
+	if f.transition != nil {
+		return &InTransitionError{event}
+	}
+
+	dst, ok := f.transitions[eKey{event, f.current}]
+	if !ok {
+		for ekey := range f.transitions {
+			if ekey.event == event {
+				return &InvalidEventError{event, f.current}
+			}
+		}
+		return &UnknownEventError{event}
+	}
+
+	e := &Event{f, event, f.current, dst, nil, args, false, false}
+
+	err := f.beforeEventCallbacks(e)
+	if err != nil {
+		return err
+	}
+
+	if f.current == dst {
+		f.afterEventCallbacks(e)
+		return &NoTransitionError{e.Err}
+	}
+
+	f.transition = func() {
+		f.current = dst
+		f.enterStateCallbacks(e)
+		f.afterEventCallbacks(e)
+	}
+
+	err = f.leaveStateCallbacks(e)
+	if err != nil {
+		return err
+	}
+
+	err = f.Transition()
+	if err != nil {
+		return &InternalError{}
+	}
+
+	return e.Err
+}
+
+func (f *FSM) Transition() error {
+	  if f.transition == nil {
+		  return &NotInTransitionError{}
+	  }
+	  f.transition()
+	  f.transition = nil
+	  return nil
+}
+```
+
+## 有限状态机的简单实践
+
+```golang
+package main
+
+import (
+    "fmt"
+    "github.com/looplab/fsm"
+)
+
+func main() {
+    fsm := fsm.NewFSM(
+        "closed",
+        fsm.Events{
+            {Name: "open", Src: []string{"closed"}, Dst: "open"},
+            {Name: "close", Src: []string{"open"}, Dst: "closed"},
+        },
+        fsm.Callbacks{},
+    )
+
+    fmt.Println(fsm.Current())
+
+    err := fsm.Event("open")
+    if err != nil {
+        fmt.Println(err)
+    }
+
+    fmt.Println(fsm.Current())
+
+    err = fsm.Event("close")
+    if err != nil {
+        fmt.Println(err)
+    }
+
+    fmt.Println(fsm.Current())
+}
+
+```
+
+  上述例子就定义了一个简单的开门和关门的状态机，这里我们门这个状态机的初始状态是closed，它可以利用open这个事件将状态从closed状态转移到open状态，
+也可以利用close这个事件将状态从open状态转移到closed状态。注意这里没有定义回调函数（fsm.Callbacks{}为空），所以这两件事件触发的时候什么事情也不
+会发生。
+
+  而调用事件就是通过fsm.Event("open”)或fsm.Event("close”)来完成的。
+  
+  上述就是实现一个简单的有限状态机的代码啦，具体的实现可以参考[Finite State Machine](http://github.com/looplab/fsm)。
+  
+  简单总结一下，实现有限状态机需要下面几件事情。
+1. 有限状态机的初始状态
+2. 有限状态机各个状态之间迁移的各种情况，也就是状态拓扑图
+3. 状态迁移时的回调方法
+
diff --git a/FactoryPattern.md b/FactoryPattern.md
new file mode 100644
index 0000000..e4528e0
--- /dev/null
+++ b/FactoryPattern.md
@@ -0,0 +1,149 @@
+# 工厂模式
+  工厂模式是设计模式里面的一种，具体点属于创建模式（creational pattern），它提供了一种创建对象的最佳方式。与传统的new来进行初始化对象不同，
+工厂模式在初始化对象时不会向客户端暴露创建的逻辑，也就减少了出错时到处修改的麻烦，工厂方法虽然稍为增加了程序猿的工作量，但会给系统带来更大的可
+拓展性和尽量少的修改。
+
+  下面我们来看一下如何使用工厂模式，工厂模式有几个要点，掌握住了几个要点，就可以轻松写代码了。
+
+* Creator: 申明我们的工厂方法，会返回抽象的Product
+* Product: 申明我们的工厂方法会返回的东西
+* Concrete Creator: 具体的工厂，返回一个特定的Product或者说是Concrete Product
+* Concrete Product: 具体的Product的实现
+
+我们以实现一个制造电脑组件的工厂方法作为例子来深入了解一下工厂模式的使用吧，我们的工厂会生产鼠标，键盘，显示器这三种组件，我们把工厂定义为接口
+`Factory` ，而生产的产品定义为 `Product` 。`Factory`  通过 `Create()` 来生产 `Product` ，这就是工厂方法的精髓所在。
+
+```golang
+type Factory interface {
+    Create(spec Spec) Component
+}
+
+type Component interface {
+    Make(io.Writer) error
+}
+
+type Spec struct {
+    MadeIn string
+}
+```
+
+  下面我们都实现了三种产品，分别是 `Mouse` ，`Keyboard` 和 `Screen` 。注意到他们都实现了 `Component` 接口，说明它们都是电脑的组件。
+  
+```golang
+type Mouse struct {
+    MadeIn    string
+    Bluetooth bool
+}
+
+func (m *Mouse) Make(w io.Writer) error {
+    _, err := fmt.Fprintf(w, "The mouse is made in %s, and bluetooth enabled is %v\n", m.MadeIn, m.Bluetooth)
+    return err
+}
+```
+
+```golang
+type Keyboard struct {
+    MadeIn    string
+    Bluetooth bool
+}
+
+func (k *Keyboard) Make(w io.Writer) error {
+    _, err := fmt.Fprintf(w, "The Keyboard is made in %s, and bluetooth enabled is %v\n", k.MadeIn, k.Bluetooth)
+    return err
+}
+```
+
+```golang
+type Screen struct {
+    MadeIn     string
+    Resolution uint64
+}
+
+func (s *Screen) Make(w io.Writer) error {
+    _, err := fmt.Fprintf(w, "The Screen is made in %s, And the resolution is %d\n", s.MadeIn, s.Resolution)
+    return err
+}
+```
+
+  然后我们定义具体的工厂，来生产具体的电脑组件，`MouseFactory` ，`KeyboardFactory` 和 `ScreenFactory` 都实现了 `Factory` 接口，并且返回
+具体的 `Component` 例如 `Mouse` ，`Keyboard` 和 `Screen` 。也就是说让子类决定实例化哪一个工厂类，工厂模式使得其创建过程延迟到子类，当然这里
+说子类并不是特别恰当，毕竟golang里没有类的概念。
+
+```golang
+type MouseFactory struct{}
+
+func (mf *MouseFactory) Create(spec Spec) Component {
+    return &Mouse{
+        MadeIn:    "China",
+        Bluetooth: true,
+    }
+}
+```
+
+```golang
+type KeyboardFactory struct{}
+
+func (kf *KeyboardFactory) Create(spec Spec) Component {
+    return &Keyboard{
+        MadeIn:    "China",
+        Bluetooth: false,
+    }
+}
+```
+
+```golang
+type ScreenFactory struct{}
+
+func (sf *ScreenFactory) Create(spec Spec) Component {
+    return &Screen{
+        MadeIn: "China",
+        Resolution: 4000000,
+    }
+}
+```
+
+  `Computer` 这个结构体包含了不同的工厂，这就可以让我们自定义`Computer` 所包含的内容。
+
+```golang
+type Computer struct {
+    ComponentFactories []Factory
+}
+
+
+func (c *Computer) Make(w io.Writer) error {
+    spec := Spec{
+        MadeIn: "China",
+    }
+
+    if _, err := fmt.Fprintln(w, "Computer Manufacture Begin"); err != nil {
+        return err
+    }
+
+    for _, factory := range c.ComponentFactories {
+        component := factory.Create(spec)
+        if err := component.Make(w); err != nil {
+            return err
+        }
+    }
+
+    _, err := fmt.Fprintln("Computer Manufacture Done")
+    return err
+}
+```
+
+  注意到通过工厂模式来产生实例时非常简单，因为我们之前已经把代码封装好了，这样就减少了出现错误或者业务需求改变时修改代码的机会了。
+
+```golang
+c := &Computer{
+    ComponentFactories: []Factory{
+        &MouseFactory{},
+        &ScreenFactory{},
+        &KeyboardFactory{},
+    },
+}
+
+c.Make(os.Stdout)
+```
+
+  工厂方法是实现代码去耦合的非常精妙的一种方法，希望读者可以仔细品味并加以掌握。如果下次你的项目中需要在很多地方初始化相同的对象，你可以抛弃传统的
+new方法而转向使用工厂模式来新建对象。
diff --git a/Fanin.md b/Fanin.md
new file mode 100644
index 0000000..6e15dbf
--- /dev/null
+++ b/Fanin.md
@@ -0,0 +1,102 @@
+  在对消息的处理过程中，我们常常会遇到不同来源的消息，如在Golang中这些消息来自于不同的通道，但是这些消息在本质上都是相同的，所以，如何把这些消息
+进行聚合后再处理，就是我们这篇文章需要探讨的内容。下面我们引入Fanin这种编程模型。
+
+  假设Master节点需要处理3个Slave节点的消息，这3个Slave节点的消息我们使用Golang中的通道进行模拟。
+  
+```golang
+type Message interface{}
+
+func Fanin(cs ...<-chan *Message) <-chan *Message {
+    var wg sync.WaitGroup
+    
+    out := make(chan *Message)
+    
+    send := func(c <-chan *Message) {
+        for n := range c {
+            out <- n
+        }
+        wg.Done()
+    }
+    
+    wg.Add(len(cs))
+    
+    for c := range cs {
+        go send(c)
+    }
+    
+    go func() {
+        wg.Wait()
+        close(out)
+    }()
+    return out
+} 
+```
+
+  在函数中我们新建一个用于消息输出的通道out，并且遍历所有cs中的输入通道c，将中的消息取出后再重新放入out当中，这样就达到了将多个通道合并为一个通道的
+目的。
+
+  但是上述方法也有其弊端，就是需要提前知晓所有的输入通道，但是在很多情况下，输入通道可能是动态增加的，那这种情况下我们应该怎么办呢？
+  
+```golang
+type Message interface{}
+
+type MessageFan struct {
+    ins []<-chan *Message
+    out <-chan *Message
+    lock sync.Mutex
+}
+
+func NewMessageFan() *MessageFan {
+    return &MessageFan{
+        ins: []<-chan *Message,
+        out: make(<-chan *Message),
+    }
+}
+
+func (fan *MessageFan) AddFaninChannel(channel <-chan *Message) {
+    fan.lock.Lock()
+    defer fan.lock.Unlock()
+    
+    for _, c := range fan.in {
+        if c == channel {
+            fmt.Println("Received duplicate connection")
+            return
+        }
+    }
+    
+    fan.ins = append(fan.ins, channel)
+    
+    go func() {
+        for msg := range channel {
+            out <- msg
+        }
+        
+        fan.lock.Lock()
+        defer fan.lock.Unlock()
+        
+        for i, c := range fan.ins {
+            if c == channel {
+                fan.ins = append(fan.ins[:i], fan.ins[i+1:]...)
+            }
+        }
+    }()
+}
+
+func (fan *MessageFan) GetOutChannel() {
+    return fan.out
+}
+```
+  这里我们定义了一个`MessageFan`结构体，里面包含了一个输入通道的数组和一个输出通道，在实例化`MessageFan`的时候，注意，我们仅仅对`out`进行了`make`
+操作，因为`out`通道是确定的，只有一个，而我们的输入通道却是`runtime`时决定的，所以无法使用`make`操作。
+  当我们调用`AddFaninChannel`方法的时候，我们先遍历`ins`这个通道数组，看有没有相同的实现已经加入过的通道，有则返回，没有则将它加入`ins`，同样的，
+在`goroutine`中轮询这个`channel`，将它的消息塞入`out`中，注意，在一般情况下该for循环是阻塞的，如果for循环返回，则说明`channel`已经被关闭了，即
+在代码的某处执行了`close(channel)`这个操作，所以说明它已经没有作用了，我们就可以把它在我们的ins数组中删除。    
+    
+# 总结
+  
+  上述两种方法都实现了Fanin这种编程模型，当你遇到那种需要对不同来源但是类型却相同的消息进行集中处理时，就可以考虑使用这种编程模型啦。
+    
+    
+    
+    
+    
diff --git a/LeakyBuffer.md b/LeakyBuffer.md
new file mode 100644
index 0000000..271db0a
--- /dev/null
+++ b/LeakyBuffer.md
@@ -0,0 +1,76 @@
+# Leaky Buffer
+
+  在科学上网服务中，客户端不断地向shadowsocks服务器发送数据，服务器从网络中读取经过加密的数据然后进行解密操作，为了避免重复的分配内存和释放内存操作，
+我们引入 `LeakyBuffer` 这种编程模型，`LeakyBuffer` 通常也被叫做 `LeakyBucket` ，或者说是漏桶模型。`LeakyBuffer` 维护了固定个数个字节数组
+（free list），如果我们的程序需要使用内存， 那么它会从 `LeakyBuffer` 维护的 `freelist` 去拿，如果 `freelist` 中没有了，则再重新make一个，
+当程序使用完了这段内存，不像通常那么被golang的runtime进行垃圾回收操作，我们把它重新放回 `LeakyBuffer` 维护的 `freelist` 中。
+
+  下面我们来看一下 `Leaky Buffer` 的实现吧。
+
+```golang
+const leakyBufferSize = 4096
+const maxNum = 2048
+
+type LeakyBuffer struct {
+    bufferSize  int
+    freeList chan []byte
+}
+```
+
+  `LeakyBuffer` 的实现非常简单，它主要维护了两个变量，一就是每个 `buffer`  的大小，而就是一个 `freelist` ，真正用于维护我们的内存。
+
+  在上面的代码中我们定义每个 `buffer` 的大小是4096，这里的单位是字节，`freelist` 的长度是2048，所以我们这个 `LeakyBuffer` 总共可以使用的内存
+大小就是 4096 * 2048 B 也就是 8MB ，这对于一般的网络应用已经足够了。
+
+```golang
+var leakyBuf = NewLeakyBuffer(maxNum, leakyBufferSize)
+
+func NewLeakyBuffer(n, bufSize int) *LeakyBuffer {
+    return &LeakyBuffer{
+        bufferSize: bufSize,
+        freeList: make(chan []byte, n)
+    }
+}
+```
+
+  `NewLeakyBuffer` 返回一个 `LeakyBuffer` 指针，它维护的 `freelist`  就是一个容量为n的通道。
+
+  下面我们来看看如何使用 `LeakyBuffer` ，`LeakyBuffer` 只定义了两种操作，存和取。
+
+## 取操作
+  `Get` 操作从 `LeakyBuffer` 所维护的 `freelist` 的通道中取出一个字节数组，如果 `freelist` 为空，则说明没有多余的空闲字节数组，则自己make一个字节数组然后返回。
+
+```golang
+func (lb *LeakyBuffer) Get() (b []byte) {
+    select {
+    case b := <- lb.freeList:
+    default:
+        b := make([]byte, lb.bufferSize)
+    }
+    return
+}
+```
+
+
+## 存操作
+  当程序使用完了这段内存空间后，我们将它重新放回 `LeakyBuffer` 中进行回收而不是用 `golang runtime` 进行垃圾回收，注意一种特殊情况，就是当
+`freelist` 已经满了，这时我们会执行default case， 也就是什么事情也不干，然后这个无家可归的字节数组就会自动被系统进行垃圾回收，这就是
+`LeakyBuffer` 这个名字中 Leaky 的由来，也就是有可能会泄漏出去。
+
+```golang
+func (lb *LeakyBuffer) Put(b []byte) {
+     if lb.bufferSize != len(b) {
+         panic("invalid buffer size that's put into leaky buffer")
+     }
+     select {
+     case lb.freeList <- b:
+     default:
+     }
+     return
+}
+```
+
+  上述就是 `LeakyBuffer` 的实现了，如果下次你遇到需要重复分配很多相同大小的内存空间时，不妨可以使用一下这个编程模型。
+
+## Golang 标准库的实现
+  在 golang 标准库中也实现了类似于 `LeakyBuffer` 的接口，`sync.Pool` ，有兴趣的读者不妨阅读一下它的源码，这里就不再重复介绍了。
diff --git a/LoadBalancing.md b/LoadBalancing.md
new file mode 100644
index 0000000..8106b4a
--- /dev/null
+++ b/LoadBalancing.md
@@ -0,0 +1,156 @@
+# 使用 etcd 进行负载均衡
+  
+  当服务提供者（Service Provider）将服务注册到 `etcd` 之后，为了更加理想地分配任务·，我们就要考虑负载均衡问题了，负载均衡的核心就是把让任务合理地
+分摊到多个执行单元上执行，以期获得更高的吞吐量或者说是数据处理能力，通俗点讲就是大家都有肉吃，没有人会撑死也没人会饿死，大家都得到适合自己的那一份。
+
+  下图中，`Service Consumer` 即服务的消费者，它通过向 `Provider` 源源不断地发送服务请求，负载均衡问题要解决的问题就是如何将请求合理地分配给不同
+的 `Service Provider` 处理，例如，我们下图中有三台服务提供者，假如服务提供者的服务都是比较消耗时间的（例如计算哈希值），为了增加整个系统的吞吐量，
+我们要考虑合适的任务分配策略，这就是负载均衡的核心所在，要是只将请求发送给其中一台 `Service Provider`，那么其它两台都会空闲着不执行任务，这样的话
+整个系统的吞吐量肯定就上不来了，毕竟没有充分的利用所有的资源，所以，我们要把任务平均地分配给每个执行单元去处理。
+
+![loadbalancing](https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/system-architecture.png)
+
+  下面我们来实现一个负载均衡的例子，实现的思路非常简单，定义一个 `LoadBalancingService` 结构体，其中的 `etcdClient` 用于与 `etcd` 进行沟通交
+流以获取相应的注册信息，`nodes`，`nodeMap`，`nodeCount` 用于记录已经注册在 `etcd` 的服务提供者的信息。
+
+```golang
+type LoadBalancingService struct {
+    etcdClient client.Client
+    connected  bool
+    nodes      []string
+    nodeMap    map[string]int
+    nodeCount  int
+    sync.RWMutex
+}
+```
+
+```golang
+func (s *LoadBalancingService) watch(watcher client.Watcher) {
+    for {
+        resp, err := watcher.Next(context.Background())
+        if err == nil {
+            if resp.Action == "set" {
+                n := resp.Node.Value
+                s.addNode(n)
+            } else if resp.Action == "delete" {
+                n := resp.PrevNode.Value
+                s.removeNode(n)
+            }
+        }
+    }
+}
+```
+
+  上面的核心就是 `Watcher` 机制，在新事件到来之前，`Watcher` 的`Next` 方法会一直阻塞，直到事件返回为止，一般来说都是在 `for` 循环中调用 `Next`
+以期达到轮询（polling）的效果。
+
+```golang
+type Watcher interface {
+    Next(context.Context) (*Response, error)
+}
+```
+
+  `Connect` 函数就是用于客户端与 `etcd` 连接并根据 `serviceName` 读取当前已经注册过的服务，并通过 `watch` 机制不断地更新当前可用的服务。
+
+```golang
+func  (s *LoadBalancingService) Connect(serviceName string, endPoints []string) error {
+    if s.connected {
+        log.Println("Can't connect twice")
+        return errors.New("Already connected")
+    }
+
+    s.nodeMap = make(map[string]int)
+    s.nodeCount = 0
+
+    cfg := client.Config{
+        Endpoints:   endpoints,
+        Transport:   client.DefaultTransport,
+        HeaderTimeoutPerRequest: time.Second,
+    }
+
+    var err error
+    s.etcdClient, err = client.New(cfg)
+    if err != nil {
+        return err
+    }
+    kapi := client.NewKeysAPI(s.etcdClient)
+
+    resp, err := kapi.Get(context.Background(), serviceName, nil)
+    if err != nil {
+        return err
+    } else {
+        if resp.Node.Dir {
+            for _, peer := resp.Node.Nodes {
+                n := peer.Value
+                s.addNode(n)
+            }
+        }
+    }
+
+    watcher := kapi.Watcher(serviceName, &client.WatcherOptions{Recursive: true})
+    go s.watch(watcher)
+    service.connected = true
+    return nil    
+}
+```
+
+  `GetNode` 采用了随机算法获取当前节点群中的随机节点进行处理我们的任务，这里是负载均衡算法的核心，说白了中随机挑选一个进行发送服务请求让服务提供者进
+行处理。
+
+```golang
+func (s *LoadBalancingService) GetNode() (string, error) {
+    if !s.connected {
+        return "", errors.New("Must call connect first")
+    }
+
+    s.RLock()
+    defer s.RUnlock()
+
+    if s.nodeCount == 0 {
+        return "", ErrEmptyService 
+    }
+
+    return s.nodes[rand.Intn(s.nodeCount)], nil
+}
+```
+
+  `addNode` 和 `removeNode` 分别对应远程服务提供者数量增加或者减少时的情况，并更新 `LoadBalancingService` 结构体中相应的数据结构。
+
+```golang
+func (s *LoadBalancingService) addNode(key string) {
+    s.Lock()
+    defer s.Unlock()
+
+    if _, ok := s.nodeMap[key]; ok {
+        if s.nodeCount >= len(s.nodes) {
+            s.nodes = append(s.nodes, key)
+        } else {
+            s.nodes[s.nodeCount] = key
+        }
+        s.nodeMap[key] = s.nodeCount
+        s.nodeCount++
+    }
+}
+
+func (s *LoadBalancingService) removeNode(key string) {
+    s.Lock()
+    defer s.Unlock()
+
+    if index, ok := s.nodeMap[key]; ok {
+        for i := index; i < len(s.nodes)-1; i++ {
+            s.nodes[i] = s.nodes[i+1]
+        }
+        s.nodeCount--
+        delete(s.nodeMap, key)
+    }
+}
+```
+
+## 负载均衡算法的改良
+  
+  在上面的例子中，我们采用的是随机算法，这种是基于每台处理任务的 `Service Provider` 性能差不多的情况下作出的抉择，但是现实生活中情况并不总是如此，
+每台服务器的性能，网络带宽都存在着或多或少的差异，所以，我们需要根据实际情况，对负载均衡的分配方法作相应的改进。
+
+  假设我们的服务提供者的平均综合性能比值为1:2:3，那么每台服务提供者任务分配的比例也应该是1:2:3，所谓能者多劳就是这个意思了。在其他情况下我们也可以根
+据流量比例分配任务，反正还是要具体问题具体分析。
+
diff --git a/MagnetLink.md b/MagnetLink.md
new file mode 100644
index 0000000..b06bc07
--- /dev/null
+++ b/MagnetLink.md
@@ -0,0 +1,95 @@
+# Magnet Link
+  
+  相信大部分人都使用过磁力链接来下载过网上的文件吧，但是估计很少人会去关心那稀奇古怪的磁力链接究竟是什么鬼，今天就让我们来解析一下磁力链接，看一下它里
+面隐藏的信息吧。
+
+  其实类似下面这种看似复杂的链接地址也就是由几个部分组成，开头的 `magnet` 我们把它称为 `scheme` 或者说是协议名，就像一般的 `http` 地址一样，
+`http` 也算是一种协议名，紧接着 `magnet:?` 后面就是几对键值对了，一般键值对之间以 `&` 符号划分，常见的键有：
+
+```
+magnet:?xt=urn:btih:0FF55426B9713084FF5229A16D21712B1E6C1625&dn=%e5%8d%97%e5%be%81%e5%8c%97%e6%88%98%20-%206415&tr=http%3a%2f%2ftracker.nexushd.org%2fannounce.php%3fpasskey%3d346ae8170f8427b078512150f3683285
+```
+
+* `xt` ：eXact Topic 的缩写，其实本质上就是一个文件的哈希值，用于唯一标示这个文件而存在的，这是整个磁力链接中不可或缺的一部分，少了它，基本上链接地址就无法解析了。
+* `dn` ：Display Name 的缩写，这个是用于向用户展示的文件的名称，这一项可以没有。
+* `tr` ： Tracker 的缩写，表示Tracker服务器的地址，取决于使用的技术，这一项也是选填的。
+* `ws` ： Web Seed 的缩写，表示网络种子，选填。
+* `urn` ：Uniform Resource Name 的缩写，也就是统一资源名称。
+* `btih` ： BitTorrent Info Hash 的缩写，表示种子的散列函数。
+
+知道了磁力链接地址中的关键信息，也就基本可以看懂链接地址中的各个部分分别代表什么含义了，但是由于其中一些信息还是经过特殊编码的，人类读起来还是比较费劲
+的，所以我们还是实现代码来解析它吧。
+
+  首先，来定义一个结构体来定义一下磁力链接中的组成部分，这里只选了几个重要的，`InfoHash` 代表的就是 `"urn:btih:"` 后面那一部分玩意儿，
+`Trackers` 数组代表的就是 `Tracker` 服务器的地址，`DisplayName` 就对应磁力链接中的 `dn` 。
+
+```golang
+type Magnet struct {
+    InfoHash Hash
+    Trackers []string
+    DisplayName string
+}
+
+const xtPrefix = "urn:btih:"
+
+func (m Magnet) String() string {
+    ret : = "magnet:?xt="
+    ret += xtPrefix + hex.EncodeToString(m.InfoHash[:])
+    if m.DisplayName != "" {
+        ret += "&dn=" + url.QueryEscape(m.DisplayName)
+    }
+    for _, tr := range m.Trackers {
+        ret += "&tr=" + url.QueryEscape(tr)
+    }
+    return ret
+}
+```
+
+  解析磁力链接的过程和解析一般的 `url` 的过程非常类似，关键的部分是哈希值部分的解析，由于 `BTIH` 这个部分的哈希值可能用 `Hex` 编码也可能用
+`Base32` 编码，所以我们要根据其哈希长度选择解码的方式，这里定义了一个函数变量 `var decode func(dst, src []byte) (int, error)` 用于接受我们
+具体的解码函数。
+
+```golang
+func ParseMagnetURI(uri string) (m Magnet, err eror) {
+    u, err := url.Parse(uri)
+    if err != nil {
+        err = fmt.Errorf("error parsing uri : %s", err) 
+        return
+    }
+    if u.Scheme != "magnet" {
+        err = fmt.Errorf("unexpected scheme: %q", u.Scheme)
+        return
+    }
+    xt := u.Query().Get("xt")
+    if !strings.HasPrefix(xtPrefix) {
+        err = fmt.Errorf("bad xt parameter")
+        return
+    }
+    
+    infoHash := xt[len(xtPrefix):]
+    
+    var decode func(dst, src []byte) (int, error)
+    switch len(infoHash) {
+    case 40:
+        decode = hex.Decode
+    case 32:
+        decode = base32.StdEncoding.Decode
+    }
+
+    if decode == nil {
+        err = fmt.Errorf("unhandled xt parameter encoding: encoded lenght", len(infoHash))
+        return
+    }
+    n, err := decode(m.InfoHash[:], []byte(infoHash))
+    if err != nil {
+        err = fmt.Errorf("error decoding xt: %s", err)
+        return
+    }
+    if n != 20 {
+        panic(n)
+    }
+    m.DisplayName = u.Query().Get("dn")
+    m.Trackers = u.Query()["tr"]
+    return
+}
+```
diff --git a/MerkleTree.md b/MerkleTree.md
new file mode 100644
index 0000000..44a2612
--- /dev/null
+++ b/MerkleTree.md
@@ -0,0 +1,162 @@
+# Merkle Tree
+  `Merkle Tree` 在各个领域都有着广泛的应用，就拿我们熟悉的 `bittorrent` 来举例，在我们使用 `bittorrent` 下载的时候，客户端会向许多并不信任的
+节点去下载目标文件的某个片段，利用 `Merkle proofs` 我们就可以验证我们下载的部分片段是否属于整个文件的一部分。`Merkle proofs` 可以用于验证某个
+数据子集是否从属于更大的集合。
+
+  那么下面我们来看一下如何实现一个 `Merkle Tree` 吧。与传统的二叉树类似，每个 `Merkle Tree` 中由许多节点组成，每个节点都指向它的左孩子节点，右
+孩子节点和父节点，同时，还有一个flag指明它是否为叶子结点等其他元信息。`Content` 是每个节点所存储的内容，只要实现了该接口 `Content` 的结构体都能
+被节点所存储。
+
+## 数据结构
+
+```golang
+type Node struct {
+    Parent *Node
+    Left   *Node
+    Right  *Node
+    leaf   bool
+    dup    bool
+    Hash   []byte
+    C      Content
+}
+
+type Content interface {
+    CalculateHash() []byte
+    Equals(other Content) bool
+}
+
+type MerkleTree struct {
+    Root       *Node
+    merkleRoot []byte
+    Leafs      []*Node
+}
+```
+
+  在 `Merkle Tree` 当中，有一个非常重要的特性就是获取节点的哈希值，我们来定义一个helper function 用于计算节点的哈希值。计算哈希分为两种情况，
+第一种就是如果当前被计算的节点为叶子结点，那么我们调用interface `Content` 中的 `CalculateHash` 方法来计算所存储内容的哈希值，如果不是叶子结点，
+则说明是中间层的节点，那么就计算左子节点和右子节点的哈希值的拼接值的哈希值，即 `H(P) = H( H(P.L) + H(P.R) )`。
+
+```golang
+func (n *Node) calculateNodeHash() []byte {
+    if n.leaf {
+        return n.C.CalculateHash()
+    }
+    h := sha256.New()
+    h.Write(append(n.Left.Hash, n.Right.Hash...))
+    return h.Sum(nil)
+}
+```
+
+## 新建一棵树
+
+```golang
+func NewTree(cs []Content) (*MerkleTree, error) {
+    root, leafs, err := buildWithContent(cs)
+    if err != nil {
+        return nil, err
+    }
+    mk := &MerkleTree{
+        Root: root,
+        merkleRoot: root.Hash,
+        Leafs: leafs
+    } 
+    return mk, nil
+}
+```
+
+
+```golang
+func buildWithContent(cs []Content) (*Node, []*Node, error) {
+    if len(cs) == 0 {
+        return nil, nil, errors.New("Error: cannot construct tree with no content")
+    }    
+    var leafs []*Node
+    for _, c := range cs {
+        leafs = append(leafs, &Node{
+            Hash: c.CalculateHash(),
+            C: c,
+            leaf: true,
+        })
+    }
+    if len(cs) % 2 == 1 {
+        duplicate := &Node{
+            Hash: leafs[len(leafs)-1].Hash,
+            C: leafs[len(leafs)-1].C,
+            leaf: true,
+            dup: true,
+        }
+        leafs = append(leafs, duplicate)
+    }
+    root := buildIntermediate(leafs)
+    return root, leafs, nil
+}
+```
+
+  `buildIntermediate` 函数利用递归的方法建立树，递归在树的建立中是一种非常常用的套路，只需要特别关注一下它的退出条件就可以了，这里的退出条件就是
+最后仅剩两个节点了，说明已经可以返回根节点，那么函数执行到这里就可以返回了。
+
+```golang
+func buildIntermediate(nl []*Node) *Node {
+    var nodes []*Node
+    for i := 0; i < len(nl); i += 2 {
+        h := sha256.New()
+        var l, r int = i, i+1
+        if r == len(nl) {
+            r = len(nl)-1
+        }
+        h.Write(nl[l].Hash, nl[r].Hash...)
+        n := &Node{
+            Left:  nl[l],
+            Right: nl[r],
+            Hash:  h.Sum(nil),
+        }
+        nodes = append(nodes, n)
+        nl[l].Parent = n
+        nl[r].Parent = n
+        if len(nl) == 2 {
+            return n
+        }
+    }
+    return buildIntermediate(nodes)
+}
+```
+
+  只有当叶子结点的个数为 `2^n` 的时候，才能保证每一层的中节点都能两两配对，但一般来说叶子结点的个数不一定恰好为 `2^n` ，在这种情况下，就可以将每一
+层的最右边的结点进行自我复制，自己与自己配对然后再计算哈希值，上面的算法就采用了这样的解决方法。
+
+```
+     ┌───┴──┐       ┌────┴───┐         ┌─────┴─────┐          ┌─────┴─────┐
+  ┌──┴──┐   │    ┌──┴──┐     │      ┌──┴──┐     ┌──┴──┐    ┌──┴──┐     ┌──┴──┐
+┌─┴─┐ ┌─┴─┐ │  ┌─┴─┐ ┌─┴─┐ ┌─┴─┐  ┌─┴─┐ ┌─┴─┐ ┌─┴─┐   │  ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ ┌─┴─┐ 
+   (5-leaf)         (6-leaf)             (7-leaf)                (8-leaf)
+```
+
+## 验证内容是否存在在 Merkle Tree 中
+
+  那么，我们又如何验证某个部分的内容是否真正存在于我们的 `MerkleTree` 中呢。具体的思路非常简单，就是遍历该树的叶子结点，看有没有与我们要验证的内容
+相一致的，如果没有则直接返回false，如果有则开始真正的验证阶段，验证的基本思路也不难，就是一个从叶子节点往根节点走并且验证这条路上的哈希值是否都正确的
+过程，先获取当前遍历的节点的父节点，然后判断父节点的左子节点和右子节点的哈希值是否相匹配，如果不匹配，则直接返回false，如果匹配，则继续验证知道根节点
+为止。
+
+```golang
+func (m *MerkleTree) VerifyContent(expectedMerkleRoot []byte, content Content) bool {
+    for _, l := range m.Leafs {
+        if l.C.Content.Equals(content) {
+            currentParent := l.Parent
+            for currentParent != nil {
+                h := sha256.New()
+               h.Write(append(currentParent.Left.calculateNodeHash(), currentParent.Right.calculateNodeHash()...))  
+                if bytes.Compare(h.Sum(nil), currentParent.Hash) != 0 {
+                    return false
+                } 
+                currentParent = currentParent.Parent
+            }
+            return true
+        }
+    }
+    return false
+}
+```
+
+
+
diff --git a/PKCS7_Padding.md b/PKCS7_Padding.md
new file mode 100644
index 0000000..c04c1c6
--- /dev/null
+++ b/PKCS7_Padding.md
@@ -0,0 +1,83 @@
+  由于某些特定加密算法的要求，例如AES中的CBC，要求被加密的数据是特定块大小的整数倍，例如在AES中一个块大小即BlockSize的大小为16字节，故被加密数据的
+长度`len(src) % BlockSize == 0`，但现实生活中要求加密的数据长度往往是随机的，所以需要有一种可靠高效的数据填充方法（padding）。
+
+  现在我们的问题是这样的，一个不定长度的数据作为加密的输入，我们需要把它填充到固定的长度，即满足`len(src) % BlockSize == 0`的条件，并且在解密时
+可以获得原来的数据。
+
+  现在的前提是BlockSize为16字节，输入长度随机。流程大致经过下面几步，填充=>加密=>网络传输=>解密=>去填充。问题的难点就是如何保证去填充之后可以获取
+原来填充之前的数据。
+
+  我们的初始数据即待加密数据的格式如下
+  
+  |XX16bytesXX|XX16bytesXX|…….|XX16bytesXX|XX?bytesXX|
+  
+  填充后得到的数据格式为如下。
+  
+  |XX16bytesXX|XX16bytesXX|…….|XX16bytesXX|XX16bytesXX|
+  
+  这里我们使用 |XX16bytesXX| 表示一段16字节的随机数据。也就是说我们需要把最后的?bytes填充到固定长度的16bytes，这里？的取值范围是0到15。
+现在我们就来引入PKCS7这种填充标准。
+
+  PKCS7填充的做法是这样的，首先它会确定需要被填充的字节的长度，也就是上述所说的?bytes的那一段字节。
+```golang
+padding := aes.BlockSize - len(src)%aes.BlockSize
+```
+
+  上面的代码段非常好理解，首先对待加密的数据长度对BlockSize取模，获得我们的?bytes，再利用它与BlockSize的差值获得我们需要填充的长度值，
+这里的padding就是一个int值。
+
+  下面就是真正填充的一个逻辑了。
+  
+```golang
+padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+```
+
+  这一行代码乍看起来有点复杂，我们一步一步来看，它要做的一件事情就是获得一个用于填充的文字，而这个文字就是利用我们上述获得的padding（注意它是一个int）
+转化成一个byte后重复padding次。
+
+  也就是说假设我们的padding是7，也就是需要填充7字节的信息，那我们的padtext也就是我们填充的文字就是 7 7 7 7 7 7 7，当然我们这里的每个7都是一个byte。
+  
+  以此类推，同理我们padtext里面的每一个数字就是一个byte，6 6 6 6 6 6 应该理解成byte(6) byte(6) byte(6) byte(6) byte(6) byte(6)。
+  
+  获得了我们的填充信息后，我们将原数据与我们的填充信息相连接就行了，下面就是我们完整填充过程的函数，非常简单。
+  
+```golang
+func PKCS7Padding(src []byte) []byte {
+    padding := aes.BlockSize - len(src)%aes.BlockSize
+    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+    return append(src, padtext...)
+}
+```
+
+  理解了PKCS7中填充的标准之后，我们再来看一下如何去填充，去填充的过程也非常简单，但是在工程代码中实现还需要考虑一些特殊的边界情况。
+  
+	下面直接给出去填充的代码。
+  
+```golang
+func PKCS7Unpadding(src []byte) ([]byte, error) {
+    length := len(src)
+    unpadding := int(src[length - 1])
+	
+    if unpadding > aes.BlockSize || unpadding == 0 {
+    return nil, fmt.Errorf("invalid unpadding")
+    }
+	  
+    pad := src[len(src)-unpadding:]
+    for i := 0; i < unpadding; i++ {
+        if pad[i] != byte(unpadding) {
+            return nil, fmt.Errorf("invalid padding")
+        }
+    }
+
+    return src[:(len(src)-unpadding)], nil
+}	
+```
+  这里我们需要去填充的为src，讲src的最后一个byte取出再转换为int，这个数值就是我们之前填充字节的个数，记为unpadding，如果unpadding的值大于
+BlockSize或者出现unpadding为0的情况，这种情况是一场的因为我们填充的时候就将padding值约束在[1, BlockSize-1)，所以出现不符合要求的padding值都
+将返回异常。
+
+  然后将数组末尾取出unpadding个字节，将unpadding个字节分别与byte(unpadding)这个字节进行比较，如果不想等，则返回异常。
+
+  最后如果一切都没有问题，则返回去除padding个字节后的byte数组。
+
+
diff --git a/Port_0.md b/Port_0.md
new file mode 100644
index 0000000..8542402
--- /dev/null
+++ b/Port_0.md
@@ -0,0 +1,45 @@
+# port 0, WTF?
+  
+  我们都知道 `TCP` 或者 `UDP` 的端口号可以从0一直到65535，而0到1023端口则被称为熟知端口，是系统保留使用的端口号，0号端口在 `TCP/IP` 中也属于保留
+端口号，但它并不可以在一般的 `TCP` 或者 `UDP` 通信中使用。
+
+  但是，如果0号端口不能被使用的话，那它又有什么用呢，简单来讲，就是如果程序监听了0号端口，那么它就会触发操作系统自动去寻找在0到65535这个范围内可以使
+用的端口号（即未被其他程序占用），这样就相当于动态分配一个端口号了，和 `DHCP` 协议有着异曲同工之妙，不过 `DHCP` 是用于动态分配IP地址，而0号端口则用
+于动态分配端口号，而且两者的工作原理也不同。
+
+  所以，如果想要得到一个动态的端口号，我们只要让程序监听0号端口就可以了，即 `net.Listen("tcp", "127.0.0.1:0")` ，下面给出一个获取动态端口号的示
+例代码。
+
+```golang
+package main
+
+import (
+    "net"
+    "strconv"
+)
+
+func GetFreePort() (port int, err error) {
+    listener, err := net.Listen("tcp", "127.0.0.1:0")
+    if err != nil {
+        return 0, err
+    }
+    defer listener.Close()
+     
+    addr := listener.Addr().String()
+    _, portString, err := net.SplitHostPort(addr)
+    if err != nil {
+        return 0, err
+    }
+    return strconv.Atoi(portString)
+}
+
+func main() {
+    port, err := GetFreePort()
+    if err != nil {
+        fmt.Println(err)
+        return
+    }
+
+    fmt.Println(port)
+}
+```
diff --git a/Protobuf.md b/Protobuf.md
new file mode 100644
index 0000000..83fffbd
--- /dev/null
+++ b/Protobuf.md
@@ -0,0 +1,117 @@
+# Protocol Buffer
+
+  Protobuf是一种用于信息交换的数据格式，你们可能会问我可以用JSON，再不济XML也可以用啊，为什么要接触这个完全没有用过的玩意儿呢？答案只有两个字：高效。
+使用XML不仅会占用更多的存储空间，而且会降低整个系统的性能。
+
+  搞过分布式系统的朋友一定知道，消息在分布式系统中起着至关重要的作用，例如两个节点之间相互交换自己的状态信息，一个网络中节点之间的交流就需要负载在消息
+之上，与人类一样，只有节点之间有一套共用的语言，分布式系统才能正常工作下去。而且protobuf可以让我们非常方便的定义消息的类型，它还提供了供我们序列化和
+反序列化的API，下面我们就来看看该如何使用它。
+
+## 前期准备
+  首先需要安装protobuf，使用macOS的用户可以考虑使用brew进行安装，安装完了之后还需要安装Go语言的protobuf插件—proto-gen-go，这个插件会被安装在
+`$GOPATH/bin`目录下。
+
+```
+$ brew install protobuf
+$ go get -u github.com/golang/protobuf/protoc-gen-go
+```
+
+## 定义我们自己的消息格式
+
+  使用protobuf，我们只需要定义一个以 `.proto` 结尾的文件，这里我们以PBFT算法中的几个消息类型为例子进行讲解，首先注意到”=1”， “=2”这样的标记，
+这些标记是为了二进制编码用的。其次，如果一个消息中有多个类似的成员，也就是一个数组，我们可以使用 `repeated` 这个关键字来表示。
+
+```protobuf
+syntax = "proto3";
+
+import "google/protobuf/timestamp.proto";
+
+package pbft;
+
+message request {
+    google.protobuf.Timestamp timestamp = 1;
+    bytes payload = 2;
+    uint64 replica_id = 3;
+    bytes signature = 4;
+}
+
+message request_batch {
+    repeated request batch = 1;
+}
+
+message pre_prepare {
+    uint64 view = 1;
+    uint64 sequence_number = 2;
+    string batch_digest = 3;
+    request_batch request_batch = 4;
+    uint64 replica_id = 5;
+}
+
+message prepare {
+    uint64 view = 1;
+    uint64 sequence_number = 2;
+    string batch_digest = 3;
+    uint64 replica_id = 4;
+}
+
+message commit {
+    uint64 view = 1;
+    uint64 sequence_number = 2;
+    string batch_digest = 3;
+    uint64 replica_id = 4;
+}
+```
+
+## 使用protoc编译器编译我们的消息
+```
+protoc -I=$SRC_DIR --go_out=$DST_DIR $SRC_DIR/messages.proto
+```
+  在命令行中运行上述命令，`-I` 表示你的源文件所在的目录，`--go_out`  表示你指定的生成目标文件（messages.pb.go）的目录，一般来说与源文件所在的目录
+相同，最后就是我们需要编译的源文件的路径。
+
+## 使用protobuf提供的API对消息进行写操作
+  
+  我们可以使用 `proto.Marshal()` 对数据进行序列化。序列化之后得到的是一个字节数组（ []byte ）。
+
+```golang
+prep := &pb.Prepare{
+    view: 1,
+    SequenceNumber: 2,
+    BatchDigest: "aaaaa",
+    ReplicaId: 11,    
+}
+
+out, err := proto.Marshal(prep)
+
+if err != nil {
+    fmt.Printf("Error marshalling prepare: %s", err) 
+    return 
+}
+
+if err := ioutil.WriteFile(fname, out, 0644); err != nil {
+    fmt.Printf("Error writing file: %s", err) 
+    return    
+}
+```
+
+## 使用protobuf提供的API对消息进行读操作
+  
+  对编码过的数据调用 `proto.Unmarshal` 就可以进行反序列化操作得到原来的信息。
+
+```golang
+in, err := ioutil.ReadFile(fname)
+
+if err != nil {
+    fmt.Printf("Error reading file: %s", err) 
+    return    
+}
+
+prep := &pb.Prepare{}
+
+if err := proto.Unmarshal(in, prep); err != nil {
+    fmt.Printf("Error unmarshalling prepare: %s", err)
+    return
+}
+```
+
+  当然了，上面两个例子是将序列化的数据存储到文件中，同样的，我们可以将序列化后的数据直接在网上传播，因为序列化后的数据已经是 `wire format` 了。
diff --git a/PubSub.md b/PubSub.md
new file mode 100644
index 0000000..0e01e5e
--- /dev/null
+++ b/PubSub.md
@@ -0,0 +1,114 @@
+# PubSub
+  消息的发布和订阅这种设计模式在大型开源项目中还是会经常被使用到的，它的要点是一堆消息订阅者（ `Subscriber` ）会订阅某个自己感兴趣的 `topic` ，一
+旦发布者（ `Publisher` ）向这个 `topic` 发布消息，消息的订阅者就能收到该消息。
+
+  这种设计模式的灵感其实就来自于现实生活之中，我们（ `Subscriber` ）向我们感兴趣的杂志社订阅想要阅读的月刊，那么我们订阅的消息（算一个
+`subscription` ）就会被杂志社（ `Publisher` ）记录下来，一旦杂志可以上市发行了，杂志社就会主动向我们推送（ `Publish` ）杂志消息。
+
+![PubSub](https://docs.oracle.com/cd/E19575-01/819-3669/images/jms-publishSubscribe.gif)
+
+  下面我们来实现一个简单的发布者订阅者模型吧。
+
+  由于这个模型的核心就在于很多 `subscriber` 会向某一个 `topic` 订阅消息，所以需要一个结构体来记录特定的 `topic` 对应的所有 `subscriber` ，这
+里 `subscriber` 用一个集合（ `Set` ）来表示。
+
+```golang
+type PubSub struct {
+    sync.RWMutex
+    subscriptions map[string]*Set
+}
+
+type Set struct {
+    items map[interface{}]struct{}
+    lock *sync.RWMutex
+}
+
+func NewPubSub() *PubSub {
+    return &PubSub{
+        subscriptions: make(map[string]*Set),
+    }
+}
+```
+
+  `Subscription` 应该具有监听行为，通过 `Listen` 来获取 `Publisher` 发布的消息。而结构体 `subscription` 则相当于一个订阅的注册信息。
+
+```golang
+type Subscription interface {
+    Listen() (interface{}, error)
+}
+
+type subscription struct {
+    topic string
+    ttl   time.Duration
+    c     chan interface{}    
+}
+
+type (s *subscription) Listen() (interface{}, error) {
+    select {
+    case <-time.After(s.ttl):
+        return nil, errors.New("timed out")
+    case iterm := <-s.c:
+        return item, nil
+    }
+}
+```
+
+  其实订阅和取消订阅的本质就是将自己从订阅名单（ `subscriptions map[string]*Set` ）里面进行增加或删除的操作，因为我们向杂志社订阅了某本杂志，那
+么关于我们的订阅信息一定会在杂志出版商那里存在。
+
+```golang
+func (ps *PubSub) Subscribe(topic string, ttl time.Duration) Subscription {
+    sub := &subscription{
+        topic: topic.
+        ttl:   ttl,
+        c:     make(chan interface{}, subscriptionBuffSize),
+    }
+    ps.Lock()
+    s, exists := ps.subscriptions[topic]
+    if !exists {
+        s = NewSet()
+        ps.subscriptions[topic] = s
+    }
+    ps.Unlock()
+
+    s.Add(sub)
+    time.AfterFunc(ttl, func() {
+        ps.unSubscribe(sub)
+    })
+    return
+}
+
+func (ps *PubSub) unSubscribe(sub *subscription) {
+    ps.Lock()
+    defer ps.Unlock()
+    ps.subscriptions[sub.topic].Remove(sub)
+    if ps.subscriptions[sub.topic].Size() != 0 {
+        return
+    }
+    delete(ps.subscriptions, sub.topic)
+}
+```
+
+  最后我们订阅的杂志终于要发布了，杂志的出版社会根据自己手中的订阅名单，逐一向订阅该 `topic` 的订阅者发送杂志，当然只有订阅了的人才能收到。但是由于
+订阅者可能出去旅游了，也就是说他最近并没有调用 `Listen` 将收到的订阅消息拿出，而我们接受订阅消息的邮箱大小是有上限的（ `c: make(chan interface
+{}, subscriptionBuffSize)` ，我们设置了 `subscriptionBuffSize` 来表示一个通道中最多可以存放的消息数量），如果该邮箱内已有的消息超出这个限制，
+则选择不将消息放入邮箱中，否则则将消息放入这个邮箱中。
+
+```golang
+func (ps *PubSub) Publish(topic string, item interface{}) error {
+    ps.RLock()
+    defer ps.RUnlock()
+    s, subscribed := ps.subscriptions[topic]
+    if !subscribed {
+        return errors.New("no subscribers")
+    }
+    for _, sub := range s.ToArray() {
+        c := sub.(*subscription).c
+        if len(c) == subscriptionBuffSize {
+            continue
+        }
+        c <- item
+    }
+    return nil
+}
+```
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..82b141e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,2 @@
+# oceanoverflow.github.io
+Pieces of valuable programming knowledges
diff --git a/Screenshot.md b/Screenshot.md
new file mode 100644
index 0000000..360b60d
--- /dev/null
+++ b/Screenshot.md
@@ -0,0 +1,120 @@
+# 使用Golang获取手机屏幕截图
+
+  在今年年前的时候，像冲顶大会，芝士超人这样的答题赚钱类应用异常火爆，当然了，聪明的程序猿们也不是吃素的，为了提高答对题目的概率，就写了一些程序（脚本
+）来自动化答题过程，整个作弊的思路并不难，关键点就在于获取手机的当前截屏，然后通过文字识别来获取题目的信息，最后再调用浏览器搜索答案，在浏览器中出现最
+多的那个基本就可以锁定是答案了（当然还有其他的作弊方法，这里不一一列举），这种作弊方法在初期真是屡试不爽，所以今天就让我们来看一下整个作弊流程的关键环
+节——自动获取手机截屏的代码实现吧。
+
+  因为手机分为 `Android` 阵营和 `iOS` 阵营，而且两者实现截屏的方法也稍有不同，所以我们先定义一个 `Screenshot` interface对两种平台进行抽象，之
+后会分别定义 `iOS` 和 `Android` 这两个结构体来实现这个接口（有没有慢慢开始体会到 `interface` 的好处呢），下面的代码中我们也利用了工厂模式来返回 
+`Screenshot` 实例。
+
+```golang
+type Screenshot interface {
+    GetImage() (image.Image. error)
+}
+
+func NewScreenshot(cfg *Config) Screenshot {
+    if cfg.Device == "iOS" {
+        return NewIOS(cfg)
+    }
+    return NewAndroid(cfg)
+}
+
+type Config {
+    Device     string
+    WdaAddress string
+    .....
+}
+```
+
+## Android 实现
+ 
+  我们先定义个 `Android` 结构体，这个结构体实现了 `GetImage` 方法，所以可以在上面的工厂方法中作为 `Screenshot` 接口返回。而在真正运行我们的代码
+之前，我们需要确保安卓机已经正确地连接至电脑，并且要确保电脑上已经安装过 `adb` 这个命令行工具。这里实现截屏主要靠调用 `adb` 的 `screencap` 和
+`pull` 这两个子命令，`screencap` 对当前手机进行截屏并保存到手机本地，`pull` 命令将手机上的截图传到电脑本地（然后就可以接着一通骚操作了），我们通
+过 `exec.Command` 接口对 `adb` 进行调用，整体思路比较清晰，难点应该就在我们不熟悉 `adb` 命令的使用。
+
+```golang
+type Android struct {}
+
+func NewAndroid(cfg *Config) *Android {
+    return new(Android)
+}
+
+func (android *Android) GetImage() (img image.Image, err error) {
+    err := exec.Command("adb", "shell", "screencap", "-p". "/sdcard/screenshot.png").Run()
+    if err != nil {
+        return
+    }
+    dstImagePath := "/Desktop" + "origin.png"
+    err = exec.Command("adb", "pull", "/sdcard/screenshot.png", dstImgPath).Run()
+    if err != nil {
+        return
+    }
+    f, err := os.Open(dstImagePath)
+    if err != nil {
+        return nil, err
+    }
+    defer f.Close()
+    return png.Decode(f)
+}
+```
+
+## iOS 实现
+
+  依葫芦画瓢，同样定义一个 `IOS` 结构体，来实现 `GetImage` 方法，在具体截屏的实现中，由于 `iOS` 系统的封闭性，所以自然没有像 `Android` 的
+`adb` 那样的命令行调试工具，不过也不是说啥事也做不了，在 `iOS` 中，我们可以向特定接口地址 `wdaAddress` 发送 `http` 的`GET` 请求，然后通过解析
+返回的 `json` 数据，这个 `json` 数据中就编码了我们的图片信息，然后再利用 `base64` 进行解码获得一个字节数组，再对该字节数组进行 `png` 解码，最终
+就可以获得我们想要的 `image` 了。
+
+```golang
+type IOS struct {
+    wdaAddress string
+}
+
+type screenshotRes {
+    Value     string `json:"value"`
+    SessionID string `json:"sessionId"`
+    Status    int    `json:"status"`
+}
+
+func NewIOS(cfg *Config) *IOS {
+    ios := new(IOS)
+    ios.wdaAddress = cfg.WdaAddress
+    if ios.wdaAddress == "" {
+        panic("Please specify the wda address")
+    }
+    return ios
+}
+
+func (ios *IOS) GetImage() (img image.Image, err error) {
+    body, err := util.HTTPGet(ios.wdaAddress)
+    if err != nil {
+         return
+    }
+    res := new(screenshotRes)
+    err = json.Unmarshal(body, res)
+    if err != nil {
+        return
+    }
+    pngValue, err := base64.stdEncoding.DecodeString(res.Value)
+    if err != nil {
+        return
+    }
+    src, err := png.Decode(bytes.NewReader(pngValue))
+    if err != nil {
+        return
+    }
+    img = src
+    return
+}
+```
+
+## 总结
+  
+  在本篇博客中，我们看到了工厂模式在具体程序设计中的应用，灵活使用工厂模式可以提供我们工程代码的水平，也见识到了如何利用 `adb` 工具对 `Android` 机
+器进行调试，当然了 `adb` 的功能不仅仅局限于上述两点，它还可以干非常多的事情，有兴趣的小伙伴可以自己研究一下，最后还有就是因为 `iOS` 系统本身的封闭性
+，我们只能通过调用web接口来获取其截图信息。
+
+  最后，作为程序员圈子里的一员，在日常生活中还是要多思考，啥东西要是可以用代码实现自动化，就马上动手去实现它吧。
diff --git a/SmoothWeightedRoundRobin.md b/SmoothWeightedRoundRobin.md
new file mode 100644
index 0000000..a8d7ba8
--- /dev/null
+++ b/SmoothWeightedRoundRobin.md
@@ -0,0 +1,135 @@
+# Smooth Weighted Round Robin
+
+  我们在之前的文章中就讲过负载均衡，但是那篇文章中的例子比较简单，仅仅是利用随机算法来进行负载均衡，并没有考虑服务器的实际情况，在很多情况下，服务器的性
+能可能存在显著差异，这时候如果采用随机算法，那么性能较差的服务器会承受过多的压力，而性能较好的服务器则大部分时间处于空闲状态，系统整体的吞吐量就无法上来。
+
+  例如服务器的性能比例如下：`{a:3, b: 2, c:1}` ，一般来说可以使用加权的轮询算法（ `Weighted Round Robin` ）进行负载均衡，但是普通的加权轮询会得
+出类似这样的序列， `a a a b b c` ，这样的序列有一个问题，就是它并不够平滑，我们更希望得到像这样的序列 `a b a c b a` 。也就是说一般的轮询调度在调度
+的过程中并没有考虑瞬时的情况，所以会导致对某一台服务器的瞬时访问。
+
+  下面我们就来介绍一下平滑版本的加权轮询算法，来解决上述瞬时访问可能出现的问题。我们对每个节点赋予两个权重， `Weight` ，这是一个较为固定的值，就是前面
+给出的 `{a:3, b: 2, c:1}` ，还需要一个 `CurrentWeight` 来记录当前的权重，初始时均为0，这个权重是在每次选择节点时动态变化的。
+
+  例如现在有三台服务器，其权重比值为 `{a:3, b: 2, c:1}` ，刚开始时它们的 `CurrentWeight` 均为0，按照下面的算法，每一回合中各个节点的
+`CurrentWeight` 都会加上它相应的的 `Weight` ，`total` 变量则用于记录每一个节点增加的 `Weight` 的总和，并记录当前权重最高的那一个节点，也就是我们的 `best` ，在一轮计算之后，再让 `best` 节点的 `CurrentWeight` 减去 `total` 值。
+
+  也就是说开始时每台服务器的 `CurrentWeight` 为 `{a:0, b: 0, c:0}` ，在选择节点的过程中，每个节点均会加上自己对应的 `Weight` ，这样就变成
+`{a:3, b: 2, c:1}` ， 此时 `best=a` ， 最后 a 对应的 `CurrentWeight` 要减去 `total` ，也就是 `{a:-3, b: 2, c:1}`  。
+
+  然后 `{a:-3, b: 2, c:1}` 作为下一轮挑选节点时的初始状态，以此类推，最后可以得到下面这样的序列  `a b a c b a` ，这样就不会导致对服务器 `a` 集中
+访问的情况，也就是说访问序列更加平滑了。
+
+  整个周期计算的流程如下所示。
+
+```
+a   b   c
+0   0   0
+
+3   2   1   Next() : a
+-3  2   1
+
+0   4   2   Next() : b
+0  -2   2
+
+3   0   3   Next() : a
+-3  0   3
+
+0   2   4   Next() : c
+0   2   -2 
+
+3   4   -1  Next() : b
+3  -2   -1
+
+6   0   0   Next() : a
+0   0   0
+
+```
+
+## 普通版本平滑轮询调度算法
+
+```golang
+type Weighted struct {
+    Server string
+    Weight int
+    CurrentWeight int
+}
+```
+
+  普通版本的算法，每次选择结点的时候，我们为每个候选结点的 `CurrentWeight` 增加 `Weight` ，选取 `CurrentWeight` 最大的节点作为我们最后返回的结果
+，然后将该节点减去所有节点增加的 `Weight` 之和。 
+
+```golang
+func Next(servers []*Weighted) (best *Weight) {
+    total := 0 
+    for i := 0; i < len(servers); i++ {
+        w := servers[i]
+        
+        if w == nil {
+            continue
+        }
+
+        w.CurrentWeight += w.Weight
+        total += w.CurrentWeight 
+        if best == nil || w.CurrentWeight > best.CurrentWeight {
+            best = w
+        }
+    }
+    if best == nil {
+        return nil
+    }
+    best.CurrentWeight -= total
+    return best
+} 
+```
+
+## 考虑节点失效情况时的算法
+
+  上面那种算法不能很好的应对节点失效的情况，为了解决节点失效时的这种突发情况，我们多引入一个权重也就是 `EffectiveWeight` ，该权重初始时与 `Weight`
+的值相同，例如上述的例子中都是  `{a:3, b: 2, c:1}` ，但是 `EffectiveWeight` 会在节点失败的时候清0，当节点恢复正常时再慢慢递增直到达到原本的
+`Weight` ，这样就能很好地考虑了节点失效再重启时的真实情况。因为引入了 `EffectiveWeight` ， 我们在相应计算的时候就不直接采用 `Weight` 而是直接使用
+`EffectiveWeight` 来代替计算。 
+
+```golang
+type Weighted struct {
+    Server string
+    Weight int
+    CurrentWeight int
+    EffectiveWeight int
+}
+```
+
+```golang
+func (w *Weighted) fail() {
+    w.EffetiveWeight -= w.Weight
+    if w.EffectiveWeight < 0 {
+        w.EffectiveWeight = 0
+    }
+}
+```
+
+```golang
+func Next(servers []*Weighted) (best *Weight) {
+    total := 0
+    for i := 0; i < len(servers); i++ {
+        w := servers[i]
+
+        if w == nil {
+            continue
+        }
+
+        w.CurrentWeight += w.EffectiveWeight
+        total += w.EffectiveWeight
+        if w.EffectiveWeight < w.Weight {
+            w.EffectiveWeight++
+        }
+        if best == nil || w.CurrentWeight > best.CurrentWeight {
+            best = w
+        }
+    }
+    if best == nil {
+        return nil
+    }
+    best.CurrentWeight -= total
+    return best
+}
+```
diff --git a/TCP_IP.md b/TCP_IP.md
new file mode 100644
index 0000000..c03c5d6
--- /dev/null
+++ b/TCP_IP.md
@@ -0,0 +1,138 @@
+# TCP/IP
+  网络是分布式系统之间通信的媒介，掌握网络编程自然变成了程序猿们居家旅行必备技能之一了，与直接使用应用层的 `http` 协议不同，我们一般使用传输层的协议
+例如 `tcp` 进行编程，掌握好了 `tcp` 编程，我们甚至能写一套类似`http` 这样的应用层协议，是不是很兴奋呢，那今天就让我们从最简单的例子出发，掌握 
+`tcp/ip` 编程的精髓吧。
+
+  一般来说大部分网络通信模型是 `c/s` 模型，也有部分是 `p2p` 模型，今天我们先了解一下 `c/s` 模型的编程使用吧。
+
+  客户端要想与服务器通信，前提必须是服务器已经启动并且监听了某个端口了。如果服务器没有监听而客户端直接连接的话，就会报类似下面这样的错误：
+
+  `dial tcp 127.0.0.1:8080: connect: connection refused`
+ 
+  也就是说，服务器端要调用 `net.Listen` 接口对特定端口进行监听，监听会返回一个 `Listener` ，服务器一旦监听到来自客户端的请求，就会调用 `Accept`
+来接受该请求，`Accept` 会返回一个 `net.Conn` ，以后服务器就可以使用 `net.Conn` 与客户端进行通信。
+
+```golang
+type Listener interface {
+    Accept() (Conn, error)
+    Close() error
+    Addr() Addr
+}
+
+type Conn interface {
+    Read(b []byte) (n int, err error)
+    Write(b []byte) (n int, err error)
+    Close() error
+    LocalAddr() Addr
+    RemoteAddr() Addr
+    SetDeadline(t time.Time) error
+    SetReadDeadline(t time.Time) error
+    SetWriteDeadline(t time.Time) error
+}
+```
+
+## server.go
+
+  一般来说，服务器需要处理来自多个客户端的请求，所以我们使用goroutine来处理不同客户端的请求，这样就达到一个并发的目的。
+
+  服务器处理客户端请求的主要的流程如下：
+  `Listen => Accept => Read & Write => Close` 。
+
+```golang
+package main 
+
+import (
+    "log"
+    "net"
+    "fmt"
+    "bufio"
+    "strings"
+)
+
+func main() {
+    fmt.Println("Launching server...")
+
+    l, err := net.Listen("tcp", ":8080")
+    if err != nil {
+        log.Fatal(err)
+    }
+    defer l.Close()
+
+    for {
+        conn, err := ln.Accept()
+        if err != nil {
+            log.Fatal(err)
+        }
+        go handleConn(conn)
+    }
+}
+
+func handleConn(c net.Conn) {
+    for {
+        m, _ := bufio.NewReader(c).ReadString('\n')
+        fmt.Print("Message Received:", string(m))
+        newMsg := strings.ToUpper(m)
+        c.Write([]byte(newMsg + "\n"))
+    } 
+}
+```
+
+## client.go
+
+  一般来说连接都是由客户端主动发起的，客户端调用 `net.Dial` 向服务器发起连接行为，在正常情况下，则也返回一个 `net.Conn` ，注意到客户端和服务器都
+是通过 `net.Conn` 进行通信的，linux基础好的同学，就知道它的本质就是一个套接字（socket），而套接字的本质则是一个文件，所以我们可以对待正常文件一样
+去使用它，例如使用 `fmt.Fprintf` 来对套接字写入数据。
+
+  主要的流程如下： 
+  `Dial => Read & Write => Close` 。
+
+```golang
+package main
+
+import (
+    "os"
+    "log"
+    "net"
+    "fmt"
+    "bufio"
+)
+
+func main() {
+    c, e := net.Dial("tcp", "localhost:8080")
+    if e != nil {
+        log.Fatal(e)
+    }
+    reader := bufio.NewReader(os.Stdin)
+    for {
+        fmt.Print("Text to send: ")
+        text, err := reader.ReadString('\n')
+        if err != nil {
+            log.Fatal(err)
+        }
+        fmt.Fprintf(c, text + "\n")
+        m, e := bufio.NewReader(c).ReadString('\n')
+        if e != nil {
+            log.Fatal(e)
+        }
+        fmt.Print("Message from server: " + m)
+    }
+}
+```
+
+## 运行
+  先对两个源文件进行编译。
+```
+$ go build *.go
+```
+
+  在一个命令行中输入：
+
+```
+$ ./server
+```
+
+  在另一个命令行中输入：
+
+```
+$ ./client
+```
diff --git a/TLS.md b/TLS.md
new file mode 100644
index 0000000..fcb98cb
--- /dev/null
+++ b/TLS.md
@@ -0,0 +1,169 @@
+# TLS
+
+  在之前的博客中涉及到的 `TCP` 网络编程都是非常不安全的，因为它将我们的数据直接以明文的形式在公网上面传输，如果有恶意第三方的存在，我们传输的数据就
+可以被捕捉监听甚至修改，从而导致各种各样无法预测的结果，所以，考虑到安全性，我们还是要学一学如果用 `TLS` 进行网络编程，以提高我们的客户端和服务器之
+前传输数据的安全性。
+
+  `TLS` 即 `Transport Layer Security` ，就是为了保证传输层上的数据安全，服务器和客户端会在 `handshake` 阶段协商出只有两者知晓的一个对称密钥
+，然后之后的通信就利用这个对称密钥将数据进行加密后进行传输，很幸运的是，在我们使用 `TLS` 进行网络编程的时候，并不用去关注这些繁杂的细节，因为golang
+的标准库都已经帮我们封装好了（hooray！）。
+
+## 准备工作
+
+  使用 `TLS` 进行网络编程的时候，我们需要在服务器上放一个证书，证书的话可以使用 `openssl` 工具来生成，这里作为例子就先生成一个自签名的证书吧。
+
+  要生成一个证书，第一步当然就是生成一个私钥了，这里我们指定使用 `RSA` 算法生成一个 `2048bit` 的私钥。
+
+`$ openssl genrsa -out server.key 2048`
+ 
+  计算私钥是比较耗时的一个过程，无论多好的电脑，都需要在毫秒级别才能生成一个RSA私钥，这里输出的 `server.key` 就是我们要的私钥，生成的私钥是经过
+`pem` 格式编码的，也就是类似如下的格式：
+
+```
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA1DYBcVnQFyFEW9AhHY+6+Shp7LIT5ZtjbFfu2ZQgg3aTsXVF..........
+-----END RSA PRIVATE KEY-----
+```
+
+  当拥有了私钥之后，为了得到对应的证书，我们还需要有一个 `Certificate Signing Request` ，简称为 `CSR` ，也就是证书签名请求。
+
+`$ openssl req -new -sha256 -key server.key -out server.csr`
+
+  这个命令会要求你输入相关的信息，填入相关信息后就会得到一个 `server.csr` 文件，这个文件也是用`pem` 格式编码的，类似如下：
+
+```
+-----BEGIN CERTIFICATE REQUEST-----
+MIIC0jCCAboCAQAwbjELMAkGA1UEBhMCQ04xETAPBgNVBAcMCEhhbmd6aG91MQww..........
+-----END CERTIFICATE REQUEST-----
+```
+
+  最后一步就是利用上面步骤中得到的私钥和证书签名请求来最终获得一个自签名的证书。
+
+`$ openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt`
+
+  最终获得的证书 `server.crt` 也是 `pem` 格式编码的，类似如下：
+
+```
+-----BEGIN CERTIFICATE-----
+MIIDWDCCAkACCQCFvy51fQRGMTANBgkqhkiG9w0BAQUFADBuMQswCQYDVQQGEwJD..........
+-----END CERTIFICATE-----
+```
+
+  利用下面的命令我们可以查看我们刚刚生成的符合 `x509` 标准的证书的具体信息，里面包含了两个比较重要的信息就是公钥（public key）和签名
+（signature）。
+
+`$ openssl x509 -in server.crt -noout -text`
+
+  上面这么多命令必须按顺序执行，也就是说第一步生成私钥，第二步生成证书签名请求，最后才能生成我们的证书。
+
+## TLS server
+
+  在 `TLS` 编程中，服务器端需要得到私钥和证书的信息。我们使用 `tls.LoadX509KeyPair` 来获得我们之前生成证书和私钥信息，然后在监听时作为
+参数导入。
+
+```golang
+package main
+
+import (
+    "crypto/tls"
+    "net"
+    "log"
+    "bufio"
+    "fmt"
+)
+
+func main() {
+    cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
+    if err != nil {
+        log.Println(err)
+        return
+    }
+
+    config := &tls.Config{Certificates: []tls.Certificate{cert}}
+    listener, err := tls.Listen("tcp", ":443", config)
+    if err != nil {
+        log.Println(err)
+        return
+    }
+    defer listener.Close()
+    
+    for {
+        conn, err := listener.Accept()
+        if err != nil {
+            log.Println(err)
+            continue
+        }
+        go handleConnection(conn)
+    }
+}
+
+func handleConnection(conn net.Conn) {
+    defer conn.Close()
+    r := bufio.NewReader(conn)
+    for {
+        msg, err := r.ReadString('\n')
+        if err != nil {
+            log.Println(err)
+            return
+        }
+        
+        fmt.Println(msg)
+
+        n, err := conn.Write([]byte("world\n"))
+        if err != nil {
+            log.Println(n, err)
+            return
+        }
+    }
+}
+```
+
+## TLS client
+
+  与一般的TCP网络编程类似，作为客户端我们调用 `tls.Dial` 而非 `net.Dial` 来与服务器建立连接，但与 `net.Dial` 不同的是，我们还需要多传递一个
+`tls.Config` 参数，来指定 `TLS` 连接时的各种参数。
+
+```golang
+package main
+
+import (
+    "fmt"
+    "log"
+    "crypto/tls"
+)
+
+func main() {
+    conf := &tls.Config{
+        InsecureSkipVerify: true,
+    }
+
+    conn, err := tls.Dial("tcp", "127.0.0.1:443", conf)
+    if err != nil {
+        log.Println(err)
+        return
+    }
+    defer conn.Close()
+
+    n, err := conn.Write([]byte("hello\n"))
+    if err != nil {
+        log.Println(err)
+        return
+    }
+
+    buf := make([]byte, 100)
+    n , err := conn.Read(buf)
+    if err != nil {
+        log.Println(n, err)
+        return
+    }
+
+    fmt.Println(string(buf[:n]))
+}
+```
+
+## 抓取tcp包进行验证
+
+`$ tcpdump host 127.0.0.1 port 433`
+
+  当我们这时候使用类似 `tcpdump` 这样的抓包工具进行网络抓包时，我们不再能看到明文了，看到的只能是一堆乱七八糟的东西，因为客户端和服务器已经将数据
+经过加密处理了。
diff --git a/WebSocket.md b/WebSocket.md
new file mode 100644
index 0000000..0a03ce6
--- /dev/null
+++ b/WebSocket.md
@@ -0,0 +1,148 @@
+# WebSocket
+
+  如果服务器会定期地更新消息，但是具体的时间间隔并不确定，客户端为了能够及时拿取最新的消息，就得不断的发送 `HTTP` 请求来轮询服务器，也就是说为了能够
+及时获取最新资讯，由于 `HTTP` 本身的特点，服务请求的发起方只能是客户端，服务器本身并没有消息推送的功能，这样就导致了资源浪费的问题，很多客户端发送的
+请求都是无效的，当客户端和服务器一对一交流时倒还好，如果很多客户端向服务器以这样的形式咨询，服务器将会承受非常大的压力了。
+
+  所以，为了避免资源浪费，我们来引入 `WebSocket` 解决上述问题，`WebSocket` 可以说是 `HTTP` 协议的一个升级，它同样基于 `TCP` 之上，但与传输层的
+`socket` 不同，它的 `socket` 是应用层的概念。要想使用 `WebSocket` ，客户端和服务器必须同时支持才可以使用。
+
+  `WebSocket` 中比较重要的一个阶段就是握手阶段了，如下图所示，客户端向服务器发送一个协议升级的 `HTTP` 请求，并且附带上一些其他的元信息用于握手。
+
+![WebSocket](http://www.cuelogic.com/blog/wp-content/uploads/2013/11/websocketlifecycle_30624_l.png)
+
+```
+Request headers from client
+
+GET /mychat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
+Sec-WebSocket-Protocol: chat
+Sec-WebSocket-Version: 13
+Origin: http://example.com
+```
+
+  服务器收到该协议升级的 `HTTP` 请求后，会返回一个 `HTTP` 答复，向客户端确认同意建立 `WebSocket` 连接，从此之后，它们之间就不再用 `HTTP` 的形式
+交流了，而是直接改用 `WebSocket` 格式的报文进行交流，服务器也具备了相应推送消息的能力了。
+
+```
+Response headers from server
+
+HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
+Sec-WebSocket-Protocol: chat
+```
+
+  下面我们来看一下使用 `"github.com/gorilla/websocket"` 时各个步骤对应的代码吧。
+
+  客户端代码的风格和使用 `TCP` 进行编程非常类似，第一步，客户端向服务器发送协议升级请求，对应
+`websocket.DefaultDialer.Dial(u.string(), nil)` 。
+
+```golang
+var addr = flag.String("addr", "localhost:8080", "http service addr")
+u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}
+log.Printf("connecting to %s", u.String())
+
+c, _, err := websocket.DefaultDialer.Dial(u.string(), nil)
+if err != nil {
+    log.Fatal("dial:", err)
+} 
+defer c.Close()
+```
+
+  在服务端处理 `WebSocket` 请求与处理 `HTTP` 请求类似，我们同样需要定义一个 `handler` ，但与普通处理 `HTTP` 请求不同的是，此 `handler` 会对
+协议进行升级，也就是 `upgrader.Upgrade(w, r, nil)` ，这段代码相当于服务端向客户端发送一个协议升级的确认消息。在这之后，服务器就可以一直读取客户
+端发来的请求和向客户端返回答复了（代码的逻辑在 `for` 循环之中），也就是说服务器只起了一个 `handler` 来处理这段 `session` 。
+
+```golang
+func echo(w http.ResponseWriter, r *http.Request) {
+    c, err := upgrader.Upgrade(w, r, nil)
+    if err != nil {
+        log.Print("upgrade:", err)
+        return
+    }
+    defer c.Close()
+    for {
+        mt, message, err := c.ReadMessage()
+        if err != nil {
+            log.Println("read:", err)
+            break
+        }
+        log.Printf("recv: %s", message)
+        err = c.WriteMessage(mt, message)
+        if err != nil {
+            log.Println("write:", err)
+            break
+        }
+    }
+}
+
+func main() {
+    http.HandleFunc("echo", echo)
+    log.Fatal(http.ListenAndServe(*addr, nil))
+}
+```
+
+  客户端在握手之后就可以读取和发送数据，在这里，由于在 `WebSocket` 中服务器可以主动向客户端推送数据，所以我们起一个 `goroutine` 专门用于接受服务
+器主动推送的数据（ `c.ReadMessage()` ）。
+
+```golang
+done := make(chan struct{})
+
+go func() {
+    defer close(done)
+    for {
+        _, message, err := c.ReadMessage()
+        if err != nil {
+            log.Println("read:", err)
+            return
+        }
+        log.Printf("recv:", message)
+    }
+}
+```
+
+  下面是客户端发送数据的逻辑，这里我们每隔一秒钟向服务器发送当前的时间，`c.WriteMessage(websocket.TextMessage, []byte(t.string()))` ，这里
+我们注意到，`WebSocket` 中的消息是有类型的，这个函数的第一个参数就是指明该消息的类型，这里我们使用 `websocket.TextMessage` 。
+
+  那么如何让这段 `session` 结束呢，结束会话一般来说都是客户端主动发起的，客户端主要发送一个结束对话的消息类型就可以了，
+`c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))` ，这里注意该结束对话的消
+息类型为 `websocket.CloseMessage` 。
+ 
+```golang
+ticker := time.NewTicker(time.Second)
+defer ticker.Stop()
+
+interrupt := make(chan os.Signal, 1)
+signal.Notify(interrupt, os.Interrupt)
+
+for {
+    select {
+    case <-done:
+        return
+    case t := <-ticker.C:
+        err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
+        if err != nil {
+            log.Println("write:", err)
+            return
+        }
+    case <-interrupt:
+        log.Println("interrupt")
+        
+        err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+        if err != nil {
+            log.Println("write close:", err)
+            return
+        }
+        select {
+        case <-done:
+        case <-time.After(time.Second)
+        }
+        return
+    }
+}
+```
diff --git a/ZeroKnowledgeProof.md b/ZeroKnowledgeProof.md
new file mode 100644
index 0000000..e69de29
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 0000000..c419263
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-cayman
\ No newline at end of file
diff --git a/archives/2017/09/index.html b/archives/2017/09/index.html
deleted file mode 100644
index 2962e8d..0000000
--- a/archives/2017/09/index.html
+++ /dev/null
@@ -1,252 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2017/9 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2017/09/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/02/LinuxManiac/">
-		<h3 class="post-title">Linux Maniac</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-02T13:24:46.000Z" itemprop="datePublished">
-	      92.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/01/TODO/">
-		<h3 class="post-title">TODO</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-01T13:20:48.000Z" itemprop="datePublished">
-	      91.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2017/12/index.html b/archives/2017/12/index.html
deleted file mode 100644
index bb624a4..0000000
--- a/archives/2017/12/index.html
+++ /dev/null
@@ -1,240 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2017/12 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2017/12/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/12/07/openssl/">
-		<h3 class="post-title">openssl</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-12-07T05:17:05.000Z" itemprop="datePublished">
-	      127.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2017/index.html b/archives/2017/index.html
deleted file mode 100644
index f804efa..0000000
--- a/archives/2017/index.html
+++ /dev/null
@@ -1,264 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2017 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2017/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/12/07/openssl/">
-		<h3 class="post-title">openssl</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-12-07T05:17:05.000Z" itemprop="datePublished">
-	      127.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/02/LinuxManiac/">
-		<h3 class="post-title">Linux Maniac</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-02T13:24:46.000Z" itemprop="datePublished">
-	      92.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/01/TODO/">
-		<h3 class="post-title">TODO</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-01T13:20:48.000Z" itemprop="datePublished">
-	      91.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/02/index.html b/archives/2018/02/index.html
deleted file mode 100644
index a1fe2d3..0000000
--- a/archives/2018/02/index.html
+++ /dev/null
@@ -1,240 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/2 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/02/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/02/05/CryptoBasic/">
-		<h3 class="post-title">Cryptography Basics</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-02-05T14:39:55.000Z" itemprop="datePublished">
-	      25.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/04/index.html b/archives/2018/04/index.html
deleted file mode 100644
index 1c67d17..0000000
--- a/archives/2018/04/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/4 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/04/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/ConsistentHashing/">
-		<h3 class="post-title">Connection Hashing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T10:59:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/Crontab/">
-		<h3 class="post-title">crontab</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T05:58:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/TCP_IP/">
-		<h3 class="post-title">TCP/IP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-29T11:56:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/BloomFilter/">
-		<h3 class="post-title">Bloom Filter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-28T16:00:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/EventTimer/">
-		<h3 class="post-title">Event Timer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T06:47:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/MerkleTree/">
-		<h3 class="post-title">Merkle Tree</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T04:18:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/FactoryPattern/">
-		<h3 class="post-title">Factory Pattern</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T15:27:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/LeakyBuffer/">
-		<h3 class="post-title">Leaky Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T06:21:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/EventProcessEngine/">
-		<h3 class="post-title">Event Process Engine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T01:43:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Fanin/">
-		<h3 class="post-title">Fan-in</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T12:35:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <span class="page-number current">1</span><a class="page-number" href="/archives/2018/04/page/2/">2</a><a class="extend next" rel="next" href="/archives/2018/04/page/2/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/04/page/2/index.html b/archives/2018/04/page/2/index.html
deleted file mode 100644
index 3aa8f43..0000000
--- a/archives/2018/04/page/2/index.html
+++ /dev/null
@@ -1,304 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/4 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/04/page/2/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/gRPC/">
-		<h3 class="post-title">gRPC</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:27:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Protobuf/">
-		<h3 class="post-title">Protocol Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:03:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/FSM/">
-		<h3 class="post-title">Finite State Machine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T01:58:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/24/PKCS7_Padding/">
-		<h3 class="post-title">PKCS7 Padding</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-24T08:26:24.000Z" itemprop="datePublished">
-	      424.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/23/RSS/">
-		<h3 class="post-title">RSS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-23T13:50:37.000Z" itemprop="datePublished">
-	      423.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/22/heap/">
-		<h3 class="post-title">heap</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-22T09:44:48.000Z" itemprop="datePublished">
-	      422.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/04/">Prev</a><a class="page-number" href="/archives/2018/04/">1</a><span class="page-number current">2</span>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/05/index.html b/archives/2018/05/index.html
deleted file mode 100644
index 075f83f..0000000
--- a/archives/2018/05/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/5 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/05/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/31/MemoryMappedFile/">
-		<h3 class="post-title">Memory Mapped File</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-31T11:05:38.000Z" itemprop="datePublished">
-	      531.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/29/ProtocolMultiplexer/">
-		<h3 class="post-title">Protocol Multiplexer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-29T11:50:23.000Z" itemprop="datePublished">
-	      529.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/28/Shredder-Gluer/">
-		<h3 class="post-title">Shredder &amp; Gluer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-28T03:38:22.000Z" itemprop="datePublished">
-	      528.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/27/TUNTAP/">
-		<h3 class="post-title">TUN/TAP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-27T06:05:03.000Z" itemprop="datePublished">
-	      527.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/26/TryLock/">
-		<h3 class="post-title">Try Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-26T14:05:27.000Z" itemprop="datePublished">
-	      526.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/25/ConcurrentPrimeSieve/">
-		<h3 class="post-title">Concurrent Prime Sieve</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-25T06:36:04.000Z" itemprop="datePublished">
-	      525.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/SingleFlight/">
-		<h3 class="post-title">Single Flight</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-24T05:46:36.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/LRU/">
-		<h3 class="post-title">LRU</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T16:23:40.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/23/Heartbeat/">
-		<h3 class="post-title">Heartbeat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T09:52:18.000Z" itemprop="datePublished">
-	      523.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/BitwiseOperation/">
-		<h3 class="post-title">Bitwise Operation</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T11:28:38.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <span class="page-number current">1</span><a class="page-number" href="/archives/2018/05/page/2/">2</a><a class="page-number" href="/archives/2018/05/page/3/">3</a><a class="page-number" href="/archives/2018/05/page/4/">4</a><a class="extend next" rel="next" href="/archives/2018/05/page/2/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/05/page/2/index.html b/archives/2018/05/page/2/index.html
deleted file mode 100644
index c91069e..0000000
--- a/archives/2018/05/page/2/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/5 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/05/page/2/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/GUID/">
-		<h3 class="post-title">GUID</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T03:49:08.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/21/mpg123/">
-		<h3 class="post-title">mpg123</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-21T11:12:06.000Z" itemprop="datePublished">
-	      521.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/20/Future/">
-		<h3 class="post-title">Future</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-20T06:04:59.000Z" itemprop="datePublished">
-	      520.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/19/ADB/">
-		<h3 class="post-title">ADB</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-19T07:38:54.000Z" itemprop="datePublished">
-	      519.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/15/ConnectionLimiter/">
-		<h3 class="post-title">Connection Limiter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-15T02:18:24.000Z" itemprop="datePublished">
-	      515.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/14/TerminalUI/">
-		<h3 class="post-title">Terminal UI</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-14T14:49:04.000Z" itemprop="datePublished">
-	      514.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/13/JobDispatcher/">
-		<h3 class="post-title">Job Dispatcher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-13T13:34:24.000Z" itemprop="datePublished">
-	      513.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/ReverseProxy/">
-		<h3 class="post-title">Reverse Proxy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T13:30:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/AdvisoryLock/">
-		<h3 class="post-title">Advisory Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T05:26:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/TokenBucket/">
-		<h3 class="post-title">Token Bucket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T14:05:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/05/">Prev</a><a class="page-number" href="/archives/2018/05/">1</a><span class="page-number current">2</span><a class="page-number" href="/archives/2018/05/page/3/">3</a><a class="page-number" href="/archives/2018/05/page/4/">4</a><a class="extend next" rel="next" href="/archives/2018/05/page/3/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/05/page/3/index.html b/archives/2018/05/page/3/index.html
deleted file mode 100644
index 1b0bc6d..0000000
--- a/archives/2018/05/page/3/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/5 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/05/page/3/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/StreamCipher/">
-		<h3 class="post-title">Stream Cipher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T05:10:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/10/ConnectionPool/">
-		<h3 class="post-title">Connection Pool</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-10T03:40:24.000Z" itemprop="datePublished">
-	      510.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/MorseCode/">
-		<h3 class="post-title">Morse Code</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T09:07:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/CircuitBreaker/">
-		<h3 class="post-title">Circuit Breaker</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T01:17:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/ColorfulPrinting/">
-		<h3 class="post-title">Colorful Printing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T11:48:24.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/SmoothWeightedRoundRobin/">
-		<h3 class="post-title">Weighted Round Robin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T02:29:04.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/07/MagnetLink/">
-		<h3 class="post-title">Magnet Link</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-07T07:15:24.000Z" itemprop="datePublished">
-	      57.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/06/PubSub/">
-		<h3 class="post-title">PubSub</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-06T11:08:04.000Z" itemprop="datePublished">
-	      56.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/WebSocket/">
-		<h3 class="post-title">WebSocket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:52:04.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/dep/">
-		<h3 class="post-title">dep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:47:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/05/page/2/">Prev</a><a class="page-number" href="/archives/2018/05/">1</a><a class="page-number" href="/archives/2018/05/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/archives/2018/05/page/4/">4</a><a class="extend next" rel="next" href="/archives/2018/05/page/4/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/05/page/4/index.html b/archives/2018/05/page/4/index.html
deleted file mode 100644
index 42df56b..0000000
--- a/archives/2018/05/page/4/index.html
+++ /dev/null
@@ -1,340 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/5 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/05/page/4/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/Crawler/">
-		<h3 class="post-title">Crawler</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:05:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/04/Docker/">
-		<h3 class="post-title">Docker &amp; Golang</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-04T09:01:24.000Z" itemprop="datePublished">
-	      54.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/Screenshot/">
-		<h3 class="post-title">Screenshot</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T12:29:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/LoadBalancing/">
-		<h3 class="post-title">Load Balancing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T10:12:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/DecodingDubboProtocol/">
-		<h3 class="post-title">Dubbo Protocol</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T07:58:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/TLS/">
-		<h3 class="post-title">TLS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T04:40:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/iobridge/">
-		<h3 class="post-title">iobridge</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T13:13:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/etcd/">
-		<h3 class="post-title">etcd</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T04:28:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/Port_0/">
-		<h3 class="post-title">port 0, WTF?</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T03:11:11.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/05/page/3/">Prev</a><a class="page-number" href="/archives/2018/05/">1</a><a class="page-number" href="/archives/2018/05/page/2/">2</a><a class="page-number" href="/archives/2018/05/page/3/">3</a><span class="page-number current">4</span>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/06/index.html b/archives/2018/06/index.html
deleted file mode 100644
index 46e8293..0000000
--- a/archives/2018/06/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/6 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/06/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/27/Graphviz/">
-		<h3 class="post-title">Graphviz</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-27T13:37:09.000Z" itemprop="datePublished">
-	      627.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/26/CGO/">
-		<h3 class="post-title">CGO</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-26T08:34:33.000Z" itemprop="datePublished">
-	      626.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/25/Trie/">
-		<h3 class="post-title">Trie</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-25T14:25:54.000Z" itemprop="datePublished">
-	      625.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/23/PageViews/">
-		<h3 class="post-title">Page Views</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-23T15:08:44.000Z" itemprop="datePublished">
-	      623.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/21/SkipList/">
-		<h3 class="post-title">Skip List</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-21T12:53:24.000Z" itemprop="datePublished">
-	      621.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/20/grep/">
-		<h3 class="post-title">grep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-20T06:07:24.000Z" itemprop="datePublished">
-	      620.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/19/Pipeline/">
-		<h3 class="post-title">Pipeline</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-19T08:39:47.000Z" itemprop="datePublished">
-	      619.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/18/imgcat/">
-		<h3 class="post-title">imgcat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-18T14:02:51.000Z" itemprop="datePublished">
-	      618.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/17/WorldCup/">
-		<h3 class="post-title">World Cup</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-17T07:18:49.000Z" itemprop="datePublished">
-	      617.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/15/Snappy/">
-		<h3 class="post-title">Snappy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-15T09:00:01.000Z" itemprop="datePublished">
-	      615.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <span class="page-number current">1</span><a class="page-number" href="/archives/2018/06/page/2/">2</a><a class="extend next" rel="next" href="/archives/2018/06/page/2/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/06/page/2/index.html b/archives/2018/06/page/2/index.html
deleted file mode 100644
index cf4d557..0000000
--- a/archives/2018/06/page/2/index.html
+++ /dev/null
@@ -1,340 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/6 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/06/page/2/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/14/TimingWheel/">
-		<h3 class="post-title">Timing Wheel</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-14T01:20:25.000Z" itemprop="datePublished">
-	      614.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/13/Ligatures/">
-		<h3 class="post-title">Ligatures</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-13T05:20:38.000Z" itemprop="datePublished">
-	      613.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/12/Calculate24/">
-		<h3 class="post-title">Calculate 24</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-12T06:53:49.000Z" itemprop="datePublished">
-	      612.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/11/ChatChatChat/">
-		<h3 class="post-title">Chat Chat Chat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-11T07:09:34.000Z" itemprop="datePublished">
-	      611.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/06/bitcoin/">
-		<h3 class="post-title">bitcoin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-06T14:19:02.000Z" itemprop="datePublished">
-	      66.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/05/MagicNumber/">
-		<h3 class="post-title">Magic Number</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-05T08:27:07.000Z" itemprop="datePublished">
-	      65.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/03/Raft/">
-		<h3 class="post-title">Raft</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-03T12:59:23.000Z" itemprop="datePublished">
-	      63.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/02/ReplicatedServiceClient/">
-		<h3 class="post-title">Replicated Service Client</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-02T07:01:00.000Z" itemprop="datePublished">
-	      62.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/01/Semaphore/">
-		<h3 class="post-title">Semaphore</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-01T13:07:44.000Z" itemprop="datePublished">
-	      61.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/06/">Prev</a><a class="page-number" href="/archives/2018/06/">1</a><span class="page-number current">2</span>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/07/index.html b/archives/2018/07/index.html
deleted file mode 100644
index 644e38d..0000000
--- a/archives/2018/07/index.html
+++ /dev/null
@@ -1,240 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018/7 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/07/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/07/01/BarberShop/">
-		<h3 class="post-title">BarberShop</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-07-01T09:34:34.000Z" itemprop="datePublished">
-	      71.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/index.html b/archives/2018/index.html
deleted file mode 100644
index 9f66a36..0000000
--- a/archives/2018/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/07/01/BarberShop/">
-		<h3 class="post-title">BarberShop</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-07-01T09:34:34.000Z" itemprop="datePublished">
-	      71.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/27/Graphviz/">
-		<h3 class="post-title">Graphviz</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-27T13:37:09.000Z" itemprop="datePublished">
-	      627.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/26/CGO/">
-		<h3 class="post-title">CGO</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-26T08:34:33.000Z" itemprop="datePublished">
-	      626.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/25/Trie/">
-		<h3 class="post-title">Trie</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-25T14:25:54.000Z" itemprop="datePublished">
-	      625.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/23/PageViews/">
-		<h3 class="post-title">Page Views</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-23T15:08:44.000Z" itemprop="datePublished">
-	      623.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/21/SkipList/">
-		<h3 class="post-title">Skip List</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-21T12:53:24.000Z" itemprop="datePublished">
-	      621.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/20/grep/">
-		<h3 class="post-title">grep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-20T06:07:24.000Z" itemprop="datePublished">
-	      620.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/19/Pipeline/">
-		<h3 class="post-title">Pipeline</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-19T08:39:47.000Z" itemprop="datePublished">
-	      619.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/18/imgcat/">
-		<h3 class="post-title">imgcat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-18T14:02:51.000Z" itemprop="datePublished">
-	      618.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/17/WorldCup/">
-		<h3 class="post-title">World Cup</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-17T07:18:49.000Z" itemprop="datePublished">
-	      617.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <span class="page-number current">1</span><a class="page-number" href="/archives/2018/page/2/">2</a><a class="page-number" href="/archives/2018/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/2/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/2/index.html b/archives/2018/page/2/index.html
deleted file mode 100644
index 5399a24..0000000
--- a/archives/2018/page/2/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/2/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/15/Snappy/">
-		<h3 class="post-title">Snappy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-15T09:00:01.000Z" itemprop="datePublished">
-	      615.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/14/TimingWheel/">
-		<h3 class="post-title">Timing Wheel</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-14T01:20:25.000Z" itemprop="datePublished">
-	      614.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/13/Ligatures/">
-		<h3 class="post-title">Ligatures</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-13T05:20:38.000Z" itemprop="datePublished">
-	      613.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/12/Calculate24/">
-		<h3 class="post-title">Calculate 24</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-12T06:53:49.000Z" itemprop="datePublished">
-	      612.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/11/ChatChatChat/">
-		<h3 class="post-title">Chat Chat Chat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-11T07:09:34.000Z" itemprop="datePublished">
-	      611.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/06/bitcoin/">
-		<h3 class="post-title">bitcoin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-06T14:19:02.000Z" itemprop="datePublished">
-	      66.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/05/MagicNumber/">
-		<h3 class="post-title">Magic Number</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-05T08:27:07.000Z" itemprop="datePublished">
-	      65.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/03/Raft/">
-		<h3 class="post-title">Raft</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-03T12:59:23.000Z" itemprop="datePublished">
-	      63.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/02/ReplicatedServiceClient/">
-		<h3 class="post-title">Replicated Service Client</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-02T07:01:00.000Z" itemprop="datePublished">
-	      62.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/01/Semaphore/">
-		<h3 class="post-title">Semaphore</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-01T13:07:44.000Z" itemprop="datePublished">
-	      61.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/">Prev</a><a class="page-number" href="/archives/2018/">1</a><span class="page-number current">2</span><a class="page-number" href="/archives/2018/page/3/">3</a><a class="page-number" href="/archives/2018/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/3/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/3/index.html b/archives/2018/page/3/index.html
deleted file mode 100644
index a539f6c..0000000
--- a/archives/2018/page/3/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/3/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/31/MemoryMappedFile/">
-		<h3 class="post-title">Memory Mapped File</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-31T11:05:38.000Z" itemprop="datePublished">
-	      531.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/29/ProtocolMultiplexer/">
-		<h3 class="post-title">Protocol Multiplexer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-29T11:50:23.000Z" itemprop="datePublished">
-	      529.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/28/Shredder-Gluer/">
-		<h3 class="post-title">Shredder &amp; Gluer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-28T03:38:22.000Z" itemprop="datePublished">
-	      528.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/27/TUNTAP/">
-		<h3 class="post-title">TUN/TAP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-27T06:05:03.000Z" itemprop="datePublished">
-	      527.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/26/TryLock/">
-		<h3 class="post-title">Try Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-26T14:05:27.000Z" itemprop="datePublished">
-	      526.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/25/ConcurrentPrimeSieve/">
-		<h3 class="post-title">Concurrent Prime Sieve</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-25T06:36:04.000Z" itemprop="datePublished">
-	      525.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/SingleFlight/">
-		<h3 class="post-title">Single Flight</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-24T05:46:36.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/LRU/">
-		<h3 class="post-title">LRU</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T16:23:40.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/23/Heartbeat/">
-		<h3 class="post-title">Heartbeat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T09:52:18.000Z" itemprop="datePublished">
-	      523.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/BitwiseOperation/">
-		<h3 class="post-title">Bitwise Operation</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T11:28:38.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/page/2/">Prev</a><a class="page-number" href="/archives/2018/">1</a><a class="page-number" href="/archives/2018/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/archives/2018/page/4/">4</a><a class="page-number" href="/archives/2018/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/4/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/4/index.html b/archives/2018/page/4/index.html
deleted file mode 100644
index 85b1d65..0000000
--- a/archives/2018/page/4/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/4/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/GUID/">
-		<h3 class="post-title">GUID</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T03:49:08.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/21/mpg123/">
-		<h3 class="post-title">mpg123</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-21T11:12:06.000Z" itemprop="datePublished">
-	      521.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/20/Future/">
-		<h3 class="post-title">Future</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-20T06:04:59.000Z" itemprop="datePublished">
-	      520.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/19/ADB/">
-		<h3 class="post-title">ADB</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-19T07:38:54.000Z" itemprop="datePublished">
-	      519.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/15/ConnectionLimiter/">
-		<h3 class="post-title">Connection Limiter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-15T02:18:24.000Z" itemprop="datePublished">
-	      515.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/14/TerminalUI/">
-		<h3 class="post-title">Terminal UI</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-14T14:49:04.000Z" itemprop="datePublished">
-	      514.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/13/JobDispatcher/">
-		<h3 class="post-title">Job Dispatcher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-13T13:34:24.000Z" itemprop="datePublished">
-	      513.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/ReverseProxy/">
-		<h3 class="post-title">Reverse Proxy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T13:30:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/AdvisoryLock/">
-		<h3 class="post-title">Advisory Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T05:26:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/TokenBucket/">
-		<h3 class="post-title">Token Bucket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T14:05:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/page/3/">Prev</a><a class="page-number" href="/archives/2018/">1</a><a class="page-number" href="/archives/2018/page/2/">2</a><a class="page-number" href="/archives/2018/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/archives/2018/page/5/">5</a><a class="page-number" href="/archives/2018/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/5/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/5/index.html b/archives/2018/page/5/index.html
deleted file mode 100644
index 56376da..0000000
--- a/archives/2018/page/5/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/5/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/StreamCipher/">
-		<h3 class="post-title">Stream Cipher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T05:10:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/10/ConnectionPool/">
-		<h3 class="post-title">Connection Pool</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-10T03:40:24.000Z" itemprop="datePublished">
-	      510.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/MorseCode/">
-		<h3 class="post-title">Morse Code</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T09:07:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/CircuitBreaker/">
-		<h3 class="post-title">Circuit Breaker</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T01:17:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/ColorfulPrinting/">
-		<h3 class="post-title">Colorful Printing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T11:48:24.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/SmoothWeightedRoundRobin/">
-		<h3 class="post-title">Weighted Round Robin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T02:29:04.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/07/MagnetLink/">
-		<h3 class="post-title">Magnet Link</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-07T07:15:24.000Z" itemprop="datePublished">
-	      57.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/06/PubSub/">
-		<h3 class="post-title">PubSub</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-06T11:08:04.000Z" itemprop="datePublished">
-	      56.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/WebSocket/">
-		<h3 class="post-title">WebSocket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:52:04.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/dep/">
-		<h3 class="post-title">dep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:47:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/page/4/">Prev</a><a class="page-number" href="/archives/2018/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/3/">3</a><a class="page-number" href="/archives/2018/page/4/">4</a><span class="page-number current">5</span><a class="page-number" href="/archives/2018/page/6/">6</a><a class="page-number" href="/archives/2018/page/7/">7</a><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/6/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/6/index.html b/archives/2018/page/6/index.html
deleted file mode 100644
index 506144d..0000000
--- a/archives/2018/page/6/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/6/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/Crawler/">
-		<h3 class="post-title">Crawler</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:05:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/04/Docker/">
-		<h3 class="post-title">Docker &amp; Golang</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-04T09:01:24.000Z" itemprop="datePublished">
-	      54.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/Screenshot/">
-		<h3 class="post-title">Screenshot</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T12:29:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/LoadBalancing/">
-		<h3 class="post-title">Load Balancing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T10:12:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/DecodingDubboProtocol/">
-		<h3 class="post-title">Dubbo Protocol</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T07:58:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/TLS/">
-		<h3 class="post-title">TLS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T04:40:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/iobridge/">
-		<h3 class="post-title">iobridge</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T13:13:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/etcd/">
-		<h3 class="post-title">etcd</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T04:28:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/Port_0/">
-		<h3 class="post-title">port 0, WTF?</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T03:11:11.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/ConsistentHashing/">
-		<h3 class="post-title">Connection Hashing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T10:59:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/page/5/">Prev</a><a class="page-number" href="/archives/2018/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/4/">4</a><a class="page-number" href="/archives/2018/page/5/">5</a><span class="page-number current">6</span><a class="page-number" href="/archives/2018/page/7/">7</a><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/7/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/7/index.html b/archives/2018/page/7/index.html
deleted file mode 100644
index 7296ba2..0000000
--- a/archives/2018/page/7/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/7/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/Crontab/">
-		<h3 class="post-title">crontab</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T05:58:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/TCP_IP/">
-		<h3 class="post-title">TCP/IP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-29T11:56:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/BloomFilter/">
-		<h3 class="post-title">Bloom Filter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-28T16:00:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/EventTimer/">
-		<h3 class="post-title">Event Timer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T06:47:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/MerkleTree/">
-		<h3 class="post-title">Merkle Tree</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T04:18:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/FactoryPattern/">
-		<h3 class="post-title">Factory Pattern</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T15:27:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/LeakyBuffer/">
-		<h3 class="post-title">Leaky Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T06:21:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/EventProcessEngine/">
-		<h3 class="post-title">Event Process Engine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T01:43:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Fanin/">
-		<h3 class="post-title">Fan-in</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T12:35:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/gRPC/">
-		<h3 class="post-title">gRPC</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:27:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/page/6/">Prev</a><a class="page-number" href="/archives/2018/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/5/">5</a><a class="page-number" href="/archives/2018/page/6/">6</a><span class="page-number current">7</span><a class="page-number" href="/archives/2018/page/8/">8</a><a class="extend next" rel="next" href="/archives/2018/page/8/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/2018/page/8/index.html b/archives/2018/page/8/index.html
deleted file mode 100644
index d39a5ef..0000000
--- a/archives/2018/page/8/index.html
+++ /dev/null
@@ -1,304 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives: 2018 | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/2018/page/8/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Protobuf/">
-		<h3 class="post-title">Protocol Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:03:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/FSM/">
-		<h3 class="post-title">Finite State Machine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T01:58:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/24/PKCS7_Padding/">
-		<h3 class="post-title">PKCS7 Padding</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-24T08:26:24.000Z" itemprop="datePublished">
-	      424.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/23/RSS/">
-		<h3 class="post-title">RSS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-23T13:50:37.000Z" itemprop="datePublished">
-	      423.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/22/heap/">
-		<h3 class="post-title">heap</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-22T09:44:48.000Z" itemprop="datePublished">
-	      422.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/02/05/CryptoBasic/">
-		<h3 class="post-title">Cryptography Basics</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-02-05T14:39:55.000Z" itemprop="datePublished">
-	      25.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/2018/page/7/">Prev</a><a class="page-number" href="/archives/2018/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/2018/page/6/">6</a><a class="page-number" href="/archives/2018/page/7/">7</a><span class="page-number current">8</span>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/index.html b/archives/index.html
deleted file mode 100644
index f81995a..0000000
--- a/archives/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/07/01/BarberShop/">
-		<h3 class="post-title">BarberShop</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-07-01T09:34:34.000Z" itemprop="datePublished">
-	      71.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/27/Graphviz/">
-		<h3 class="post-title">Graphviz</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-27T13:37:09.000Z" itemprop="datePublished">
-	      627.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/26/CGO/">
-		<h3 class="post-title">CGO</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-26T08:34:33.000Z" itemprop="datePublished">
-	      626.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/25/Trie/">
-		<h3 class="post-title">Trie</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-25T14:25:54.000Z" itemprop="datePublished">
-	      625.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/23/PageViews/">
-		<h3 class="post-title">Page Views</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-23T15:08:44.000Z" itemprop="datePublished">
-	      623.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/21/SkipList/">
-		<h3 class="post-title">Skip List</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-21T12:53:24.000Z" itemprop="datePublished">
-	      621.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/20/grep/">
-		<h3 class="post-title">grep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-20T06:07:24.000Z" itemprop="datePublished">
-	      620.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/19/Pipeline/">
-		<h3 class="post-title">Pipeline</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-19T08:39:47.000Z" itemprop="datePublished">
-	      619.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/18/imgcat/">
-		<h3 class="post-title">imgcat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-18T14:02:51.000Z" itemprop="datePublished">
-	      618.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/17/WorldCup/">
-		<h3 class="post-title">World Cup</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-17T07:18:49.000Z" itemprop="datePublished">
-	      617.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <span class="page-number current">1</span><a class="page-number" href="/archives/page/2/">2</a><a class="page-number" href="/archives/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/2/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/2/index.html b/archives/page/2/index.html
deleted file mode 100644
index aa9eeb3..0000000
--- a/archives/page/2/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/2/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/15/Snappy/">
-		<h3 class="post-title">Snappy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-15T09:00:01.000Z" itemprop="datePublished">
-	      615.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/14/TimingWheel/">
-		<h3 class="post-title">Timing Wheel</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-14T01:20:25.000Z" itemprop="datePublished">
-	      614.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/13/Ligatures/">
-		<h3 class="post-title">Ligatures</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-13T05:20:38.000Z" itemprop="datePublished">
-	      613.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/12/Calculate24/">
-		<h3 class="post-title">Calculate 24</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-12T06:53:49.000Z" itemprop="datePublished">
-	      612.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/11/ChatChatChat/">
-		<h3 class="post-title">Chat Chat Chat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-11T07:09:34.000Z" itemprop="datePublished">
-	      611.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/06/bitcoin/">
-		<h3 class="post-title">bitcoin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-06T14:19:02.000Z" itemprop="datePublished">
-	      66.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/05/MagicNumber/">
-		<h3 class="post-title">Magic Number</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-05T08:27:07.000Z" itemprop="datePublished">
-	      65.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/03/Raft/">
-		<h3 class="post-title">Raft</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-03T12:59:23.000Z" itemprop="datePublished">
-	      63.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/02/ReplicatedServiceClient/">
-		<h3 class="post-title">Replicated Service Client</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-02T07:01:00.000Z" itemprop="datePublished">
-	      62.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/01/Semaphore/">
-		<h3 class="post-title">Semaphore</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-01T13:07:44.000Z" itemprop="datePublished">
-	      61.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/">Prev</a><a class="page-number" href="/archives/">1</a><span class="page-number current">2</span><a class="page-number" href="/archives/page/3/">3</a><a class="page-number" href="/archives/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/3/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/3/index.html b/archives/page/3/index.html
deleted file mode 100644
index fbc9183..0000000
--- a/archives/page/3/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/3/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/31/MemoryMappedFile/">
-		<h3 class="post-title">Memory Mapped File</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-31T11:05:38.000Z" itemprop="datePublished">
-	      531.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/29/ProtocolMultiplexer/">
-		<h3 class="post-title">Protocol Multiplexer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-29T11:50:23.000Z" itemprop="datePublished">
-	      529.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/28/Shredder-Gluer/">
-		<h3 class="post-title">Shredder &amp; Gluer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-28T03:38:22.000Z" itemprop="datePublished">
-	      528.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/27/TUNTAP/">
-		<h3 class="post-title">TUN/TAP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-27T06:05:03.000Z" itemprop="datePublished">
-	      527.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/26/TryLock/">
-		<h3 class="post-title">Try Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-26T14:05:27.000Z" itemprop="datePublished">
-	      526.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/25/ConcurrentPrimeSieve/">
-		<h3 class="post-title">Concurrent Prime Sieve</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-25T06:36:04.000Z" itemprop="datePublished">
-	      525.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/SingleFlight/">
-		<h3 class="post-title">Single Flight</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-24T05:46:36.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/LRU/">
-		<h3 class="post-title">LRU</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T16:23:40.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/23/Heartbeat/">
-		<h3 class="post-title">Heartbeat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T09:52:18.000Z" itemprop="datePublished">
-	      523.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/BitwiseOperation/">
-		<h3 class="post-title">Bitwise Operation</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T11:28:38.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/page/2/">Prev</a><a class="page-number" href="/archives/">1</a><a class="page-number" href="/archives/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/archives/page/4/">4</a><a class="page-number" href="/archives/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/4/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/4/index.html b/archives/page/4/index.html
deleted file mode 100644
index 7a461c1..0000000
--- a/archives/page/4/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/4/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/GUID/">
-		<h3 class="post-title">GUID</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T03:49:08.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/21/mpg123/">
-		<h3 class="post-title">mpg123</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-21T11:12:06.000Z" itemprop="datePublished">
-	      521.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/20/Future/">
-		<h3 class="post-title">Future</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-20T06:04:59.000Z" itemprop="datePublished">
-	      520.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/19/ADB/">
-		<h3 class="post-title">ADB</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-19T07:38:54.000Z" itemprop="datePublished">
-	      519.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/15/ConnectionLimiter/">
-		<h3 class="post-title">Connection Limiter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-15T02:18:24.000Z" itemprop="datePublished">
-	      515.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/14/TerminalUI/">
-		<h3 class="post-title">Terminal UI</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-14T14:49:04.000Z" itemprop="datePublished">
-	      514.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/13/JobDispatcher/">
-		<h3 class="post-title">Job Dispatcher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-13T13:34:24.000Z" itemprop="datePublished">
-	      513.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/ReverseProxy/">
-		<h3 class="post-title">Reverse Proxy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T13:30:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/AdvisoryLock/">
-		<h3 class="post-title">Advisory Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T05:26:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/TokenBucket/">
-		<h3 class="post-title">Token Bucket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T14:05:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/page/3/">Prev</a><a class="page-number" href="/archives/">1</a><a class="page-number" href="/archives/page/2/">2</a><a class="page-number" href="/archives/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/archives/page/5/">5</a><a class="page-number" href="/archives/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/5/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/5/index.html b/archives/page/5/index.html
deleted file mode 100644
index e34f515..0000000
--- a/archives/page/5/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/5/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/StreamCipher/">
-		<h3 class="post-title">Stream Cipher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T05:10:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/10/ConnectionPool/">
-		<h3 class="post-title">Connection Pool</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-10T03:40:24.000Z" itemprop="datePublished">
-	      510.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/MorseCode/">
-		<h3 class="post-title">Morse Code</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T09:07:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/CircuitBreaker/">
-		<h3 class="post-title">Circuit Breaker</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T01:17:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/ColorfulPrinting/">
-		<h3 class="post-title">Colorful Printing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T11:48:24.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/SmoothWeightedRoundRobin/">
-		<h3 class="post-title">Weighted Round Robin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T02:29:04.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/07/MagnetLink/">
-		<h3 class="post-title">Magnet Link</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-07T07:15:24.000Z" itemprop="datePublished">
-	      57.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/06/PubSub/">
-		<h3 class="post-title">PubSub</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-06T11:08:04.000Z" itemprop="datePublished">
-	      56.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/WebSocket/">
-		<h3 class="post-title">WebSocket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:52:04.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/dep/">
-		<h3 class="post-title">dep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:47:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/page/4/">Prev</a><a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/3/">3</a><a class="page-number" href="/archives/page/4/">4</a><span class="page-number current">5</span><a class="page-number" href="/archives/page/6/">6</a><a class="page-number" href="/archives/page/7/">7</a><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/6/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/6/index.html b/archives/page/6/index.html
deleted file mode 100644
index 38af214..0000000
--- a/archives/page/6/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/6/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/Crawler/">
-		<h3 class="post-title">Crawler</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:05:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/04/Docker/">
-		<h3 class="post-title">Docker &amp; Golang</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-04T09:01:24.000Z" itemprop="datePublished">
-	      54.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/Screenshot/">
-		<h3 class="post-title">Screenshot</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T12:29:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/LoadBalancing/">
-		<h3 class="post-title">Load Balancing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T10:12:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/DecodingDubboProtocol/">
-		<h3 class="post-title">Dubbo Protocol</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T07:58:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/TLS/">
-		<h3 class="post-title">TLS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T04:40:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/iobridge/">
-		<h3 class="post-title">iobridge</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T13:13:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/etcd/">
-		<h3 class="post-title">etcd</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T04:28:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/Port_0/">
-		<h3 class="post-title">port 0, WTF?</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T03:11:11.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/ConsistentHashing/">
-		<h3 class="post-title">Connection Hashing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T10:59:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/page/5/">Prev</a><a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/4/">4</a><a class="page-number" href="/archives/page/5/">5</a><span class="page-number current">6</span><a class="page-number" href="/archives/page/7/">7</a><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/7/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/7/index.html b/archives/page/7/index.html
deleted file mode 100644
index 125930d..0000000
--- a/archives/page/7/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/7/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/Crontab/">
-		<h3 class="post-title">crontab</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T05:58:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/TCP_IP/">
-		<h3 class="post-title">TCP/IP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-29T11:56:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/BloomFilter/">
-		<h3 class="post-title">Bloom Filter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-28T16:00:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/EventTimer/">
-		<h3 class="post-title">Event Timer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T06:47:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/MerkleTree/">
-		<h3 class="post-title">Merkle Tree</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T04:18:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/FactoryPattern/">
-		<h3 class="post-title">Factory Pattern</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T15:27:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/LeakyBuffer/">
-		<h3 class="post-title">Leaky Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T06:21:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/EventProcessEngine/">
-		<h3 class="post-title">Event Process Engine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T01:43:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Fanin/">
-		<h3 class="post-title">Fan-in</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T12:35:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/gRPC/">
-		<h3 class="post-title">gRPC</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:27:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/page/6/">Prev</a><a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/5/">5</a><a class="page-number" href="/archives/page/6/">6</a><span class="page-number current">7</span><a class="page-number" href="/archives/page/8/">8</a><a class="extend next" rel="next" href="/archives/page/8/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/archives/page/8/index.html b/archives/page/8/index.html
deleted file mode 100644
index 115bc7f..0000000
--- a/archives/page/8/index.html
+++ /dev/null
@@ -1,340 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Archives | Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/archives/page/8/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Protobuf/">
-		<h3 class="post-title">Protocol Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:03:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/FSM/">
-		<h3 class="post-title">Finite State Machine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T01:58:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/24/PKCS7_Padding/">
-		<h3 class="post-title">PKCS7 Padding</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-24T08:26:24.000Z" itemprop="datePublished">
-	      424.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/23/RSS/">
-		<h3 class="post-title">RSS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-23T13:50:37.000Z" itemprop="datePublished">
-	      423.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/22/heap/">
-		<h3 class="post-title">heap</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-22T09:44:48.000Z" itemprop="datePublished">
-	      422.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/02/05/CryptoBasic/">
-		<h3 class="post-title">Cryptography Basics</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-02-05T14:39:55.000Z" itemprop="datePublished">
-	      25.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/12/07/openssl/">
-		<h3 class="post-title">openssl</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-12-07T05:17:05.000Z" itemprop="datePublished">
-	      127.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/02/LinuxManiac/">
-		<h3 class="post-title">Linux Maniac</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-02T13:24:46.000Z" itemprop="datePublished">
-	      92.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/01/TODO/">
-		<h3 class="post-title">TODO</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-01T13:20:48.000Z" itemprop="datePublished">
-	      91.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/archives/page/7/">Prev</a><a class="page-number" href="/archives/">1</a><span class="space">&hellip;</span><a class="page-number" href="/archives/page/6/">6</a><a class="page-number" href="/archives/page/7/">7</a><span class="page-number current">8</span>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/atom.xml b/atom.xml
deleted file mode 100644
index 612a0a8..0000000
--- a/atom.xml
+++ /dev/null
@@ -1,451 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<feed xmlns="http://www.w3.org/2005/Atom">
-  <title>Whyyy</title>
-  
-  
-  <link href="/atom.xml" rel="self"/>
-  
-  <link href="https://oceanoverflow.github.io/"/>
-  <updated>2018-07-02T10:48:13.921Z</updated>
-  <id>https://oceanoverflow.github.io/</id>
-  
-  <author>
-    <name>Yangyi, Yi</name>
-    
-  </author>
-  
-  <generator uri="http://hexo.io/">Hexo</generator>
-  
-  <entry>
-    <title>BarberShop</title>
-    <link href="https://oceanoverflow.github.io/2018/07/01/BarberShop/"/>
-    <id>https://oceanoverflow.github.io/2018/07/01/BarberShop/</id>
-    <published>2018-07-01T09:34:34.000Z</published>
-    <updated>2018-07-02T10:48:13.921Z</updated>
-    
-    <content type="html"><![CDATA[<p>理发师问题是操作系统中一个非常经典的同步问题，假设理发店里有一位理发师，一把理发椅和5把供等候理发的顾客坐的椅子。如果当前没有顾客，则理发师躺在理发椅上睡觉，如果有顾客前来，他必须唤醒理发师，如果理发师正在理发但又有顾客前来，如果有空位置可坐，顾客就坐下来等待，否则则离开。</p><p>下面我们使用 <code>golang</code> 中的 <code>for select</code> 机制结合 <code>goroutine</code> 和 <code>channel</code> 来解决这个问题。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    CUTTING_TIME = <span class="number">20</span></span><br><span class="line">    BARBERS_COUNT = <span class="number">1</span></span><br><span class="line">    HALL_SITS_AMOUNT = <span class="number">5</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Barber <span class="keyword">struct</span> &#123;</span><br><span class="line">    name <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Client <span class="keyword">struct</span> &#123;</span><br><span class="line">    name <span class="keyword">int</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>clientProducer</code> 模拟顾客前来，每隔一段随机的时间，前来一位顾客，<code>cutHear</code> 模拟理发师理发过程，理发结束时，向 <code>finished</code> 通道发送一个 <code>barber</code> ，表示该理发师已经空闲。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">clientProducer</span><span class="params">(clients <span class="keyword">chan</span> *Client)</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        time.Sleep(time.Duration(rand.Intn(<span class="number">28</span>) + <span class="number">7</span>)</span><br><span class="line">        clients &lt;- &amp;Client&#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">cutHear</span><span class="params">(barber *Barber, client *Client, finished <span class="keyword">chan</span> *Barber)</span></span> &#123;</span><br><span class="line">    fmt.Printf(<span class="string">"%v cutting hear for %v\n"</span>, barber.name, client.name)</span><br><span class="line">    time.Sleep(CUTTING_TIME * time.Millisecond)</span><br><span class="line">    finished &lt;- barber</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>若一顾客进入理发店，理发师正在为别人理发，且等待室有空椅子，该顾客就找张椅子按顺序坐下；</li><li>若一顾客进入理发店，理发师正在为别人理发，且所有椅子都被占用了，该顾客马上离开。</li><li>若一顾客进入理发店，理发师在睡觉，则叫醒理发师为该顾客理发；</li><li>如果理发师工作完，发现还有在等待的顾客，则呼唤顾客前来理发。</li><li>若没有要理发的顾客，则理发师去睡觉；</li></ol><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">BarberShop</span><span class="params">(clients &lt;-<span class="keyword">chan</span> *Client)</span></span> &#123;</span><br><span class="line">    freeBarbers := []*Barber&#123;&#125;</span><br><span class="line">    waitingClient := []*Client&#123;&#125;</span><br><span class="line">    syncBarberChan := <span class="built_in">make</span>(<span class="keyword">chan</span> *Barber)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; BARBERS_COUNT; i++ &#123;</span><br><span class="line">        freeBarbers = <span class="built_in">append</span>(freeBarbers, &amp;Barber&#123;&#125;)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> client := &lt;-clients:</span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">len</span>(freeBarbers) == <span class="number">0</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> <span class="built_in">len</span>(waitingClient) &lt; HALL_SITS_AMOUNT &#123;</span><br><span class="line">                    waitingClient = <span class="built_in">append</span>(waitingClient, client)</span><br><span class="line">                    fmt.Printf(<span class="string">"Client is waiting in hall (%v)\n"</span>, <span class="built_in">len</span>(waitingClient))</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    fmt.Println(<span class="string">"No free space for client"</span>)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                barber := freeBarbers[<span class="number">0</span>]</span><br><span class="line">                freeBarbers := freeBarbers[<span class="number">1</span>:]</span><br><span class="line">                fmt.Println(<span class="string">"Client goes to barber"</span>)</span><br><span class="line">                <span class="keyword">go</span> cutHear(barber, client, syncBarberChan)</span><br><span class="line">            &#125;</span><br><span class="line">        <span class="keyword">case</span> barber := &lt;-syncBarberChan:</span><br><span class="line">            <span class="keyword">if</span> <span class="built_in">len</span>(waitingClient) &gt; <span class="number">0</span> &#123;</span><br><span class="line">                client := waitingClient[<span class="number">0</span>]</span><br><span class="line">                waitingClient = waitingClient[<span class="number">1</span>:]</span><br><span class="line">                fmt.Printf(<span class="string">"Take client from room (%v)\n"</span>, <span class="built_in">len</span>(waitingClient))</span><br><span class="line">                <span class="keyword">go</span> cutHear(barber, client, syncBarberChan)</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                fmt.Println(<span class="string">"Barber idle"</span>)</span><br><span class="line">                freeBarbers = <span class="built_in">append</span>(freeBarbers, barbers)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们在 <code>main</code> 函数中起两个 <code>goroutine</code> ，分别代表顾客进程和理发师进程，理发师在工作8小时后退出，<code>clients</code> 通道作为两个 <code>goroutine</code> 沟通的媒介，类似于生产者和消费者模式。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    clients := <span class="built_in">make</span>(<span class="keyword">chan</span> *Client)</span><br><span class="line">    <span class="keyword">go</span> clientProducer(clients)</span><br><span class="line">    <span class="keyword">go</span> BarberShop(clients)</span><br><span class="line">    time.Sleep(<span class="number">8</span> * time.Hour)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;理发师问题是操作系统中一个非常经典的同步问题，假设理发店里有一位理发师，一把理发椅和5把供等候理发的顾客坐的椅子。如果当前没有顾客，则理发师躺在理发椅上睡觉，如果有顾客前来，他必须唤醒理发师，如果理发师正在理发但又有顾客前来，如果有空位置可坐，顾客就坐下来等待，否则则离开。
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Graphviz</title>
-    <link href="https://oceanoverflow.github.io/2018/06/27/Graphviz/"/>
-    <id>https://oceanoverflow.github.io/2018/06/27/Graphviz/</id>
-    <published>2018-06-27T13:37:09.000Z</published>
-    <updated>2018-06-27T13:45:10.019Z</updated>
-    
-    <content type="html"><![CDATA[<p>最近看了许多比较酷炫的数据结构的实现，例如 <code>Trie</code> ， <code>Skip List</code> ，<code>B-Tree</code> 等，看代码的时候经常会想，要是有什么工具可以帮助我们将内存中的结构体绘制出来就好了，搜了一下 <code>github</code> ，发现早已经有大佬帮我们实现过了。</p><p>下面以二叉搜索树为例，来看一下如何使用 <code>graphviz</code> 绘制内存中的结构体。二叉树的定义非常简单，每个节点都有一个左节点和右节点，用于指向自己的左子树和右子树。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Node <span class="keyword">struct</span> &#123;</span><br><span class="line">    val   <span class="keyword">int</span></span><br><span class="line">    left  *Node</span><br><span class="line">    right *Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">Insert</span><span class="params">(val <span class="keyword">int</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> errors.New(<span class="string">"Cannot insert a value into a nil tree"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">switch</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> val == n.val:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    <span class="keyword">case</span> val &lt; n.val:</span><br><span class="line">        <span class="keyword">if</span> n.left == <span class="literal">nil</span> &#123;</span><br><span class="line">            n.left = &amp;Node&#123;val: val&#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> n.left.Insert(val)</span><br><span class="line">    <span class="keyword">case</span> val &gt; n.val:</span><br><span class="line">        <span class="keyword">if</span> n.right == <span class="literal">nil</span> &#123;</span><br><span class="line">            n.right = &amp;Node&#123;val: val&#125;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> n.right.Insert(val)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Tree <span class="keyword">struct</span> &#123;</span><br><span class="line">    Root  *Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Tree)</span> <span class="title">Insert</span><span class="params">(val <span class="keyword">int</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> t.root == <span class="literal">nil</span> &#123;</span><br><span class="line">        t.Root = &amp;Node&#123;val: val&#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> t.Root.Insert(value)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在 <code>main</code> 函数中我们构造一个二叉树，并向该树中随意插入一些值，最后我们使用 <code>memviz.Map(os.Stdout, &amp;tree)</code> 将该树对应的 <code>DOT</code> 形态输出到标准输出中。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">"github.com/bradleyjkemp/memviz"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    tree := &amp;Tree&#123;&#125;</span><br><span class="line">    values := []<span class="keyword">int</span>&#123;<span class="number">4</span>, <span class="number">2</span>, <span class="number">6</span>, <span class="number">1</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="number">7</span>&#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(values); i++ &#123;</span><br><span class="line">        err := tree.Insert(values[i])</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Fatal(<span class="string">"Error inserting value '"</span>, values[i], <span class="string">"': "</span>, err)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    memviz.Map(os.Stdout, &amp;tree)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>利用 <code>unix pipe</code> 将 <code>go run main.go</code> 得到的结果输入到 <code>dot</code> 命令中。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ go run main.go | dot -Tpng -o output.png | open output.png</span><br></pre></td></tr></table></figure><p><img src="https://image.ibb.co/bPod9o/output.png" alt="graphviz"></p><p> <code>dot</code> 命令相当于 <code>graphviz</code> 的一个子命令，它专门用于绘制有向图，除了 <code>dot</code> 之外，还有 <code>neato</code> ，<code>twopi</code> ，<code>circo</code> ，<code>fdp</code> ，<code>sfdp</code> ，<code>patchword</code> 和<code>osage</code> ，它们的用法与 <code>dot</code> 完全一致，只是它们的用处稍稍不同，例如 <code>neato</code> 比较适合用来绘制无向图。</p><p>下面我们来看一下（ <code>memviz.Map(os.Stdout, &amp;tree)</code> ）的实现，该函数的实现主要依靠 <code>golang</code> 中的反射机制（ <code>reflect</code> ），利用 <code>reflect</code> 可以在运行时审查元素的类型，然后根据其类型，构造符合 <code>dot</code> 的语法的模版就行了。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Map</span><span class="params">(w io.Writer, is ...<span class="keyword">interface</span>&#123;&#125;)</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> iVals []reflect.Value</span><br><span class="line">    <span class="keyword">for</span> _, i := <span class="keyword">range</span> is &#123;</span><br><span class="line">        iVal := reflect.ValueOf(i)</span><br><span class="line">        <span class="keyword">if</span> !iVal.CanAddr() &#123;</span><br><span class="line">            <span class="keyword">if</span> iVal.Kind() != reflect.Ptr &amp;&amp; iVal.Kind() != reflect.Interface &#123;</span><br><span class="line">                fmt.Fprint(w, <span class="string">"error: cannot map unaddressable value"</span>)</span><br><span class="line">                <span class="keyword">return</span></span><br><span class="line">             &#125;</span><br><span class="line">             iVal = iVal.Elem()</span><br><span class="line">        &#125;</span><br><span class="line">        iVals = <span class="built_in">append</span>(iVals, iVal)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    m := &amp;mapper&#123;</span><br><span class="line">        w,</span><br><span class="line">        <span class="keyword">map</span>[nodeKey]nodeID&#123;nilKey: <span class="number">0</span>&#125;,</span><br><span class="line">        <span class="keyword">map</span>[nodeKey]<span class="keyword">string</span>&#123;nilKey: <span class="string">"nil"</span>&#125;,</span><br><span class="line">        <span class="number">2</span>,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fmt.Fprintln(w, <span class="string">"digraph structs &#123;"</span>)</span><br><span class="line">    fmt.Fprintln(w, <span class="string">"  node [shape=Mrecord];"</span>)</span><br><span class="line">    <span class="keyword">for</span> _, iVal := <span class="keyword">range</span> iVals &#123;</span><br><span class="line">        m.mapValue(iVal, <span class="number">0</span>, <span class="literal">false</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Fprintln(w, <span class="string">"&#125;"</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;最近看了许多比较酷炫的数据结构的实现，例如 &lt;code&gt;Trie&lt;/code&gt; ， &lt;code&gt;Skip List&lt;/code&gt; ，&lt;code&gt;B-Tree&lt;/code&gt; 等，看代码的时候经常会想，要是有什么工具可以帮助我们将内存中的结构体绘制出来就好了，搜了一下 &lt;cod
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>CGO</title>
-    <link href="https://oceanoverflow.github.io/2018/06/26/CGO/"/>
-    <id>https://oceanoverflow.github.io/2018/06/26/CGO/</id>
-    <published>2018-06-26T08:34:33.000Z</published>
-    <updated>2018-07-03T12:18:05.760Z</updated>
-    
-    <content type="html"><![CDATA[<p>cgo is an amazing technology which allows Go programs to interoperate with C libraries. Given a Go source file written with some special features, cgo outputs Go and C files that can be combined into a single Go package.</p><p>C code and Go code live in two different universes, cgo traverses the boundary between them. The transition is not free and depending on where it exists in your code, the cost could be inconsequential, or substantial.  </p><p>There are some cases where cgo is unavoidable, most notably where you have to interoperate with a graphics driver or windowing system what is only available as a binary blob.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> rand</span><br><span class="line"></span><br><span class="line"><span class="comment">// #include &lt;stdlib.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Random</span><span class="params">()</span> <span class="title">int</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> r C.long = C.random()</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">int</span>(r)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Seed</span><span class="params">(i <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    C.srandom(C.<span class="keyword">uint</span>(i))  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="cgo-directives"><a href="#cgo-directives" class="headerlink" title="cgo directives"></a>cgo directives</h2><p>cgo is not a language nor a compiler. It’s a Foreign Function Interface (FFI), a mechanism we can use in Go to invoke functions and services written in a different language, specifically C.</p><p>The comment block right above the import “C” instruction is called a “preamble” and can contain actual C code, in this case an header inclusion. Once imported, the “C” pseudo-package lets us “jump” to the foreign code. You can build the example by invoking go build, the same as if it was plain Go.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include &lt;stdio.h&gt;</span></span><br><span class="line"><span class="comment">// #include &lt;errno.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br></pre></td></tr></table></figure><p>CFLAGS, CPPFLAGS, CXXFLAGS, FFLAGS, LDFLAGS may be defined with pseudo <code>#cgo</code> directives within these comments to tweak the behavior of the C, C++ or Fortran compiler. Values defined in multiple directives are concatenated together. The directive can include a list of build constraints limiting its effect to systems satisfying one of the constraints.</p><p>cgo recognizes this comment. Any lines starting with <code>#cgo</code> followed by a space character are removed; these become directives for cgo. The remaining lines are used as a header when compiling the C parts of the package. In this case those lines are just a single <code>#include</code> statement, but they can be almost any C code. The <code>cgo</code> directives are used to provide flags for the compiler and linker when building the C parts of the package.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo CFLAGS: -DPNG_DEBUG=1</span></span><br><span class="line"><span class="comment">// #cgo amd64 386 CFLAGS: -D86=1</span></span><br><span class="line"><span class="comment">// #cgo LDFLAGS: -lpng</span></span><br><span class="line"><span class="comment">// #include &lt;png.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br></pre></td></tr></table></figure><p>Alternatively, CPPFLAGS and LDFLAGS may be obtained via the pkg-config tool using a ‘#cgo pkg-config:’ directive followed by the package names. For example:</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo pkg-config: png cairo</span></span><br><span class="line"><span class="comment">// #include &lt;png.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo LDFLAGS -L$&#123;SRCDIR&#125;/libs -l foo</span></span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #cgo LDFLAGS -L/go/src/foo/libs -l foo</span></span><br></pre></td></tr></table></figure><p><code>-L</code> is the path to the directories containing the libraries. A search path for libraries.<br><code>-l</code> is the name of the library you want to link to.</p><p>For instance, if you want to link to the library  <code>~/libs/libabc.a</code>  you’d add:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-L$(HOME)/libs -labc</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">| file                            | compiler          |</span><br><span class="line">| ------------------------------- |:-----------------:|</span><br><span class="line">| xxx.c, xxx.s, xxx.S             | C compiler        |</span><br><span class="line">| xxx.cc, xxx.cpp, xxx.cxx        | C++ compiler      |</span><br><span class="line">| xxx.f, xxx.F, xxx.for, xxx.f90  | fortran compiler  |</span><br><span class="line"></span><br><span class="line">Any .h, .hh, .hpp or .hxx files will not be compiled separately, but if these header files are changed, the C and C++ files will be recompiled.</span><br></pre></td></tr></table></figure><h2 id="tips-about-pkg-config"><a href="#tips-about-pkg-config" class="headerlink" title="tips about pkg-config"></a>tips about pkg-config</h2><p>pkg-config: return metainformation about installed libraries.</p><p>The <code>pkg-config</code> program is used to retrieve information about installed libraries in the system. It is typically used to compile and link against one or more libraries. Here is a typical usage scenario in a Makefile:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">program: program.c</span><br><span class="line">    cc program.c `pkg-config --cflags --libs gnomeui`</span><br></pre></td></tr></table></figure><p><code>pkg-config</code> retrieves information about packages from special metadata files. These files are named after the package, and has a <code>.pc</code> extension. On most systems, <code>pkg-config</code> looks in <code>/usr/lib/pkgconfig</code> , <code>/usr/share/pkgconfig</code> , <code>/usr/local/lib/pkgconfig</code> and <code>/usr/local/share/pkgconfig</code> for these files. It will additionally look in the colon-separated (on Windows, semi-colon-separated) list of directories specified by the <code>PKG_CONFIG_PATH</code> environment variable.</p><p>The package name specified on the <code>pkg-config</code> command line is defined to be the name of the metadata file, minus the <code>.pc</code> extension. If a library can install multiple versions simultaneously, it must give each version its own name (for example, GTK 1.2 might have the package name “gtk+” while GTK 2.0 has “gtk-2.0”).</p><p>In addition to specifying a package name on the command line, the full path to a given <code>.pc</code> file may be given instead. This allows a user to directly query a particular <code>.pc</code> file.</p><p><code>/usr/local/lib/pkgconfig/libuv.pc</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">prefix=/usr/local/Cellar/libuv/1.20.0</span><br><span class="line">exec_prefix=$&#123;prefix&#125;</span><br><span class="line">libdir=$&#123;exec_prefix&#125;/lib</span><br><span class="line">includedir=$&#123;prefix&#125;/include</span><br><span class="line"></span><br><span class="line">Name: libuv</span><br><span class="line">Version: 1.20.0</span><br><span class="line">Description: multi-platform support library with a focus on asynchronous I/O.</span><br><span class="line">URL: http://libuv.org/</span><br><span class="line"></span><br><span class="line">Libs: -L$&#123;libdir&#125; -luv -lphread -ldl</span><br><span class="line">Cflags: -I$&#123;includedir&#125;</span><br></pre></td></tr></table></figure><h2 id="basic-data-type-conversion"><a href="#basic-data-type-conversion" class="headerlink" title="basic data type conversion"></a>basic data type conversion</h2><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">| C                   | Go              |</span><br><span class="line">| ------------------- |:---------------:|</span><br><span class="line">| <span class="keyword">char</span>                | C.<span class="keyword">char</span>          |</span><br><span class="line">| <span class="keyword">signed</span> <span class="keyword">char</span>         | C.schar         |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">char</span>       | C.uchar         |</span><br><span class="line">| <span class="keyword">short</span>               | C.<span class="keyword">short</span>         |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">short</span>      | C.ushort        |</span><br><span class="line">| <span class="keyword">int</span>                 | C.<span class="keyword">int</span>           |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">int</span>        | C.uint          |</span><br><span class="line">| <span class="keyword">long</span>                | C.<span class="keyword">long</span>          |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">long</span>       | C.ulong         |</span><br><span class="line">| <span class="keyword">long</span> <span class="keyword">long</span>           | C.longlong      |</span><br><span class="line">| <span class="keyword">unsigned</span> <span class="keyword">long</span> <span class="keyword">long</span>  | C.ulonglong     |</span><br><span class="line">| <span class="keyword">float</span>               | C.<span class="keyword">float</span>         |</span><br><span class="line">| <span class="keyword">double</span>              | C.<span class="keyword">double</span>        |</span><br><span class="line">| <span class="keyword">complex</span> <span class="keyword">float</span>       | C.complexfloat  |</span><br><span class="line">| <span class="keyword">complex</span> <span class="keyword">double</span>      | C.complexdouble |</span><br><span class="line">| <span class="keyword">long</span> <span class="keyword">long</span>           | C.longlong      |</span><br><span class="line">| <span class="keyword">void</span> *              | unsafe.Pointer  |</span><br><span class="line">| <span class="keyword">__int128_t</span>          | [<span class="number">16</span>]byte        |</span><br><span class="line">| <span class="keyword">__uint128_t</span>         | [<span class="number">16</span>]byte        |</span><br><span class="line">| few special C types | uintptr         |</span><br></pre></td></tr></table></figure><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">| C                | Go                |</span><br><span class="line">| ---------------- |:-----------------:|</span><br><span class="line">| <span class="keyword">sizeof</span>(T)        | C.sizeof_T        |</span><br><span class="line">| <span class="keyword">sizeof</span>(struct T) | C.sizeof_struct_T |</span><br><span class="line">| <span class="class"><span class="keyword">struct</span> <span class="title">X</span>         | <span class="title">C</span>.<span class="title">struct_X</span>        |</span></span><br><span class="line"><span class="class">| <span class="title">union</span> <span class="title">X</span>          | <span class="title">C</span>.<span class="title">union_X</span>         |</span></span><br><span class="line"><span class="class">| <span class="title">enum</span> <span class="title">X</span>           | <span class="title">C</span>.<span class="title">enum_X</span>          |</span></span><br></pre></td></tr></table></figure><h2 id="string-conversion-between-C-and-Go"><a href="#string-conversion-between-C-and-Go" class="headerlink" title="string conversion between C and Go"></a>string conversion between C and Go</h2><p>Unlike Go, C doesn’t have an explicit string type. Strings in C are represented by a zero-terminated array of chars. Conversion between Go and C strings is done with the C.CString, C.GoString, and C.GoStringN functions. These conversions make a copy of the string data.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Go string to C string</span></span><br><span class="line"><span class="comment">// The C string is allocated in the C heap using malloc.</span></span><br><span class="line"><span class="comment">// It is the caller's responsibility to arrange for it to be</span></span><br><span class="line"><span class="comment">// freed, such as by calling C.free (be sure to include stdlib.h if C.free is needed).</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">C</span>.<span class="title">CString</span><span class="params">(<span class="keyword">string</span>)</span> *<span class="title">C</span>.<span class="title">char</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">// <span class="title">Go</span> []<span class="title">byte</span> <span class="title">slice</span> <span class="title">to</span> <span class="title">C</span> <span class="title">array</span></span></span><br><span class="line"><span class="function">// <span class="title">The</span> <span class="title">C</span> <span class="title">array</span> <span class="title">is</span> <span class="title">allocated</span> <span class="title">in</span> <span class="title">the</span> <span class="title">C</span> <span class="title">heap</span> <span class="title">using</span> <span class="title">malloc</span>.</span></span><br><span class="line"><span class="function">// <span class="title">It</span> <span class="title">is</span> <span class="title">the</span> <span class="title">caller</span>'<span class="title">s</span> <span class="title">responsibility</span> <span class="title">to</span> <span class="title">arrange</span> <span class="title">for</span> <span class="title">it</span> <span class="title">to</span> <span class="title">be</span></span></span><br><span class="line"><span class="function">// <span class="title">freed</span>, <span class="title">such</span> <span class="title">as</span> <span class="title">by</span> <span class="title">calling</span> <span class="title">C</span>.<span class="title">free</span> <span class="params">(be sure to include stdlib.h <span class="keyword">if</span> C.free is needed)</span>.</span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">C</span>.<span class="title">CBytes</span><span class="params">([]<span class="keyword">byte</span>)</span> <span class="title">unsafe</span>.<span class="title">Pointer</span></span></span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// C string to Go string</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">C</span>.<span class="title">GoString</span><span class="params">(*C.char)</span> <span class="title">string</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">// <span class="title">C</span> <span class="title">data</span> <span class="title">with</span> <span class="title">explicit</span> <span class="title">length</span> <span class="title">to</span> <span class="title">Go</span> <span class="title">string</span></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">C</span>.<span class="title">GoStringN</span><span class="params">(*C.char, C.<span class="keyword">int</span>)</span> <span class="title">string</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">// <span class="title">C</span> <span class="title">data</span> <span class="title">with</span> <span class="title">explicit</span> <span class="title">length</span> <span class="title">to</span> <span class="title">Go</span> []<span class="title">byte</span></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="title">C</span>.<span class="title">GoBytes</span><span class="params">(unsafePinter, C.<span class="keyword">int</span>)</span> []<span class="title">byte</span></span></span><br></pre></td></tr></table></figure><h2 id="memory-management"><a href="#memory-management" class="headerlink" title="memory management"></a>memory management</h2><p>Memory allocations made by C code are not known to Go’s memory manager. When you create a C string with C.CString (or any C memory allocation) you must remember to free the memory when you’re done with it by calling C.free.</p><p>The call to C.CString returns a pointer to the start of the char array, so before the function exits we convert it to an unsafe.Pointer and release the memory allocation with C.free. A common idiom in cgo programs is to defer the free immediately after allocating (especially when the code that follows is more complex than a single function call), as in this rewrite of Print:</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Print</span><span class="params">(s <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    cs := C.CString(s)</span><br><span class="line">    <span class="keyword">defer</span> C.free(unsafe.Pointer(cs))</span><br><span class="line">    C.fputs(cs, (*C.FILE)(C.stdout))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p> A standard way to do this follows.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include &lt;stdlib.h&gt;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"C"</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">"unsafe"</span></span><br><span class="line">...</span><br><span class="line">    <span class="keyword">var</span> cmsg *C.char = C.CString(<span class="string">"hi"</span>)</span><br><span class="line">    <span class="keyword">defer</span> C.free(unsafe.Pointer(cmsg))</span><br><span class="line">    <span class="comment">// do something with the C string</span></span><br></pre></td></tr></table></figure><h2 id="handle-C-return-error-in-Go"><a href="#handle-C-return-error-in-Go" class="headerlink" title="handle C return error in Go"></a>handle C return error in Go</h2><p>Any C function (even void functions) may be called in a multiple assigned context to retrieve both the return value (if any) and the C errno variable as an error (use _ to skip the result value if the function returns void). For example.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">The sqrt() function compute the non-negative square root of x</span></span><br><span class="line"><span class="comment">sqrt(-0) returns -0</span></span><br><span class="line"><span class="comment">sqrt(x) returns a NaN and generates a domain error for x &lt; 0</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;math.h&gt;</span></span></span><br><span class="line"><span class="keyword">double</span></span><br><span class="line"><span class="built_in">sqrt</span>(<span class="keyword">double</span> x);</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">n, err := C.sqrt(<span class="number">-1</span>)</span><br><span class="line">_, err = C.voidFunc()</span><br></pre></td></tr></table></figure><h2 id="call-Go-code-in-C-code"><a href="#call-Go-code-in-C-code" class="headerlink" title="call Go code in C code"></a>call Go code in C code</h2><p>Using //export in a file places a restriction on the preamble: since it is copied into two different C. Output files, it must not contain any definitions, only declarations.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//export MyFunction</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">MyFunction</span><span class="params">(arg1, arg2 <span class="keyword">int</span>, arg3 <span class="keyword">string</span>)</span> <span class="title">int64</span></span> &#123;...&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//export MyFunction2</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">MyFunction2</span><span class="params">(arg1, arg2 <span class="keyword">int</span>, arg3 <span class="keyword">string</span>)</span> <span class="params">(<span class="keyword">int64</span>, *C.char)</span></span> &#123;...&#125;</span><br></pre></td></tr></table></figure><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">extern</span> int64 <span class="title">MyFunction</span><span class="params">(<span class="keyword">int</span> arg1, <span class="keyword">int</span> arg2, GoString arg3)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">extern</span> struct MyFunction2_return <span class="title">MyFunction2</span><span class="params">(<span class="keyword">int</span> arg1, <span class="keyword">int</span> arg2, GoString arg3)</span></span>;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;cgo is an amazing technology which allows Go programs to interoperate with C libraries. Given a Go source file written with some special 
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Trie</title>
-    <link href="https://oceanoverflow.github.io/2018/06/25/Trie/"/>
-    <id>https://oceanoverflow.github.io/2018/06/25/Trie/</id>
-    <published>2018-06-25T14:25:54.000Z</published>
-    <updated>2018-06-26T08:47:30.860Z</updated>
-    
-    <content type="html"><![CDATA[<p>假设我们要实现一个类似于有道词典这样的字典，开始时使用哈希表来存储键值对，后来在实现前缀搜索，模糊匹配等相关功能时，发现使用哈希表作为底层存储的数据结构有一个致命的缺点，基于哈希表的前缀搜索，模糊匹配实现难度非常之大，所以决定换一种数据结构来存储数据。下面我们来介绍一下 <code>Trie</code> 树， <code>Trie</code> 树也叫字典树，它非常适合我们上面说的场景，作为一种树形结构，还经常被用于统计，排序和保存大量的字符串等场景。</p><p><img src="https://cdn-images-1.medium.com/max/1600/1*f89l46VKjKPgnecqOw4V_w.png" alt="trie"></p><h2 id="data-structure"><a href="#data-structure" class="headerlink" title="data structure"></a>data structure</h2><p><code>Trie</code> 是一棵R叉树，可以用于保存大量的字符串，每棵树都有一个根节点（ <code>root</code> ）。非叶节点存储一个 <code>rune</code> ，除了指向父节点的指针 <code>parent</code> 之外，并还包含一系列子节点 <code>children</code> ，使用 <code>map</code> 来存储。叶节点标志着一个字符串的结束，其 <code>term</code> 标记为 <code>true</code> ，叶节点中还可以存储一些元数据（ <code>meta</code> ），来表示该字符串的含义。从根节点开始一直到叶节点就可以形成一个完整的字符串。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Node <span class="keyword">struct</span> &#123;</span><br><span class="line">    val      <span class="keyword">rune</span></span><br><span class="line">    term     <span class="keyword">bool</span></span><br><span class="line">    depth    <span class="keyword">int</span></span><br><span class="line">    meta     <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">    parent   *Node</span><br><span class="line">    children <span class="keyword">map</span>[<span class="keyword">rune</span>]*Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Trie <span class="keyword">struct</span> &#123;</span><br><span class="line">    root *Node</span><br><span class="line">    size <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">()</span> *<span class="title">Trie</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> &amp;Trie&#123;</span><br><span class="line">        root: &amp;Node&#123;depth: <span class="number">0</span>, children: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">rune</span>]*Node)&#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="helper-function"><a href="#helper-function" class="headerlink" title="helper function"></a>helper function</h2><p>为了方便后面的搜索操作，我们需要实现两个 <code>helper function</code> ，第一个就是计算一个字符串的掩码，例如对 <code>apple</code> 计算掩码时，分别对’a’，’p’，’p’，’l’，’e’ 这几个 <code>rune</code> 进行位运算，最后返回一个 <code>uint64</code> ，该掩码在搜索中起着非常重要的作用，因为每个节点都会存储一个掩码（ <code>mask</code> ），我们可以利用该掩码判断该节点及后续字节点存储了什么字符。<code>findNode</code> 方法帮助我们搜索 <code>runes</code> 字符数组中最后一个字符在树中对应的节点。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">maskruneslice</span><span class="params">(rs []<span class="keyword">rune</span>)</span> <span class="title">uint64</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> m <span class="keyword">uint64</span></span><br><span class="line">    <span class="keyword">for</span> _, r := <span class="keyword">range</span> rs &#123;</span><br><span class="line">        m |= <span class="keyword">uint64</span>(<span class="number">1</span>) &lt;&lt; <span class="keyword">uint64</span>(r-<span class="string">'a'</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> m</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">findNode</span><span class="params">(node *Node, runes []<span class="keyword">rune</span>)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(runes) == <span class="number">0</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> node</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    n, ok := node.Children()[runes[<span class="number">0</span>]]</span><br><span class="line">    <span class="keyword">if</span> !ok &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> nrunes []<span class="keyword">rune</span></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(runes) &gt; <span class="number">1</span> &#123;</span><br><span class="line">        nrunes = runes[<span class="number">1</span>:]</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        nrunes = runes[<span class="number">0</span>:<span class="number">0</span>]</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> findNode(n, nrunes)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Basic-Operation"><a href="#Basic-Operation" class="headerlink" title="Basic Operation"></a>Basic Operation</h2><p><code>Trie</code> 树的基本操作有三个，<code>Add</code> ，<code>Find</code> 和 <code>Del</code> 。</p><p><code>Add</code> 方法将 <code>key</code> 字符串加入到树中。对于每一个要加入树中的字符串中的 <code>rune</code> ， 我们构造一个节点，如果相应的 <code>rune</code> 已经存在，此时只需要更新其 <code>mask</code> 值，如果该 <code>rune</code> 不存在，则构建一个中间节点 <code>node = node.NewChild(r, bitmask, nil, false)</code> ，在所有中间节点都构建完毕之后，我们构建一个叶节点结束 <code>Add</code> 操作，叶节点的 <code>val</code> 值设为 <code>nul</code> ，<code>term</code> 为 <code>true</code> ，并存储相应的元数据 <code>meta</code> 。 </p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> nul = <span class="number">0x0</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Add</span><span class="params">(key <span class="keyword">string</span>, meta <span class="keyword">interface</span>)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    t.size++</span><br><span class="line">    runes := []<span class="keyword">rune</span>(key)</span><br><span class="line">    bitmask := maskruneslice(runes)</span><br><span class="line">    node := t.root</span><br><span class="line">    node.mask |= bitmask</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> runes &#123;</span><br><span class="line">        r := runes[i]</span><br><span class="line">        bitmask := maskruneslice(runes[i:])</span><br><span class="line">        <span class="keyword">if</span> n, ok := node.children[r]; ok &#123;</span><br><span class="line">            node = n</span><br><span class="line">            node.mask |= bitmask</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            node = node.NewChild(r, bitmask, <span class="literal">nil</span>, <span class="literal">false</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    node = node.NewChild(nul, <span class="number">0</span>, meta, <span class="literal">true</span>)</span><br><span class="line">    <span class="keyword">return</span> node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">NewChild</span><span class="params">(val <span class="keyword">rune</span>, bitmask <span class="keyword">uint64</span>, meta <span class="keyword">interface</span>&#123;&#125;, term <span class="keyword">bool</span>)</span> *<span class="title">Node</span></span> &#123;</span><br><span class="line">    node := &amp;Node&#123;</span><br><span class="line">        val: val,</span><br><span class="line">        bitmask: bitmask,</span><br><span class="line">        term: term,</span><br><span class="line">        meta: meta,</span><br><span class="line">        parent: n,</span><br><span class="line">        children: <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">rune</span>]*Node),</span><br><span class="line">        depth: n.depth + <span class="number">1</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    n.children[val] = node</span><br><span class="line">    n.mask |= bitmask</span><br><span class="line">    <span class="keyword">return</span> node</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>Find</code> 方法判断一个特定的字符串是否出现在该树中，我们先通过 <code>findNode</code> 找到相应的 <code>node</code> ，<code>Find</code> 方法用于查找一个完整的字符串，例如我们要查找 <code>app</code> ，但树中只有 <code>apple</code> 这个字符串，所以 <code>findNode</code> 调用时应该返回说不存在 <code>app</code> 这个字符串。当查找 <code>app</code> 这个字符串时，<code>findNode</code> 方法会返回最后一个 <code>p</code> 对应的节点，但这并不说明 <code>app</code> 存在于树中，我们还需要判断该节点是否为叶节点 <code>node.term == true</code> ，如果不是叶节点，则返回 <code>nil</code> 。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Find</span><span class="params">(key <span class="keyword">string</span>)</span> <span class="params">(*Node, <span class="keyword">bool</span>)</span></span> &#123;</span><br><span class="line">    node := findNode(t.Root(), []<span class="keyword">rune</span>(key))</span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, <span class="literal">false</span></span><br><span class="line">    &#125;</span><br><span class="line">    node, ok := node.Children()[nul]</span><br><span class="line">    <span class="keyword">if</span> !ok || !node.term &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, <span class="literal">false</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> node, <span class="literal">true</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>Remove</code> 方法同样通过 <code>findNode</code> 方法找到相应的节点，然后从该节点向根节点的方向依次删除相应的 <code>rune</code> ，主要目的是为了更新每个中间节点的<code>mask</code> 值。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Remove</span><span class="params">(key <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> (</span><br><span class="line">        i <span class="keyword">int</span></span><br><span class="line">        rs = []<span class="keyword">rune</span>(key)</span><br><span class="line">        node = findNode(t.Root(), []<span class="keyword">rune</span>(key))</span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    t.size--</span><br><span class="line">    <span class="keyword">for</span> n := node.Parent(); p != <span class="literal">nil</span>; n = n.Parent() &#123;</span><br><span class="line">        i++</span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(n.Children()) &gt; <span class="number">1</span> &#123;</span><br><span class="line">            r := rs[<span class="built_in">len</span>(rs)-i]</span><br><span class="line">            n.RemoveChild(r)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *Node)</span> <span class="title">RemoveChild</span><span class="params">(r <span class="keyword">rune</span>)</span></span> &#123;</span><br><span class="line">    <span class="built_in">delete</span>(n.children, r)</span><br><span class="line">    <span class="keyword">for</span> nd := n.parent; nd != <span class="literal">nil</span>; nd = nd.parent &#123;</span><br><span class="line">        nd.mask ^= nd.mask</span><br><span class="line">        nd.mask |= <span class="keyword">uint64</span>(<span class="number">1</span>) &lt;&lt; <span class="keyword">uint64</span>(nd.val - <span class="string">'a'</span>)</span><br><span class="line">        <span class="keyword">for</span> _, c := <span class="keyword">range</span> nd.children &#123;</span><br><span class="line">            nd.mask |= c.mask</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Collect"><a href="#Collect" class="headerlink" title="Collect"></a>Collect</h2><p>有时候我们搜索单词的时候只记得该单词的前缀，例如我们要搜索 <code>append</code> 这个单词，但是我们只记得 <code>app</code> 这个前缀，我们可以使用 <code>collect</code> 方法帮我们收集所有 <code>app</code> 开头的单词，换句话说就是特定节点下面所有可能的叶节点的集合，开始收集时我们构造一个队列，该队列中仅有 <code>node</code> 一个节点，然后使用广度优先搜索的方式（层序遍历），首先将队列中的第一个节点出队，然后将该节点所有的子节点加入该队列中，如果节点为叶节点，则从该叶节点开始一直向上遍历到根节点的下一层节点（ <code>p.depth == 1</code> ），直到完成所有单词的收集为止。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">collect</span><span class="params">(node *Node)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> (</span><br><span class="line">        keys []<span class="keyword">string</span></span><br><span class="line">        n    *Node</span><br><span class="line">        i    <span class="keyword">int</span></span><br><span class="line">    )</span><br><span class="line">    nodes := []*Node&#123;node&#125;</span><br><span class="line">    <span class="keyword">for</span> l := <span class="built_in">len</span>(nodes); l != <span class="number">0</span>; l = <span class="built_in">len</span>(nodes) &#123;</span><br><span class="line">        i := l - <span class="number">1</span></span><br><span class="line">        n = nodes[i]</span><br><span class="line">        nodes = nodes[:i]</span><br><span class="line">        <span class="keyword">for</span> _, c := <span class="keyword">range</span> n.children &#123;</span><br><span class="line">            nodes = <span class="built_in">append</span>(nodes, c)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> n.term &#123;</span><br><span class="line">            word := <span class="string">""</span></span><br><span class="line">            <span class="keyword">for</span> p := n.parent; p.depth != <span class="number">0</span>; p = p.parent &#123;</span><br><span class="line">                word = <span class="keyword">string</span>(p.val) + word</span><br><span class="line">            &#125;</span><br><span class="line">            keys = <span class="built_in">append</span>(keys, word)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> keys</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Fuzzy-Collect"><a href="#Fuzzy-Collect" class="headerlink" title="Fuzzy Collect"></a>Fuzzy Collect</h2><p>除了比较准确的前缀匹配之外，有时候我们可能还需要模糊匹配，再举 <code>append</code> 这个单词为例子，我们可能只记得这个单词包含了 <code>apd</code> 这样的模式，使用 <code>Trie</code> 树我们可以非常轻松地实现模糊匹配功能，<code>fuzzycollect</code> 同样利用层序遍历，在每一个循环开始时，对队列中的第一个节点进行出队操作，如果相应的掩码不包含在正在遍历的节点中 <code>(p.node.mask &amp; m) != m</code> ，说明其后面的节点中不包含所有 <code>partial</code> 中包含的 <code>rune</code> 值，直接进入下一个循环 ，如果 <code>p.idx == len(partial)</code> ，说明我们找到了与 <code>partial</code> 相匹配的一个单词，此时进行 <code>collect</code> 操作 。最后同样需要将该节点的子节点加入队列中以进行下一轮的层序遍历。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> potentialSubtree <span class="keyword">struct</span> &#123;</span><br><span class="line">    idx <span class="keyword">int</span></span><br><span class="line">    node *Node</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">fuzzycollect</span><span class="params">(node *Node, partial []<span class="keyword">rune</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> (</span><br><span class="line">        m    <span class="keyword">uint64</span></span><br><span class="line">        i    <span class="keyword">int</span></span><br><span class="line">        p    potentialSubtree</span><br><span class="line">        keys []<span class="keyword">string</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line">    potential := []potentialSubtree&#123;potentialSubtree&#123;<span class="number">0</span>, node&#125;&#125;</span><br><span class="line">    <span class="keyword">for</span> l := <span class="built_in">len</span>(potential); l &gt; <span class="number">0</span>; l = <span class="built_in">len</span>(potential) &#123;</span><br><span class="line">        i := l - <span class="number">1</span></span><br><span class="line">        p = potential[i]</span><br><span class="line">        potential = potential[:i]</span><br><span class="line">        m = maskruneslice(partial[p.idx:])</span><br><span class="line">        <span class="keyword">if</span> (p.node.mask &amp; m) != m &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> p.node.val == partial[p.idx] &#123;</span><br><span class="line">            p.idx++</span><br><span class="line">            <span class="keyword">if</span> p.idx == <span class="built_in">len</span>(partial) &#123;</span><br><span class="line">                keys = <span class="built_in">append</span>(keys, collect(p.node)...)</span><br><span class="line">                <span class="keyword">continue</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> _, c := <span class="keyword">range</span> p.node.children &#123;</span><br><span class="line">            potential = <span class="built_in">append</span>(potential, potentialSubtree&#123;node: c, idx: p.idx&#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> keys</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="search"><a href="#search" class="headerlink" title="search"></a>search</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ByKeys []<span class="keyword">string</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a ByKeys)</span> <span class="title">Len</span><span class="params">()</span> <span class="title">int</span></span>           &#123; <span class="keyword">return</span> <span class="built_in">len</span>(a) &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a ByKeys)</span> <span class="title">Swap</span><span class="params">(i, j <span class="keyword">int</span>)</span></span>      &#123; a[i], a[j] = a[j], a[i] &#125;</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a ByKeys)</span> <span class="title">Less</span><span class="params">(i, j <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123; <span class="keyword">return</span> <span class="built_in">len</span>(a[i]) &lt; <span class="built_in">len</span>(a[j]) &#125;</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">HasKeysWithPrefix</span><span class="params">(key <span class="keyword">string</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    node := findNode(t.Root(), []<span class="keyword">rune</span>(key))</span><br><span class="line">    <span class="keyword">return</span> node != <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t Trie)</span> <span class="title">FuzzySearch</span><span class="params">(pre <span class="keyword">string</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    keys := fuzzycollect(t.Root(), []<span class="keyword">rune</span>(pre))</span><br><span class="line">    sort.Sort(ByKeys(keys))</span><br><span class="line">    <span class="keyword">return</span> keys</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t Trie)</span> <span class="title">PrefixSearch</span><span class="params">(pre <span class="keyword">string</span>)</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    node := findNode(t.Root(), []<span class="keyword">rune</span>(pre))</span><br><span class="line">    <span class="keyword">if</span> node == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> collect(node)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(t *Trie)</span> <span class="title">Keys</span><span class="params">()</span> []<span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> t.PrefixSearch(<span class="string">""</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;假设我们要实现一个类似于有道词典这样的字典，开始时使用哈希表来存储键值对，后来在实现前缀搜索，模糊匹配等相关功能时，发现使用哈希表作为底层存储的数据结构有一个致命的缺点，基于哈希表的前缀搜索，模糊匹配实现难度非常之大，所以决定换一种数据结构来存储数据。下面我们来介绍一下 &lt;
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Page Views</title>
-    <link href="https://oceanoverflow.github.io/2018/06/23/PageViews/"/>
-    <id>https://oceanoverflow.github.io/2018/06/23/PageViews/</id>
-    <published>2018-06-23T15:08:44.000Z</published>
-    <updated>2018-06-26T08:48:33.155Z</updated>
-    
-    <content type="html"><![CDATA[<p>统计网站的页面浏览次数（ <code>Page Views</code> ）是分析网站的重要参数之一。由于多个用户发送的请求很可能是同时进行的，所以这里涉及到并发操作时对变量的保护问题。</p><h2 id="mutex"><a href="#mutex" class="headerlink" title="mutex"></a>mutex</h2><p>在统计页面浏览次数时，我们可以使用一个变量 <code>pageView</code> 来表示页面的浏览次数，并用一个 <code>mutex</code> 锁来保护变量存取。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    pageView <span class="keyword">int</span></span><br><span class="line">    mutex sync.Mutex</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    mutex.Lock()</span><br><span class="line">    pageView++</span><br><span class="line">    mutex.Unlock()</span><br><span class="line">    fmt.Fprintf(w, <span class="string">"&lt;h1&gt;%v&lt;/h1&gt;"</span>, pageView)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    http.HandleFunc(<span class="string">"/"</span>, handler)</span><br><span class="line">    http.ListenAndServe(<span class="string">"localhost:8080"</span>, <span class="literal">nil</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="channel"><a href="#channel" class="headerlink" title="channel"></a>channel</h2><p>除了使用互斥锁来保护变量之外，我们来可以使用 <code>golang</code> 中特有的<code>unbuffered channel</code> 来获取页面浏览次数，我们在 <code>main</code> 函数中起一个 <code>goroutine</code> 来生产递增的 <code>nextID</code> ，每个 <code>nextID &lt;- i</code> 发送操作均会阻塞直到一个 <code>goroutine</code> 启动时通过 <code>&lt;-nextID</code> 来接收，这里因为使用了<code>unbuffered channel</code> ，所以保证了整个过程的原子性。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> nextID = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">int</span>)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handler</span><span class="params">(w http.ResponseWriter, r *http.Request)</span></span> &#123;</span><br><span class="line">    fmt.Fprintf(w, <span class="string">"&lt;h1&gt;%v&lt;/h1&gt;"</span>, &lt;-nextID)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    http.HandleFunc(“/”, handler)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">for</span> i := <span class="number">0</span>; ; i++ &#123;</span><br><span class="line">            nextID &lt;- i</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">    http.ListenAndServe(<span class="string">"localhost:8080"</span>, <span class="literal">nil</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;统计网站的页面浏览次数（ &lt;code&gt;Page Views&lt;/code&gt; ）是分析网站的重要参数之一。由于多个用户发送的请求很可能是同时进行的，所以这里涉及到并发操作时对变量的保护问题。&lt;/p&gt;
-&lt;h2 id=&quot;mutex&quot;&gt;&lt;a href=&quot;#mutex&quot; class=&quot;
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Skip List</title>
-    <link href="https://oceanoverflow.github.io/2018/06/21/SkipList/"/>
-    <id>https://oceanoverflow.github.io/2018/06/21/SkipList/</id>
-    <published>2018-06-21T12:53:24.000Z</published>
-    <updated>2018-06-26T08:47:54.101Z</updated>
-    
-    <content type="html"><![CDATA[<p>跳表是一种建立在普通链表基础上的概率数据结构，为什么说是概率呢，因为跳表会根据概率在原始链表上构建后续的链表层，每个额外的链表层包含的元素数量更少，但每个元素都是原始链表中已经拥有的，这使得跳表在搜索时不用像链表一样一个一个元素的寻找，而是跳过一些元素，这就是跳表名字的由来，正是因为略过了一些元素，所以大大增加了搜索的速度。</p><p><img src="https://ds055uzetaobb.cloudfront.net/image_optimizer/968e3d82130f4bfa9a1574b1537c840a1787c919.png" alt="SkipList"></p><p>利用跳表可以构建 <code>kv</code> 数据库的索引，例如 <code>leveldb</code> 中的索引就是利用跳表来构建的，跳表相对其他索引数据结构例如红黑树，b树等有实现相对简单，但查询效率高的特点，其空间复杂度为 <code>O(n)</code> ，时间复杂度为 <code>O(logn)</code> 。</p><h2 id="跳表的组成元素"><a href="#跳表的组成元素" class="headerlink" title="跳表的组成元素"></a>跳表的组成元素</h2><p>与链表类似，跳表也是由一系列节点组成，每个节点我们用 <code>Element</code> 结构体表示，每个节点会存储一个 <code>kv</code> 对， 除了 <code>kv</code> 对之外，还包含一个 <code>elementNode</code> 结构体，该结构体其实就是一个指针数组，在单向链表中，指针有且只有一个，在跳表中，可以存在多个指向后续节点的指针，用于遍历时加速跳跃使用，这个指针数组是跳表的核心，使用 <code>next []*Element</code> 表示。</p><p>在表示完跳表的基本元素之后，我们还需要考虑一个完整跳表的数据结构，类与普通的链表类似，我们需要一个跳表头，这里用 <code>elementNode</code> 表示，由于跳表在构建时新元素的高度是不确定的，所以我们需要一个 <code>rand.Source</code> 帮助我们决定元素的高度，并限制高度小于最高高度 <code>maxLevel</code> ，这里整个跳表的质量与随机性有相当大的关系，构建得到的跳表随机性越强，搜索速度越快。</p><p>还有我们需要 <code>prevNodesCache []*elementNode</code> 来存储被查找节点的之前的节点，这个刚开始理解起来有一点复杂，因为被查找节点每一层的前一个元素都是不同的，每一个之前的元素可以用一个 <code>*elementNode</code> 来表示，由于每个节点可能存在多层指针，所以这里用一个数组来表示 <code>[]*elementNode</code> 。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> elementNode <span class="keyword">struct</span> &#123;</span><br><span class="line">    next []*Element</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Element <span class="keyword">struct</span> &#123;</span><br><span class="line">    elementNode</span><br><span class="line">    key   <span class="keyword">float64</span></span><br><span class="line">    value <span class="keyword">interface</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> SkipList <span class="keyword">struct</span> &#123;</span><br><span class="line">    elementNode</span><br><span class="line">    maxLevel       <span class="keyword">int</span></span><br><span class="line">    Length         <span class="keyword">int</span></span><br><span class="line">    randSource     rand.Source</span><br><span class="line">    mutex          sync.RWMutex</span><br><span class="line">    prevNodesCache []*elementNode</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(maxLevel <span class="keyword">int</span>)</span> *<span class="title">SkipList</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> maxLevel &lt; <span class="number">1</span> || maxLevel &gt; <span class="number">64</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"max level should be less than 64 and greater than 1"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> &amp;SkipList&#123;</span><br><span class="line">        elementNode: elementNode&#123;next: <span class="built_in">make</span>([]*Element, maxLevel)&#125;,</span><br><span class="line">        maxLevel: maxLevel,</span><br><span class="line">        randSource: rand.New(rand.NewSource(time.Now().UnixNano())),</span><br><span class="line">        prevNodesCache: <span class="built_in">make</span>([]*elementNode, maxLevel),</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="跳表的基本操作"><a href="#跳表的基本操作" class="headerlink" title="跳表的基本操作"></a>跳表的基本操作</h2><p>在插入和删除特定节点时，我们需要获取该节点之前的所有元素节点， <code>getPrevElementNodes</code> 从跳表的头节点（ <code>list.elementNode</code> ）出发，并从最高层开始，确定 <code>key</code> 对应的元素在该层对应的前一个<code>elementNode</code> ，然后存储在 <code>prevNodesCache</code> 中（ <code>prevs[i] = prev</code> ），这样一直查找直到最底层。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">getPrevElementNodes</span><span class="params">(key <span class="keyword">float64</span>)</span> []*<span class="title">elementNode</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> prev *elementNode = &amp;list.elementNode</span><br><span class="line">    <span class="keyword">var</span> next *Element</span><br><span class="line"></span><br><span class="line">    prevs := list.prevNodesCache</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := list.maxLevel - <span class="number">1</span>; i &gt;=<span class="number">0</span>; i-- &#123;</span><br><span class="line">        next = prev.next[i]</span><br><span class="line">        <span class="keyword">for</span> next != <span class="literal">nil</span> &amp;&amp; key &gt; next.key &#123;</span><br><span class="line">            prev = &amp;next.elementNode</span><br><span class="line">            next = next.next[i]</span><br><span class="line">        &#125;</span><br><span class="line">        prevs[i] = prev</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> prevs</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">randLevel</span><span class="params">()</span> <span class="params">(level <span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> list.randSource.Intn(list.maxLevel)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Get"><a href="#Get" class="headerlink" title="Get"></a>Get</h3><p><code>Get</code> 方法的本质就是一个走楼梯的过程，但是这里每个阶梯的高度和宽度并非确定，开始从楼梯的最高层出发（ <code>i := list.maxLevel - 1</code> ），每次对前方同一层的阶梯（ <code>next = prev.next[i]</code> ）进行试探，如果前方阶梯不为空（ <code>next != nil</code> ），且符合特定要求（ <code>key &gt; next.key</code> ）则继续在这一层走，否则直接进入下一层（ <code>i--</code> ），直到找到为止，最后判断此阶梯不为空（ <code>next != nil</code> ）且该阶梯保存的值和要找的值相同时，返回该阶梯。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">Get</span><span class="params">(key <span class="keyword">float64</span>)</span> *<span class="title">Element</span></span> &#123;</span><br><span class="line">    list.mutex.Lock()</span><br><span class="line">    <span class="keyword">defer</span> list.mutex.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> prev *elementNode = &amp;list.elementNode</span><br><span class="line">    <span class="keyword">var</span> next *Element</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := list.maxLevel - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i-- &#123;</span><br><span class="line">        next = prev.next[i]</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> next != <span class="literal">nil</span> &amp;&amp; key &gt; next.key &#123;</span><br><span class="line">            prev = &amp;next.elementNode</span><br><span class="line">            next = next.next[i]</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> next != <span class="literal">nil</span> &amp;&amp; next.key &lt;= key &#123;</span><br><span class="line">        <span class="keyword">return</span> next</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p><code>Set</code> 方法需要使用之前的 <code>getPrevElementNodes</code> 来获取对应 <code>key</code> 之前的元素，如果该元素对应的 <code>key</code> 已经存在，则改变其 <code>value</code> 之后返回，如果不存在，则构建一个新的节点，然后将自己之前的节点的指针和自己之后节点的指针相连，使其前节点指向自己，使自己指向后面的节点。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">Set</span><span class="params">(key <span class="keyword">float64</span>, value <span class="keyword">interface</span>&#123;&#125;)</span> *<span class="title">Element</span></span> &#123;</span><br><span class="line">    list.mutex.Lock()</span><br><span class="line">    <span class="keyword">defer</span> list.mutex.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> element *Element</span><br><span class="line">    prevs := list.getPrevElementNodes(key)</span><br><span class="line">    <span class="keyword">if</span> element = prevs[<span class="number">0</span>].next[<span class="number">0</span>]; element != <span class="literal">nil</span> &amp;&amp; element.key &lt;= key &#123;</span><br><span class="line">        element.value = value</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    element = &amp;Element &#123;</span><br><span class="line">        elementNode: elementNode&#123;</span><br><span class="line">            next: <span class="built_in">make</span>([]*Element, list.randLevel()),</span><br><span class="line">            key: key,</span><br><span class="line">            value: value,</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> element.next &#123;</span><br><span class="line">        element.next[i] = prevs[i].next[i]</span><br><span class="line">        prevs[i].next[i] = element</span><br><span class="line">    &#125;</span><br><span class="line">    list.Length++</span><br><span class="line">    <span class="keyword">return</span> element</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Remove"><a href="#Remove" class="headerlink" title="Remove"></a>Remove</h3><p><code>Remove</code> 方法也需要使用 <code>getPrevElementNodes</code> 方法，使自己前面的节点不指向该元素而是指向该元素后面的元素。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(list *SkipList)</span> <span class="title">Remove</span><span class="params">(key <span class="keyword">float64</span>)</span> *<span class="title">Element</span></span> &#123;</span><br><span class="line">    list.mutex.Lock()</span><br><span class="line">    <span class="keyword">defer</span> list.mutex.Unlock()</span><br><span class="line">    prevs := list.getPrevElementNodes(key)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> element := prevs[<span class="number">0</span>].next[<span class="number">0</span>]; element != <span class="literal">nil</span> &amp;&amp; element.key &lt;= key &#123;</span><br><span class="line">        <span class="keyword">for</span> k, v := <span class="keyword">range</span> element.next &#123;</span><br><span class="line">            prevs[k].next[k] = v</span><br><span class="line">        &#125;</span><br><span class="line">        list.Length--</span><br><span class="line">        <span class="keyword">return</span> element</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;跳表是一种建立在普通链表基础上的概率数据结构，为什么说是概率呢，因为跳表会根据概率在原始链表上构建后续的链表层，每个额外的链表层包含的元素数量更少，但每个元素都是原始链表中已经拥有的，这使得跳表在搜索时不用像链表一样一个一个元素的寻找，而是跳过一些元素，这就是跳表名字的由来
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>grep</title>
-    <link href="https://oceanoverflow.github.io/2018/06/20/grep/"/>
-    <id>https://oceanoverflow.github.io/2018/06/20/grep/</id>
-    <published>2018-06-20T06:07:24.000Z</published>
-    <updated>2018-06-26T08:45:51.416Z</updated>
-    
-    <content type="html"><![CDATA[<p>最近看到 <code>golang</code> 语法中一个非常有趣的基本组合 <code>chan chan</code> ，为了加深自己的理解，想多看几个使用案例，于是去 <code>$GOPATH</code> 下面的文件去找，但是一个个文件找肯定不现实，于是借助 <code>grep</code> 帮我们进行搜索，<code>grep</code> 的使用非常简单，但是如果在不了解 <code>grep</code> 使用的情况下，自己实现一个类似的搜索功能应该也不是很难，今天就让我们来看看 <code>grep</code> 的使用和 <code>golang</code> 版本的简单实现吧。</p><h2 id="usr-bin-grep"><a href="#usr-bin-grep" class="headerlink" title="/usr/bin/grep"></a>/usr/bin/grep</h2><p><code>grep</code> 命令的基本语法如下所示。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ grep <span class="string">'chan'</span> file</span><br><span class="line">$ grep <span class="string">'chan chan'</span> file1 file2</span><br><span class="line">$ grep [option] <span class="string">'chan chan'</span> file1 file2</span><br></pre></td></tr></table></figure><p>除了列出文件名之外，我们还可以使用通配符搜索当前目录中所有文件。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ grep <span class="string">'chan chan'</span> *</span><br></pre></td></tr></table></figure><h3 id="search-sub-directories-recursively-using-grep"><a href="#search-sub-directories-recursively-using-grep" class="headerlink" title="search sub directories recursively using grep"></a>search sub directories recursively using grep</h3><p>使用 <code>grep</code> 加上 <code>-r</code> 或者 <code>-R</code> 选项可以递归搜索当前目录下的所有文件。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ grep -r <span class="string">'chan chan'</span> *</span><br><span class="line">$ grep -R <span class="string">'chan chan'</span> *</span><br></pre></td></tr></table></figure><h3 id="examples"><a href="#examples" class="headerlink" title="examples"></a>examples</h3><p>例如，以下命令将会输出当前目录中所有文件及其所有子目录中包含单词 <code>chan chan</code>  的每一行。</p><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ grep -r <span class="string">'chan chan'</span> *</span><br></pre></td></tr></table></figure><h2 id="my-own-grep"><a href="#my-own-grep" class="headerlink" title="my own grep"></a>my own grep</h2><p>如果要自己实现，在不考虑性能的情况下， 只需要实现两个功能，一是文件夹的递归遍历，二就是模式匹配，下面我们实现一个最简单的 <code>grep</code> 。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> (</span><br><span class="line">    haystack = flag.String(<span class="string">"path"</span>, <span class="string">""</span>, <span class="string">"file path to search in"</span>)</span><br><span class="line">    needle = flag.String(<span class="string">"search"</span>, <span class="string">""</span>, <span class="string">"search string to look for"</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    flag.Parse()</span><br><span class="line">    fi, err := os.Stat(*haystack)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> fi.Mode().IsDir() &#123;</span><br><span class="line">        *haystack = strings.TrimRight(*haystack, <span class="string">"/"</span>) + <span class="string">"/"</span></span><br><span class="line">        dfs(*haystack, *needle)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        log.Fatal(<span class="string">"path must be a dir"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="depth-first-search"><a href="#depth-first-search" class="headerlink" title="depth first search"></a>depth first search</h3><p>我们利用深度优先搜索来遍历相关文件，如果当前对应的 <code>path</code> 为目录（ <code>file.Mode().IsDir()</code> ），则递归调用搜索方法，如果 <code>path</code> 为普通文件（ <code>file.Mode().IsRegular()</code> ），则利用下面的 <code>grep</code> 方法扫描该文件。直到所有文件均被遍历。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">dfs</span><span class="params">(path, search <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    files, err := ioutil.ReadDir(path)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> _, file := <span class="keyword">range</span> files &#123;</span><br><span class="line">        fullpath := path + file.Name(<span class="number">0</span></span><br><span class="line">        <span class="keyword">if</span> file.Mode().IsDir() &#123;</span><br><span class="line">            dfs(fullpath+<span class="string">"/"</span>, search)</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> file.Mode().IsRegular() &#123;</span><br><span class="line">            grep(fullpath, search)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="grep-individual-using-scanner"><a href="#grep-individual-using-scanner" class="headerlink" title="grep individual using scanner"></a>grep individual using scanner</h3><p>对于每一个 <code>fullpath</code> 对应的文件，我们利用 <code>bufio.NewScanner</code> 构建一个扫描仪，并进行逐行扫描，然后判断要搜索的文字（ <code>search</code> ）是否存在于该行中，如果存在（ <code>strings.Contains</code> ），则在命令行中输出。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">grep</span><span class="params">(fullpath, search <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">    f, err := os.Open(fullpath)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    scanner := bufio.NewScanner(f)</span><br><span class="line">    <span class="keyword">for</span> scanner.Scan() &#123;</span><br><span class="line">        line := scanner.Text()</span><br><span class="line">        <span class="keyword">if</span> strings.Contains(line, search) &#123;</span><br><span class="line">            fmt.Println(fullpath, <span class="string">" "</span>, line)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;最近看到 &lt;code&gt;golang&lt;/code&gt; 语法中一个非常有趣的基本组合 &lt;code&gt;chan chan&lt;/code&gt; ，为了加深自己的理解，想多看几个使用案例，于是去 &lt;code&gt;$GOPATH&lt;/code&gt; 下面的文件去找，但是一个个文件找肯定不现实，于是借助 &lt;
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Pipeline</title>
-    <link href="https://oceanoverflow.github.io/2018/06/19/Pipeline/"/>
-    <id>https://oceanoverflow.github.io/2018/06/19/Pipeline/</id>
-    <published>2018-06-19T08:39:47.000Z</published>
-    <updated>2018-06-26T08:48:31.242Z</updated>
-    
-    <content type="html"><![CDATA[<p><img src="http://insideenergy.org/wp-content/uploads/2017/05/DAPL-Pipeline-2-1170x775.jpg" alt="pipeline"></p><p>在介绍 <code>io.Pipe</code> 之前，我们先来看一段非常简单的代码，如果现在需要向服务器发送一个 <code>POST</code> 请求，按流程一步步来，首先构建一个消息结构体，然后将该结构体编码成 <code>json</code> 格式的数据，并将该数据暂时存储在 <code>buf</code> 中，最后利用 <code>http.Post</code> 发送该请求，轻松愉快。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> message <span class="keyword">struct</span> &#123;</span><br><span class="line">    Name <span class="keyword">string</span></span><br><span class="line">    Age  <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    m := &amp;message&#123;Name: <span class="string">"yiyangyi"</span>, Age: <span class="number">23</span>&#125;</span><br><span class="line">    <span class="keyword">var</span> buf bytes.Buffer</span><br><span class="line">    err := json.NewEncoder(&amp;buf).Encode(m)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    resp, err := http.Post(<span class="string">"example.com"</span>, <span class="string">"application/json"</span>, &amp;buf)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)     </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line">    </span><br><span class="line">    b, err := ioutil.ReadAll(resp.Body)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Println(<span class="keyword">string</span>(b))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>但是，上面的代码存在一个问题，就是我们需要分配一个缓存区（ <code>bytes.Buffer</code> ）存储编码后的数据，为了节省内存，能不能通过一个方法来避免此部分内存的分配呢，解决方法就是我们今天的主角——<code>io.Pipe</code> 。</p><p><code>io.Pipe</code> 执行后会得到一个 <code>PipeReader</code> 和 <code>PipeWriter</code> ，当程序向<code>PipeWriter</code> 中写入数据时，<code>PipeReader</code> 可以同步地收到这部分消息，根据这个特性，我们将 <code>PipeWriter</code> 代替 <code>bytes.Buffer</code> 作为参数 (它们同为 <code>io.Writer</code> ) 传入 <code>json.NewEncoder</code> 中，当我们 <code>Encode</code> 数据时，会直接向 <code>PipeWriter</code> 写入数据，此时 <code>Pipe</code> 的另一边，<code>PipeReader</code> 可以马上收到数据，利用 <code>io.Pipe</code> 我们就避免了中间非必要缓存的分配。</p><p>由于使用 <code>io.Pipe</code> 发送和接收数据是一个同步的过程 (类似于 <code>unbuffered channel</code> )，所以需要让发送和接收在两个 <code>goroutine</code> 中进行，如果它们存在于一个 <code>goroutine</code> 中，会导致程序死锁。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> message <span class="keyword">struct</span> &#123;</span><br><span class="line">    Name <span class="keyword">string</span></span><br><span class="line">    Age  <span class="keyword">int</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;       </span><br><span class="line">        m := &amp;message&#123;Name: <span class="string">"yiyangyi"</span>, Age: <span class="number">23</span>&#125;</span><br><span class="line">        err := json.NewEncoder(pw).Encode(m)</span><br><span class="line">        pw.CloseWithError(err)</span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    resp, err := http.Post(<span class="string">"example.com"</span>, <span class="string">"application/json"</span>, pr)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)     </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"></span><br><span class="line">    b, err := ioutil.ReadAll(resp.Body)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    fmt.Println(<span class="keyword">string</span>(b))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="io-TeeReader-amp-io-MultiReader-❤️-io-Pipe"><a href="#io-TeeReader-amp-io-MultiReader-❤️-io-Pipe" class="headerlink" title="io.TeeReader &amp; io.MultiReader  ❤️  io.Pipe"></a>io.TeeReader &amp; io.MultiReader  ❤️  io.Pipe</h2><p><code>io.Pipe</code> 经常与 <code>io.TeeReader</code> 和 <code>io.MultiReader</code> 一起使用，下面有两个这样的例子。</p><h3 id="io-Pipe-❤️-io-TeeReader"><a href="#io-Pipe-❤️-io-TeeReader" class="headerlink" title="io.Pipe ❤️ io.TeeReader"></a>io.Pipe ❤️ io.TeeReader</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tr  &lt;--- r -----&gt; pw ------ &gt; pr</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">upload</span><span class="params">(r io.Reader)</span></span> &#123;</span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line">    tr := io.TeeReader(r, pw)</span><br><span class="line"></span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">defer</span> <span class="built_in">close</span>(done)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> pw.Close()</span><br><span class="line">        uploadFile(tr)</span><br><span class="line">        done &lt;- <span class="literal">true</span></span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        webmr := transcode(pr)</span><br><span class="line">        uploadFile(webmr)</span><br><span class="line">        done &lt;- <span class="literal">true</span></span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> c := <span class="number">0</span>; c &lt; <span class="number">2</span>; c++ &#123;</span><br><span class="line">        &lt;-done</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="io-Pipe-❤️-io-MultiReader"><a href="#io-Pipe-❤️-io-MultiReader" class="headerlink" title="io.Pipe ❤️ io.MultiReader"></a>io.Pipe ❤️ io.MultiReader</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;- pr1 &lt;-----&gt; pw1 --\</span><br><span class="line"></span><br><span class="line">&lt;- pr2 &lt;-----&gt; pw2 ----</span><br><span class="line">                        &gt; multiwriter(pw1,pw2,pw3,pw4) &lt;----- r</span><br><span class="line">&lt;- pr3 &lt;-----&gt; pw3 ----</span><br><span class="line"></span><br><span class="line">&lt;- pr4 &lt;-----&gt; pw4 --/</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">TranscodeAll</span><span class="params">(r io.Reader)</span></span> &#123;</span><br><span class="line">    mp4R, mp4W   := io.Pipe()</span><br><span class="line">    oggR, oggW   := io.Pipe()</span><br><span class="line">    wavR, wavW   := io.Pipe()</span><br><span class="line">    webmR, webmW := io.Pipe()</span><br><span class="line"></span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">defer</span> <span class="built_in">close</span>(done)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> transcodeMP4(mp4R, done)</span><br><span class="line">    <span class="keyword">go</span> transcodeOgg(oggR, done)</span><br><span class="line">    <span class="keyword">go</span> transcodeWav(wavR, done)</span><br><span class="line">    <span class="keyword">go</span> transcodeWebM(webmR, done)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> mp4W.Close() </span><br><span class="line">        <span class="keyword">defer</span> oggW.Close()</span><br><span class="line">        <span class="keyword">defer</span> wavW.Close()</span><br><span class="line">        <span class="keyword">defer</span> webmW.Close()</span><br><span class="line"></span><br><span class="line">        mw := io.MultiWriter(mp4W, oggW, wavW, webmW)</span><br><span class="line">        io.Copy(mw, r)</span><br><span class="line">    &#125;()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> c := <span class="number">0</span>; c &lt; <span class="number">4</span>; c++ &#123;</span><br><span class="line">        &lt;-done</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;&lt;img src=&quot;http://insideenergy.org/wp-content/uploads/2017/05/DAPL-Pipeline-2-1170x775.jpg&quot; alt=&quot;pipeline&quot;&gt;&lt;/p&gt;
-&lt;p&gt;在介绍 &lt;code&gt;io.Pipe&lt;/code
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>imgcat</title>
-    <link href="https://oceanoverflow.github.io/2018/06/18/imgcat/"/>
-    <id>https://oceanoverflow.github.io/2018/06/18/imgcat/</id>
-    <published>2018-06-18T14:02:51.000Z</published>
-    <updated>2018-06-26T08:46:17.739Z</updated>
-    
-    <content type="html"><![CDATA[<p>在 <code>iTerm2</code> 中我们可以直接查看图片，是不是有点酷炫。</p><p><img src="https://www.iterm2.com/images/inline_image_sparky_demo.png" alt="imgcat"></p><p>为了使图片能够正确的展示，我们需要使数据满足特定的协议格式。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ESC ] 1337 ; File = [optional arguments] : base-64 encoded file contents ^G</span><br></pre></td></tr></table></figure><p>按照上面的格式我们将数据分为 <code>header</code> ，<code>body</code> 和 <code>footer</code> 三个部分，而 <code>header</code> 和 <code>footer</code> 相对固定，我们使用 <code>strings.NewReader</code> 封装返回一个 <code>io.Reader</code> ，而中间变化的 <code>base64</code> 编码的数据，我们需要利用 <code>base64.NewEncoder</code> 来对输入的数据进行编码，最后将三个部分利用 <code>io.MultiReader</code> 整合成一个 <code>io.Reader</code> ，然后利用 <code>io.Copy</code> 将数据传输到 <code>w</code> 中，然而 <code>base64.NewEncoder</code> 返回的是一个 <code>io.WriteCloser</code> ，而我们想要的是一个 <code>io.Reader</code> ，这种转化我们可以借助 <code>io.Pipe()</code> 实现，<code>io.Pipe()</code> 会返回一个 <code>PipeReader</code> 和一个  <code>PipeWriter</code> ，当有数据往 <code>PipeWriter</code> 中写时，<code>PipeReader</code> 就可以获得相应的数据，通过这种方式，我们就可以间接地将一个 <code>Writer</code> 转换为一个 <code>Reader</code> 来使用了。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">copy</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    header := strings.NewReader(<span class="string">"\033 ] 1337 ; File = inline=1 : "</span>)</span><br><span class="line">    footer := strings.NewReader(<span class="string">"\a\n"</span>)</span><br><span class="line">    </span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> pw.Close()</span><br><span class="line">        wc := base64.NewEncoder(base64.StdEncoding, pw)</span><br><span class="line">        _, err := io.Copy(wc, r)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            pw.CloseWithError(err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">   </span><br><span class="line">        <span class="keyword">if</span> err := wc.Close(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            pw.CloseWithError(err)</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;()</span><br><span class="line">   </span><br><span class="line">    mr := io.MultiReader(header, pr, footer)</span><br><span class="line">    _, err := io.Copy(w, mr)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>为了在下面的 <code>imgcat</code> 方法中使用 <code>io.Copy</code> 接口，我们需要自己实现一个 <code>io.Writer</code> ，在 <code>NewWriter</code> 函数中我们返回自己 <code>writer</code> 结构体，并且同时起了一个<code>goroutine</code> 来获取 <code>PipeWriter</code> 写的数据，同理，<code>PipeWriter</code> 中写入的数据可以从相应的 <code>PipeReader</code> 获取。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> imgcat</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> writer <span class="keyword">struct</span> &#123;</span><br><span class="line">    pw   *io.PipeWriter</span><br><span class="line">    done <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *writer)</span> <span class="title">Write</span><span class="params">(p []<span class="keyword">byte</span>)</span> <span class="params">(<span class="keyword">int</span>, error)</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> w.pw.Write(p)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *writer)</span> <span class="title">Close</span><span class="params">()</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> err := w.pw.Close(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    &lt;-w.done</span><br><span class="line">    <span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewWriter</span><span class="params">(w io.Writer)</span> <span class="title">io</span>.<span class="title">WriteCloser</span></span> &#123;</span><br><span class="line">    pr, pw := io.Pipe()</span><br><span class="line">    wc := &amp;writer&#123;pw, <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)&#125;</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> <span class="built_in">close</span>(w.done)</span><br><span class="line">        err := <span class="built_in">copy</span>(w, pr)</span><br><span class="line">        pr.CloseWithError(err)</span><br><span class="line">    &#125;()</span><br><span class="line">   <span class="keyword">return</span> wc</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在 <code>imgcat</code> 方法中主要是通过 <code>io.Copy</code> 将路径 <code>path</code> 对应的文件拷贝到我们上面的 <code>Writer</code> 中，<code>NewWriter</code> 指定 <code>os.Stdout</code> 作为我们的输出。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">imgcat</span><span class="params">(path <span class="keyword">string</span>)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    f, err := os.Open(path)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> f.Close()</span><br><span class="line"></span><br><span class="line">    wc := imgcat.NewWriter(os.Stdout)</span><br><span class="line">    <span class="keyword">if</span> _, err = io.Copy(wc, f); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> wc.Close()</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(os.Args) != <span class="number">2</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> </span><br><span class="line">    &#125;</span><br><span class="line">    err := imgcat(os.Args[<span class="number">1</span>])</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;在 &lt;code&gt;iTerm2&lt;/code&gt; 中我们可以直接查看图片，是不是有点酷炫。&lt;/p&gt;
-&lt;p&gt;&lt;img src=&quot;https://www.iterm2.com/images/inline_image_sparky_demo.png&quot; alt=&quot;imgcat&quot;&gt;&lt;/p&gt;
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>World Cup</title>
-    <link href="https://oceanoverflow.github.io/2018/06/17/WorldCup/"/>
-    <id>https://oceanoverflow.github.io/2018/06/17/WorldCup/</id>
-    <published>2018-06-17T07:18:49.000Z</published>
-    <updated>2018-06-26T08:47:20.459Z</updated>
-    
-    <content type="html"><![CDATA[<p>四年一度的世界杯最近正在俄罗斯如火如荼的进行，昨天看了西班牙🇪🇸对葡萄牙🇵🇹的比赛，C罗真的是太帅了，帽子戏法，不过作为一个伪球迷-真程序员，准备写一点和世界杯有关的东西，想想用机器学习预测比赛结果好像并没有什么卵用，于是就写一个最简单的搬砖程序来提醒自己比赛时间吧。最终效果如下所示，典型的 <code>MVC</code> 。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">Costa Rica                       <span class="number">0</span> - <span class="number">0</span>                           Serbia</span><br><span class="line">------------------------------------------------------------------------</span><br><span class="line">⚽  Will be played <span class="number">4</span> hours from now</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Germany                          <span class="number">0</span> - <span class="number">0</span>                           Mexico</span><br><span class="line">------------------------------------------------------------------------</span><br><span class="line">⚽  Will be played <span class="number">7</span> hours from now</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Brazil                           <span class="number">0</span> - <span class="number">0</span>                      Switzerland</span><br><span class="line">------------------------------------------------------------------------</span><br><span class="line">⚽  Will be played <span class="number">10</span> hours from now</span><br></pre></td></tr></table></figure><h2 id="Model"><a href="#Model" class="headerlink" title="Model"></a>Model</h2><p>比赛相关的数据可以从 <code>http://worldcup.sfg.io/</code> 获取，我们使用结构体定义数据模型，注意结构体中的数据字段必须为大写，否则无法正确 <code>Unmarshal</code>，如果想要使结构体中的字段与 <code>json</code> 中的字段不同，可以额外增加 <code>tag</code> 来说明。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> match <span class="keyword">struct</span> &#123;</span><br><span class="line">    Time     <span class="keyword">string</span> <span class="string">`json:"time,omitempty"`</span></span><br><span class="line">    DateTime <span class="keyword">string</span> <span class="string">`json:"datetime,omitempty"`</span></span><br><span class="line">    HomeTeam team   <span class="string">`json:"home_team,ommitempty"`</span></span><br><span class="line">    AwayTeam team   <span class="string">`json:"away_team,omitempty"`</span></span><br><span class="line">    Winner   <span class="keyword">string</span> <span class="string">`json:"winner,omitempty"`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> team <span class="keyword">struct</span> &#123;</span><br><span class="line">    Country <span class="keyword">string</span> <span class="string">`json:"country,omitempty"`</span></span><br><span class="line">    Code    <span class="keyword">string</span> <span class="string">`json:"code,omitempty"`</span></span><br><span class="line">    Goals   <span class="keyword">int</span>    <span class="string">`json:"goals,omitempty"`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">fetch</span><span class="params">(endpoint)</span> <span class="params">([]match, error)</span></span> &#123;</span><br><span class="line">    url := fmt.Sprintf(<span class="string">"http://worldcup.sfg.io/%s"</span>, endpoint)</span><br><span class="line">    res, err := http.Get(url)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> res.Body.Close()</span><br><span class="line">    b, err := ioutil.ReadAll(res.Body)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">var</span> matches []match</span><br><span class="line">    err = json.Unmarshal(b, &amp;matches)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> matches, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="View"><a href="#View" class="headerlink" title="View"></a>View</h2><p>因为我们的 <code>layout</code> 相对比较复杂，所以 <code>View</code> 部分代码也最多，但难度不大，就是繁琐，主要注意几点，彩色字体输出，不同情况下进度条的展示效果和各个字段所在的位置。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> status <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    PAST status = <span class="literal">iota</span></span><br><span class="line">    NOW</span><br><span class="line">    FUTURE</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> ScreenWidth = <span class="number">72</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> (</span><br><span class="line">    START = <span class="string">"\x1b[32m"</span></span><br><span class="line">    END   = <span class="string">"\x1b[0m"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">colorize</span><span class="params">(s <span class="keyword">string</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">return</span> START + s + END</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">multiply</span><span class="params">(c <span class="keyword">rune</span>, n <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> cs []<span class="keyword">rune</span></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; n; i++ &#123;</span><br><span class="line">        cs = <span class="built_in">append</span>(cs, c)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">string</span>(cs)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">prettify</span><span class="params">(m match)</span> <span class="title">string</span></span> &#123;</span><br><span class="line"></span><br><span class="line">    t, _ := time.Parse(time.RFC3339, m.DateTime)</span><br><span class="line">    diff := <span class="keyword">int</span>(time.Now().Sub(t).Seconds())</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> status status</span><br><span class="line">    <span class="keyword">switch</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> diff &gt; <span class="number">60</span>*<span class="number">90</span>:</span><br><span class="line">        status = PAST</span><br><span class="line">    <span class="keyword">case</span> diff &lt; <span class="number">0</span>:</span><br><span class="line">        status = FUTURE</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        status = NOW</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    percentage := <span class="number">0</span></span><br><span class="line">    matchStatus := <span class="string">""</span></span><br><span class="line">    on := <span class="literal">false</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> status &#123; </span><br><span class="line">    <span class="keyword">case</span> PAST:</span><br><span class="line">        percentage = <span class="number">100</span></span><br><span class="line">        <span class="keyword">var</span> result <span class="keyword">string</span></span><br><span class="line">        <span class="keyword">if</span> m.Winner == <span class="string">"Draw"</span> &#123;</span><br><span class="line">            result = <span class="string">"Draw"</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            result = fmt.Sprintf(<span class="string">"%s won"</span>, m.Winner)</span><br><span class="line">        &#125;</span><br><span class="line">        matchStatus = fmt.Sprintf(<span class="string">"Played %s. %s"</span>, humanize.Time(t), result)</span><br><span class="line">        on = <span class="literal">true</span></span><br><span class="line">    <span class="keyword">case</span> NOW:</span><br><span class="line">        percentage = <span class="keyword">int</span>(diff / <span class="number">60</span> / <span class="number">90</span> * <span class="number">100</span>)</span><br><span class="line">        matchStatus = fmt.Sprintf(<span class="string">"Being played now: %s minutes gone"</span>, humanize.Time(t))</span><br><span class="line">        on = <span class="literal">true</span></span><br><span class="line">    <span class="keyword">case</span> FUTURE:</span><br><span class="line">        percentage = <span class="number">0</span></span><br><span class="line">        matchStatus = fmt.Sprintf(<span class="string">"Will be played %s"</span>, humanize.Time(t))</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    home := m.HomeTeam</span><br><span class="line">    away := m.AwayTeam</span><br><span class="line"></span><br><span class="line">    s, e := <span class="string">""</span>, <span class="string">""</span></span><br><span class="line">    <span class="keyword">if</span> on &#123;</span><br><span class="line">        s = start</span><br><span class="line">        e = end</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"    %s%-32s %d - %d %32s%s\n    %s\n    \u26BD  %s\n"</span>,</span><br><span class="line">        s,home.Country,home.Goals,away.Goals,away.Country,e,</span><br><span class="line">        progressBar(percentage),</span><br><span class="line">        matchStatus,</span><br><span class="line">    )</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">progressBar</span><span class="params">(percentage <span class="keyword">int</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> bar <span class="keyword">string</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">switch</span> percentage &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">        bar = multiply(<span class="string">'-'</span>, ScreenWidth)</span><br><span class="line">    <span class="keyword">case</span> <span class="number">100</span>:</span><br><span class="line">        bar = colorize(multiply(<span class="string">'-'</span>, ScreenWidth))</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">        completed := <span class="keyword">int</span>(<span class="keyword">float64</span>(ScreenWidth) / <span class="number">100.0</span> * <span class="keyword">float64</span>(percentage))</span><br><span class="line">        bar = colorize(multiply(<span class="string">'-'</span>, completed<span class="number">-1</span>)+<span class="string">"o"</span>) + multiply(<span class="string">'-'</span>, ScreenWidth-completed)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> bar</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Controller"><a href="#Controller" class="headerlink" title="Controller"></a>Controller</h2><p><code>Controller</code> 部分就是将 <code>Model</code> 部分和 <code>view</code> 部分代码整合在一起。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    matches, err := fetch(<span class="string">"matches/today"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i, match := <span class="keyword">range</span> matches &#123;</span><br><span class="line">        <span class="keyword">if</span> i == <span class="number">0</span> &#123;</span><br><span class="line">            fmt.Println()</span><br><span class="line">        &#125;</span><br><span class="line">        fmt.Println(prettify(match))</span><br><span class="line">        <span class="keyword">if</span> i != <span class="built_in">len</span>(matches)<span class="number">-1</span> &#123;</span><br><span class="line">            fmt.Println()</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;四年一度的世界杯最近正在俄罗斯如火如荼的进行，昨天看了西班牙🇪🇸对葡萄牙🇵🇹的比赛，C罗真的是太帅了，帽子戏法，不过作为一个伪球迷-真程序员，准备写一点和世界杯有关的东西，想想用机器学习预测比赛结果好像并没有什么卵用，于是就写一个最简单的搬砖程序来提醒自己比赛时间吧
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Snappy</title>
-    <link href="https://oceanoverflow.github.io/2018/06/15/Snappy/"/>
-    <id>https://oceanoverflow.github.io/2018/06/15/Snappy/</id>
-    <published>2018-06-15T09:00:01.000Z</published>
-    <updated>2018-06-26T08:47:49.515Z</updated>
-    
-    <content type="html"><![CDATA[<p><code>Snappy</code> 是 <code>Google</code> 开发的压缩和解压缩的库，最初使用 <code>C++</code> 编写，后来又造了一个 <code>golang</code> 版本的轮子。由于目前该压缩算法还没有放到 <code>go</code> 的标准库中去，所以需要通过 <code>go get -u github.com/golang/snappy</code> 安装。</p><p>与其他常见的压缩算法相比，<code>Snappy</code> 存在的目的并不是为了获得最大程度的压缩比，正如其名字所言，它旨在保持合理的压缩比的同时最大限度地提高压缩和解压缩的速度。</p><p><code>Snappy</code> 对数据处理速度上做了很大的优化，但它并不是没有缺点，相对于其他算法来说，<code>Snappy</code> 压缩得到的文件体积会更大一点。如果你更在意压缩速度而不是压缩比的话，<code>Snappy</code> 可能会是一个很好的选择。</p><h2 id="compression"><a href="#compression" class="headerlink" title="compression"></a>compression</h2><p>下面，我们对比一下 <code>Snappy</code> 压缩算法和其他两种常见的压缩算法（ <code>zlib</code> 和 <code>gzip</code> ）的性能。首先，我们定一个 <code>Compressor</code> 接口，并使 <code>Zlib</code> ，<code>Gzip</code> 和 <code>Snappy</code> 这三个结构体均实现它。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Zlib <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"><span class="keyword">type</span> Gzip <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"><span class="keyword">type</span> Snappy <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Compressor <span class="keyword">interface</span> &#123;</span><br><span class="line">    Compress(io.Writer, io.Reader) error</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="zlib"><a href="#zlib" class="headerlink" title="zlib"></a>zlib</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(_ *Zlib)</span> <span class="title">Compress</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    zw, err := zlib.NewWriterLevel(w, zlib.BestSpeed)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> zw.Close()</span><br><span class="line"></span><br><span class="line">    _, err = io.Copy(zw, r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="gzip"><a href="#gzip" class="headerlink" title="gzip"></a>gzip</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(_ *Gzip)</span> <span class="title">Compress</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    gw, err := gzip.NewWriterLevel(w, gzip.BestSpeed)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> gw.Close()</span><br><span class="line"></span><br><span class="line">    _, err = io.Copy(gw, r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="snappy"><a href="#snappy" class="headerlink" title="snappy"></a>snappy</h3><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(_ *Snappy)</span> <span class="title">compress</span><span class="params">(w io.Writer, r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    sw := snappy.NewBufferedWriter(w)</span><br><span class="line">    <span class="keyword">defer</span> sw.Close()</span><br><span class="line"></span><br><span class="line">    _, err := io.Copy(sw, r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="performance"><a href="#performance" class="headerlink" title="performance"></a>performance</h2><p>对于压缩的性能，可以从压缩比和压缩时间这两点进行衡量。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    f, err := os.Open(<span class="string">"somebigfile"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Fatal(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fGzip, _ := os.Create(<span class="string">"gzip"</span>)</span><br><span class="line">    fZlib, _ := os.Create(<span class="string">"zlib"</span>)</span><br><span class="line">    fSnappy, _ := os.Create(<span class="string">"snappy"</span>)</span><br><span class="line"></span><br><span class="line">    cs := <span class="keyword">map</span>[compressor]io.Writer&#123;</span><br><span class="line">        &amp;Gzip&#123;&#125;:   fGzip,</span><br><span class="line">        &amp;Zlib&#123;&#125;:   fZlib,</span><br><span class="line">        &amp;Snappy&#123;&#125;: fSnappy,</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> c, v := <span class="keyword">range</span> cs &#123;</span><br><span class="line">        t := time.Now()</span><br><span class="line">        err := c.compress(v, f)</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            fmt.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">        d := time.Since(t)</span><br><span class="line">        fmt.Printf(<span class="string">"method: %s, time spend: %.02f, ratio: %.05f%%\n"</span>, </span><br><span class="line">        v.Name(), </span><br><span class="line">        d.Seconds(), </span><br><span class="line">        compressionRatio(f, v))</span><br><span class="line">        f.Seek(<span class="number">0</span>, <span class="number">0</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">compressionRatio</span><span class="params">(f1, f2 *os.File)</span> <span class="title">float64</span></span> &#123;</span><br><span class="line">    f1s, _ := f1.Stat()</span><br><span class="line">    f1size := f1s.Size()</span><br><span class="line">    f2s, _ := f2.Stat()</span><br><span class="line">    f2size := f2s.Size()</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">float64</span>(f2size) / <span class="keyword">float64</span>(f1size) * <span class="number">100</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>Snappy</code> 在速度上来说比 <code>zlib</code> 和 <code>gzip</code> 快得多，但文件相对要大 <code>20%</code> 到 <code>100%</code>。在 <code>64</code> 位模式的 <code>Core i7</code> 处理器上，<code>Snappy</code> 可以达到 <code>250~500</code> 兆每秒的压缩速度，可以说是非常惊人了。 </p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ go run main.go</span><br><span class="line">method:   gzip, time spend: 8.38s, ratio:  7.576%</span><br><span class="line">method:   zlib, time spend: 9.13s, ratio:  7.576%</span><br><span class="line">method: snappy, time spend: 1.96s, ratio: 18.813%</span><br></pre></td></tr></table></figure><p>相比其他的压缩库，<code>Snappy</code> 能在保持特定的压缩率下拥有惊人的压缩速度，压缩普通文本文件的速度是其他库的 <code>1.5-1.7</code> 倍，HTML能达到 <code>2-4</code> 倍，但是对于 <code>JPEG</code>、<code>PNG</code> 以及其他的已压缩的数据，压缩速度不会有明显改善。</p>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;&lt;code&gt;Snappy&lt;/code&gt; 是 &lt;code&gt;Google&lt;/code&gt; 开发的压缩和解压缩的库，最初使用 &lt;code&gt;C++&lt;/code&gt; 编写，后来又造了一个 &lt;code&gt;golang&lt;/code&gt; 版本的轮子。由于目前该压缩算法还没有放到 &lt;code&gt;go&lt;
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Timing Wheel</title>
-    <link href="https://oceanoverflow.github.io/2018/06/14/TimingWheel/"/>
-    <id>https://oceanoverflow.github.io/2018/06/14/TimingWheel/</id>
-    <published>2018-06-14T01:20:25.000Z</published>
-    <updated>2018-06-26T08:47:39.796Z</updated>
-    
-    <content type="html"><![CDATA[<p><img src="https://www.confluent.io/wp-content/uploads/2016/08/TimingWheels1.png" alt="timingwheel"></p><p>当我们自己编写服务端程序时候，可能需要新建大量的定时器，对每个 <code>TCP</code> 连接设置连接超时，面对成千上万的客户端连接，如果傻傻地为每一个连接分配一个计时器的话，那么 <code>10k</code> 个连接就对应 <code>10k</code> 的计时器，<code>10w</code> 个连接就对应 <code>10w</code> 个计时器，这种方法显然是比较消耗内存的。</p><p>对于需要大量定时器的情况，由于许多定时器是在相近的时间超时的，或者说在一个时间范围内到时的，如果对时间精度没有那么近乎苛刻的要求的话，我们可以利用这个特性将多个同一时间段的计时器整合成一个来使用，这样的话就可以极大程度上降低内存的消耗，例如现在有 <code>3，4，5，6</code> 四个连接，它们均会在后面的3到4秒内超时，我们可以采用一种方法使它们共用一个计数器，并当时间点到来时，它们均可以被通知到。</p><h2 id="closed-channel"><a href="#closed-channel" class="headerlink" title="closed channel"></a>closed channel</h2><p>也就是说，我们需要一个机制来重复利用某一个计时器，换句话说，当时间点到来时，我们需要一种广播的机制让等待该计时器的都能被通知到。</p><p>为此需要利用 <code>golang</code> 中通道的几个特性，我们通过一个例子来理解一下，在下面的函数中 <code>make</code> 了一个 <code>unbuffered channel</code> ch，还新起了3个 <code>goroutine</code> ，每个<code>goroutine</code> 会执行 <code>fmt.Println(&quot;start &quot;, i)</code> ，但等它们都执行到 <code>&lt;-ch</code> 语句时，由于没有其他 <code>goroutine</code> 执行 <code>ch &lt;- struct{}{}</code> 操作，所以3个 <code>goroutine</code> 都会阻塞，当 <code>time.Sleep(1 * time.Second)</code> 结束时，我们利用 <code>close(ch)</code> ，此操作相当于向每个 <code>goroutine</code> 进行 <code>ch &lt;- struct{}{}</code> ，此时阻塞解除，每个 <code>goroutine</code> 都可以继续执行 <code>fmt.Println(&quot;end &quot;, i)</code> 。也就是说 <code>close(ch)</code> 相当于一个广播操作。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    ch := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="number">3</span>; i++ &#123;</span><br><span class="line">        i := i</span><br><span class="line">        <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">            fmt.Println(<span class="string">"start "</span>, i)</span><br><span class="line">            &lt;-ch</span><br><span class="line">            fmt.Println(<span class="string">"end "</span>, i)</span><br><span class="line">        &#125;()</span><br><span class="line">    &#125;</span><br><span class="line">    time.Sleep(<span class="number">1</span> * time.Second)</span><br><span class="line">    <span class="built_in">close</span>(ch)</span><br><span class="line">    <span class="keyword">select</span> &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面的例子利用到了通道的的第一个特性和第三个特性。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. The expression blocks until a value is available. </span><br><span class="line">2. Receiving from a nil channel blocks forever. </span><br><span class="line">3. A receive operation on a closed channel can always proceed immediately, yielding the element type’s zero value after any previously sent values have been received.</span><br></pre></td></tr></table></figure><h2 id="timing-wheel"><a href="#timing-wheel" class="headerlink" title="timing wheel"></a>timing wheel</h2><p>那么上面的例子和我们要实现的东西有什么联系呢，其实联系非常大，我们可以给每一个需要进行定时操作的 <code>goroutine</code> 一个 <code>unbuffered channel</code><br>，并且给予在相同时间点超时的 <code>goroutine</code> 以同样的通道。然后我们自己维护一个 <code>ticker</code> ，这个 <code>ticker</code> 每隔固定的时间，将相应的通道关闭，这相当于一个广播操作，这样每个等待此广播的 <code>goroutine</code> 都会收到消息，也就可以继续执行下去了。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> TimingWheel <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Mutex</span><br><span class="line"></span><br><span class="line">    interval   time.Duration</span><br><span class="line">    maxTimeout time.Duration </span><br><span class="line">    </span><br><span class="line">    ticker     *time.Ticker</span><br><span class="line">    cs         []<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">    pos        <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line">    stop       <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(interval time.Duration, buckets <span class="keyword">int</span>)</span> *<span class="title">TimingWheel</span></span> &#123;</span><br><span class="line">    w := &amp;TimingWheel&#123;</span><br><span class="line">        interval:   interval,</span><br><span class="line">        maxTimeout: interval * time.Duration(buckets),</span><br><span class="line">        ticker:     time.NewTicker(interval),</span><br><span class="line">        cs :        <span class="built_in">make</span>([]<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, buckets),</span><br><span class="line">        pos:        <span class="number">0</span>,</span><br><span class="line">        stop:       <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;),</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="keyword">range</span> w.cs &#123;</span><br><span class="line">        w.cs[i] = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">go</span> w.run()</span><br><span class="line">    <span class="keyword">return</span> w</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>光说可能有一点抽象，下面我们来看一下具体的实现，<code>TimingWheel</code> 结构体相当于模拟一个秒表，其中的 <code>ticker</code> 就相当于一个秒针，同时我们还维护了一个通道数组 <code>cs</code> （其存储结构为顺序存储，而其逻辑结构则是一个圆环），作为定时器使用，<code>ticker</code> 每隔固定的 <code>interval</code> ，会让指针向前移动一个单位（ <code>pos++</code> ），并将该位置存储的通道关闭，也就相同于定时器返回，这种方法实现的定时器相对来说增加了定时器的利用率，降低了内存的消耗。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">run</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> &lt;-w.ticker.C:</span><br><span class="line">            w.tick()</span><br><span class="line">        <span class="keyword">case</span> &lt;-w.stop:</span><br><span class="line">            w.ticker.Stop()</span><br><span class="line">            <span class="keyword">return</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">tick</span><span class="params">()</span></span> &#123;</span><br><span class="line">    w.Lock()</span><br><span class="line">    last := w.cs[w.pos]</span><br><span class="line">    w.cs[w.pos] = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">     </span><br><span class="line">    w.pos = (w.pos + <span class="number">1</span>) % <span class="built_in">len</span>(w.cs)</span><br><span class="line">    w.Unlock()    </span><br><span class="line">    <span class="built_in">close</span>(last)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>After</code> 方法为我们提供一个定时器，如果 <code>timeout</code> 数值太大无法落在 <code>timing wheel</code> 的一个周期的时间范围内，则报错，如果 <code>timeout</code> 在正常范围内，则返回对应位置的通道，当该通道超时时，上面的 <code>tick</code> 方法就会将该通道关闭，相应的 <code>goroutine</code> 就可以收到通知了。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">After</span><span class="params">(timeout time.Duration)</span> &lt;-<span class="title">chan</span> <span class="title">struct</span></span> &#123;&#125; &#123;</span><br><span class="line">    <span class="keyword">if</span> timeout &gt;= w.maxTimeout &#123;</span><br><span class="line">        <span class="built_in">panic</span>(<span class="string">"timeout too long"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    idx := <span class="keyword">int</span>(timeout / w.interval)</span><br><span class="line">    <span class="keyword">if</span> idx &gt; <span class="number">0</span> &#123;</span><br><span class="line">        idx--</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    w.Lock()</span><br><span class="line">    idx = (w.pos + idx) % <span class="built_in">len</span>(w.cs)</span><br><span class="line">    b := w.cs[idx]</span><br><span class="line">    w.Unlock()</span><br><span class="line"> </span><br><span class="line">    <span class="keyword">return</span> b</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(w *TimingWheel)</span> <span class="title">Stop</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="built_in">close</span>(w.exit)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;&lt;img src=&quot;https://www.confluent.io/wp-content/uploads/2016/08/TimingWheels1.png&quot; alt=&quot;timingwheel&quot;&gt;&lt;/p&gt;
-&lt;p&gt;当我们自己编写服务端程序时候，可能需要新建大量的定时器，对每
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Ligatures</title>
-    <link href="https://oceanoverflow.github.io/2018/06/13/Ligatures/"/>
-    <id>https://oceanoverflow.github.io/2018/06/13/Ligatures/</id>
-    <published>2018-06-13T05:20:38.000Z</published>
-    <updated>2018-06-26T08:46:37.189Z</updated>
-    
-    <content type="html"><![CDATA[<p>!!! From: <code>https://github.com/tonsky/FiraCode</code> !!!</p><h2 id="problem"><a href="#problem" class="headerlink" title="problem"></a>problem</h2><p>Programmers use a lot of symbols, often encoded with several characters. For the human brain, sequences like -&gt;, &lt;= or := are single logical tokens, even if they take two or three characters on the screen. Your eye spends a non-zero amount of energy to scan, parse and join multiple characters into a single logical one. Ideally, all programming languages should be designed with full-fledged Unicode symbols for operators, but that’s not the case yet.</p><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/all_ligatures.png" alt="all_ligatures"></p><h2 id="installation"><a href="#installation" class="headerlink" title="installation"></a>installation</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> brew tap caskroom/fonts</span></span><br><span class="line"><span class="meta">$</span><span class="bash"> brew cask install font-fira-code</span></span><br></pre></td></tr></table></figure><h2 id="visual-studio-code"><a href="#visual-studio-code" class="headerlink" title="visual studio code"></a>visual studio code</h2><p>Add <code>&quot;editor.fontLigatures&quot;: true</code> to <code>settings.json</code> :</p><p>To open <code>settings.json</code> , from the File menu choose Preferences, Settings or use keyboard shortcut  <code>Cmd</code> + <code>,</code> . Then paste the following lines and save the file.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">"editor.fontFamily"</span>: <span class="string">"Fira Code"</span>,</span><br><span class="line"><span class="string">"editor.fontLigatures"</span>: <span class="literal">true</span></span><br></pre></td></tr></table></figure><h2 id="what-it-looks-like"><a href="#what-it-looks-like" class="headerlink" title="what it looks like"></a>what it looks like</h2><h3 id="Go"><a href="#Go" class="headerlink" title="Go"></a>Go</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/go.png" alt="go"></p><h3 id="Swift"><a href="#Swift" class="headerlink" title="Swift"></a>Swift</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/swift.png" alt="swift"></p><h3 id="Ruby"><a href="#Ruby" class="headerlink" title="Ruby"></a>Ruby</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/ruby.png" alt="ruby"></p><h3 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h3><p><img src="https://github.com/tonsky/FiraCode/raw/master/showcases/javascript.png" alt="js"></p>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;!!! From: &lt;code&gt;https://github.com/tonsky/FiraCode&lt;/code&gt; !!!&lt;/p&gt;
-&lt;h2 id=&quot;problem&quot;&gt;&lt;a href=&quot;#problem&quot; class=&quot;headerlink&quot; title=&quot;problem&quot;&gt;
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Calculate 24</title>
-    <link href="https://oceanoverflow.github.io/2018/06/12/Calculate24/"/>
-    <id>https://oceanoverflow.github.io/2018/06/12/Calculate24/</id>
-    <published>2018-06-12T06:53:49.000Z</published>
-    <updated>2018-06-26T08:44:01.357Z</updated>
-    
-    <content type="html"><![CDATA[<p>算24点还是挺考验一个人的心算能力的，作为一个数学比较差劲的人，每次和别人玩24点总是会慢一个节拍，可以说是非常伤自尊了。不过虽然心算算不过别人，我们可以写一个自动计算24点的程序和别人比嘛，嘻嘻。</p><h2 id="expression-tree"><a href="#expression-tree" class="headerlink" title="expression tree"></a>expression tree</h2><p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Exp-tree-ex-11.svg/500px-Exp-tree-ex-11.svg.png" alt="ExpressionTree"></p><p>我们可以利用表达式树来确定运算的优先级，进而确定运算的顺序，表达式树属于二叉树，其叶结点存储运算数（ <code>val</code> ），非叶子结点存储运算符 <code>op</code> （ <code>+，-，*，/</code> ）及运算结果（ <code>val = l.val op r.val</code> ）。每个节点都有指向其左子节点（ <code>l</code> ）和右子节点（ <code>r</code> ）的指针，叶节点中这两个指针均为空。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> node <span class="keyword">struct</span> &#123;</span><br><span class="line">    l    *node</span><br><span class="line">    r    *node</span><br><span class="line">    op   <span class="keyword">rune</span></span><br><span class="line">    val  <span class="keyword">float64</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *node)</span> <span class="title">set</span><span class="params">(l, r *node, op <span class="keyword">rune</span>)</span></span> &#123;</span><br><span class="line">    n.l  = l</span><br><span class="line">    n.r  = r</span><br><span class="line">    n.op = op</span><br><span class="line">    <span class="keyword">switch</span> op &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'+'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val + n.r.val)</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'-'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val - n.r.val)</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'*'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val * n.r.val)</span><br><span class="line">    <span class="keyword">case</span> <span class="string">'/'</span>:</span><br><span class="line">        n.val = <span class="keyword">float64</span>(n.l.val / n.r.val)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(n *node)</span> <span class="title">String</span><span class="params">()</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n.op != <span class="keyword">rune</span>(<span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> fmt.Sprintf(<span class="string">" %c "</span>, n.op)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> fmt.Sprintf(<span class="string">"%d"</span>, <span class="keyword">int</span>(n.val))</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="build-tree"><a href="#build-tree" class="headerlink" title="build tree"></a>build tree</h2><p>由于存在运算优先级的原因，所以在运算数和运算符都相同的情况下当其运算顺序不同时得出的表达式树的形态也不同，例如 <code>(1 + 8) * (7 - 13)</code>  与 <code>1 + 8 * 7 - 13</code> 的运算顺序是不同的，<code>(1 + 8) * (7 - 13)</code>  对应的是下面第一棵树的形态， <code>1 + 8 * 7 - 13</code> 对应的是下面第四棵树的形态。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">    x               x               x                x               x</span><br><span class="line">   / \             / \             / \              / \             / \</span><br><span class="line">  x   x           x   x           x   x            x   x           x   x</span><br><span class="line"> / \ / \             / \             / \          / \             / \</span><br><span class="line">x  x x  x           x   x           x   x        x   x           x   x</span><br><span class="line">                   / \                 / \          / \         / \</span><br><span class="line">                  x   x               x   x        x   x       x   x</span><br></pre></td></tr></table></figure><p>为了得出所有的可能结果，我们需要构建所有不同形态的表达式树，<code>buildAllTrees</code> 利用递归方法来建树，例如给定 <code>3，4，5，6</code> 这四个数，可以构建出上面5种形态的树。 <code>3，4，5，6</code> 作为参数传入，然后将数组分割为两个部分，例如上面的 <code>3，4，5，6</code> 可以分割为 <code>3</code> 和 <code>4，5，6</code> 或者 <code>3，4</code> 和 <code>5，6</code> 或者 <code>3，4，5</code> 和 <code>6</code> ，然后对这两个部分分别再进行递归建树操作，当数组长度为1时也就是当 <code>len(s) == 1</code> 作为递归函数退出的条件，此时返回一个叶节点，按照这样的方式最终可以得到所有可能形态的树的根节点。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">buildAllTrees</span><span class="params">(s []<span class="keyword">int</span>)</span> []*<span class="title">node</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(s) == <span class="number">1</span> &#123;</span><br><span class="line">       tree := &amp;node&#123;result: <span class="keyword">float64</span>(s[<span class="number">0</span>])&#125;</span><br><span class="line">       <span class="keyword">return</span> []*node&#123;tree&#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    treelist := []*node&#123;&#125;</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">1</span>; i &lt; <span class="built_in">len</span>(s); i++ &#123;</span><br><span class="line">        left := s[:i]</span><br><span class="line">        right := s[i:]</span><br><span class="line">        leftTrees := buildAllTrees(left)</span><br><span class="line">        rightTrees := buildAllTrees(right)</span><br><span class="line">        <span class="keyword">for</span> _, l := <span class="keyword">range</span> leftTrees &#123;</span><br><span class="line">            <span class="keyword">for</span> _, r := <span class="keyword">range</span> rightTrees &#123;</span><br><span class="line">                combinedTree := build(l, r)</span><br><span class="line">                treelist = <span class="built_in">append</span>(treelist, combinedTree...)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> treelist</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>因为存在四种运算符，例如利用 <code>a</code> 和 <code>b</code> 这两个节点构建树的时候，可以有 <code>a+b</code> ， <code>a-b</code> ， <code>a*b</code> ， <code>a/b</code> 这四种可能，所以要分别列举。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">build</span><span class="params">(l, r *node)</span> []*<span class="title">node</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> list []*node</span><br><span class="line">    tree1 := &amp;node&#123;&#125;</span><br><span class="line">    tree1.set(l, r, <span class="string">'+'</span>)</span><br><span class="line">    list = <span class="built_in">append</span>(list, tree1)</span><br><span class="line">    tree2 := &amp;node&#123;&#125;</span><br><span class="line">    tree2.set(l, r, <span class="string">'-'</span>)</span><br><span class="line">    list = <span class="built_in">append</span>(list, tree2)</span><br><span class="line">    tree3 := &amp;node&#123;&#125;</span><br><span class="line">    tree3.set(l, r, <span class="string">'*'</span>)</span><br><span class="line">    list = <span class="built_in">append</span>(list, tree3)</span><br><span class="line">    <span class="keyword">if</span> r.result != <span class="number">0.0</span> &#123;</span><br><span class="line">        tree4 := &amp;node&#123;&#125;</span><br><span class="line">        tree4.set(l, r, <span class="string">'/'</span>)</span><br><span class="line">        list = <span class="built_in">append</span>(list, tree4)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> list</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们可以通过中序遍历表达式树来遍历输出构建的表达式，由于上面我们定义了每个节点的 <code>String</code> 方法，如果节点为运算符，则输出其 <code>op</code> 的值，如果节点为叶结点，则输出其 <code>val</code> 值。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">in</span><span class="params">(root *node)</span></span> &#123;</span><br><span class="line">    <span class="keyword">if</span> n == <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> n.op != <span class="keyword">rune</span>(<span class="number">0</span>) &#123;</span><br><span class="line">        fmt.Print(<span class="string">"("</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    in(root.l)</span><br><span class="line">    fmt.Print(n.String())</span><br><span class="line">    in(root.r)</span><br><span class="line">    <span class="keyword">if</span> n.op != <span class="keyword">rune</span>(<span class="number">0</span>) &#123;</span><br><span class="line">        fmt.Print(<span class="string">")"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="permutation"><a href="#permutation" class="headerlink" title="permutation"></a>permutation</h2><p>上面的方法是对一个数组其固定的顺序构建表达式树，例如 <code>3，4，5，6</code> 。为了获得所有的运算表达式，我们需要对数组的所有排列组合进行表达式树的构建，例如对 <code>6，5，4，3</code> ，<code>5，6，4，3</code> 这样的排列组合构建表达式树。也就是说除了树形态不同的这点区别之外，还要注意叶结点值存储顺序不同的带来的可能（可能会导致重复）。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Perm</span><span class="params">(a []<span class="keyword">int</span>, f <span class="keyword">func</span>([]<span class="keyword">int</span>)</span>)</span> &#123;</span><br><span class="line">    perm(a, f, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">perm</span><span class="params">(a []<span class="keyword">int</span>, f <span class="keyword">func</span>([]<span class="keyword">int</span>)</span>, <span class="title">i</span> <span class="title">int</span>)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> i &gt; <span class="built_in">len</span>(a) &#123;</span><br><span class="line">        f(a)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">    perm(a, f, i+<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">for</span> j := i + <span class="number">1</span>; j &lt; <span class="built_in">len</span>(a); j++ &#123;</span><br><span class="line">        a[i], a[j] = a[j], a[i]</span><br><span class="line">        perm(a, f, i+<span class="number">1</span>)</span><br><span class="line">        a[i], a[j] = a[j], a[i]</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="main"><a href="#main" class="headerlink" title="main"></a>main</h2><p>在主函数中我们每隔五秒钟获得一个随机的扑克牌数字，然后对于该组数字所有的排列组合分别构建表达式树，对每棵构建好的树判断其根节点的值是否接近于24（由于涉及到除法操作，所以有小数点），如果接近，则将其表达式通过中序遍历输出，这样就可以得出一组数字所有24点的可能了。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        s := rand24()</span><br><span class="line">        fmt.Println(s)</span><br><span class="line">        Perm(s, <span class="function"><span class="keyword">func</span><span class="params">(a []<span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">            treelist := buildAllTrees(a)</span><br><span class="line">            <span class="keyword">for</span> _, root := <span class="keyword">range</span> treelist &#123;</span><br><span class="line">                <span class="keyword">if</span> math.Abs(<span class="number">24</span>-tree.result) &lt; <span class="number">0.000001</span> &#123;</span><br><span class="line">                    in(root)</span><br><span class="line">                    fmt.Println()</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">        time.Sleep(<span class="number">5</span> * time.Second)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">rand24</span><span class="params">()</span> <span class="params">(r []<span class="keyword">int</span>)</span></span> &#123;</span><br><span class="line">    rand.Seed(time.Now().UnixNano())</span><br><span class="line"></span><br><span class="line">    club    := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    heart   := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    spade   := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    diamond := []<span class="keyword">int</span>&#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>, <span class="number">12</span>, <span class="number">13</span>&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">var</span> all []<span class="keyword">int</span></span><br><span class="line">    all = <span class="built_in">append</span>(all, spade...)</span><br><span class="line">    all = <span class="built_in">append</span>(all, heart...)</span><br><span class="line">    all = <span class="built_in">append</span>(all, diamond...)</span><br><span class="line">    all = <span class="built_in">append</span>(all, club...)</span><br><span class="line"></span><br><span class="line">    r = <span class="built_in">make</span>([]<span class="keyword">int</span>, <span class="number">4</span>)</span><br><span class="line"></span><br><span class="line">    exist = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">bool</span>)</span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="number">4</span>; i++ &#123;</span><br><span class="line">        <span class="keyword">for</span> &#123;</span><br><span class="line">            x := rand.Int() % <span class="built_in">len</span>(all)</span><br><span class="line">            <span class="keyword">if</span> !exist[x] &#123;</span><br><span class="line">                exist[x] = <span class="literal">true</span></span><br><span class="line">                r[i] = all[x]</span><br><span class="line">                <span class="keyword">break</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;算24点还是挺考验一个人的心算能力的，作为一个数学比较差劲的人，每次和别人玩24点总是会慢一个节拍，可以说是非常伤自尊了。不过虽然心算算不过别人，我们可以写一个自动计算24点的程序和别人比嘛，嘻嘻。&lt;/p&gt;
-&lt;h2 id=&quot;expression-tree&quot;&gt;&lt;a href=
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Chat Chat Chat</title>
-    <link href="https://oceanoverflow.github.io/2018/06/11/ChatChatChat/"/>
-    <id>https://oceanoverflow.github.io/2018/06/11/ChatChatChat/</id>
-    <published>2018-06-11T07:09:34.000Z</published>
-    <updated>2018-06-26T08:44:07.665Z</updated>
-    
-    <content type="html"><![CDATA[<p>承认吧，你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈，却还是没有发现合适的人的时候，今天我们就来写一个随机配对聊天程序，解决广大单身狗寂寞时想要找人聊天的需求吧。</p><p>为了让聊天不那么 <code>gay</code> ，我们的聊天程序会让异性匹配聊天，用户通过客户端连接到聊天程序服务器 <code>localhost:8080</code> ，例如使用 <code>netcat</code> 通过 <code>nc localhost 8080</code> 命令连接聊天程序服务器，服务器会根据你的性别匹配异性聊天。</p><p>在实现方面，为了达到异性相互聊天的目标，我们创建两个通道，分别是 <code>boy</code> 通道和 <code>girl</code> 通道，并通过 <code>net.Listen</code> 方法监听 <code>8080</code> 端口，对于每个连接我们起一个 <code>goroutine</code> 进行匹配操作。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> boy = <span class="built_in">make</span>(<span class="keyword">chan</span> io.ReadWriteCloser)</span><br><span class="line"><span class="keyword">var</span> girl = <span class="built_in">make</span>(<span class="keyword">chan</span> io.ReadWriteCloser)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    l, err := net.Listen(<span class="string">"tcp"</span>, <span class="string">"localhost:8080"</span>)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        c, err := l.Accept()</span><br><span class="line">        <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">            log.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">go</span> match(c)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>match</code> 方法会首先询问你的性别，如果是男生则匹配女生聊天，反之亦然。如果当前只有一个男生连进来，程序会执行第一个 <code>select</code> 中的 <code>case boy &lt;- c:</code> 条件，由于 <code>boy</code> 通道是 <code>unbuffered channel</code> ，直到有女生进来之前该操作都会阻塞。如果此时进来一个女生，程序会执行第二个<code>select</code> 操作，由于 <code>girl</code> 通道也是 <code>unbuffered channel</code> ，所以<code>case girl &lt;- c:</code> 语句也会阻塞，但此时 <code>case p := &lt;-boy:</code> 会被执行，这时候就可以通过 <code>chat</code> 方法让两个 <code>net.Conn</code> 相互交流了。<code>match</code> 方法实现的逻辑就达到了异性交流的目的了。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">match</span><span class="params">(c io.ReadWriteCloser)</span></span> &#123;</span><br><span class="line">    fmt.Fprint(c, <span class="string">"Are you a boy or a girl? "</span>)</span><br><span class="line">    <span class="keyword">var</span> sex <span class="keyword">string</span></span><br><span class="line">    fmt.Fscanln(c, &amp;sex)</span><br><span class="line">    <span class="keyword">if</span> strings.HasPrefix(<span class="string">"boy"</span>, sex) &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> boy &lt;- c: </span><br><span class="line">        <span class="keyword">case</span> p := &lt;-girl:</span><br><span class="line">            chat(p, c)</span><br><span class="line">        &#125;     </span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> strings.HasPrefix(<span class="string">"girl"</span>, sex) &#123;</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> girl &lt;- c:</span><br><span class="line">        <span class="keyword">case</span> p := &lt;-boy:</span><br><span class="line">            chat(p, c)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面的 <code>chat</code> 方法依赖 <code>cp</code> 方法 ，该方法封装了 <code>io.Copy</code> 方法，主要就是为了当任意一方结束聊天时发送一个 <code>err</code> 到我们的 <code>errc</code> ，以关闭双方的连接。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">cp</span><span class="params">(w io.Writer, r io.Reader, errc <span class="keyword">chan</span>&lt;- error)</span></span> &#123;</span><br><span class="line">    _, err := io.Copy(w, r)</span><br><span class="line">    errc &lt;- err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>chat</code> 方法通过两个 <code>goroutine</code> ，<code>go cp(a, b, errc)</code>  和 <code>go cp(b, a, errc)</code> 使a和b这两个 <code>net.Conn</code> 相互发送消息，如果任意一方结束聊天， <code>errc</code> 通道就会返回一个 <code>error</code> 值，a和b就会被关闭，此时聊天结束。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">chat</span><span class="params">(a, b io.ReadWriteCloser)</span></span> &#123;</span><br><span class="line">    fmt.Fprintln(a, <span class="string">"Found one! say hi"</span>)</span><br><span class="line">    fmt.Fprintln(b, <span class="string">"Found one! say hi"</span>)</span><br><span class="line">    errc := <span class="built_in">make</span>(<span class="keyword">chan</span> error, <span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> cp(a, b, errc) </span><br><span class="line">    <span class="keyword">go</span> cp(b, a, errc)</span><br><span class="line">    <span class="keyword">if</span> err := &lt;- errc; err != <span class="literal">nil</span> &#123;</span><br><span class="line">        log.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">    a.Close()</span><br><span class="line">    b.Close()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;承认吧，你肯定也会有深夜寂寞时特别想找人聊天但翻遍朋友圈，却还是没有发现合适的人的时候，今天我们就来写一个随机配对聊天程序，解决广大单身狗寂寞时想要找人聊天的需求吧。&lt;/p&gt;
-&lt;p&gt;为了让聊天不那么 &lt;code&gt;gay&lt;/code&gt; ，我们的聊天程序会让异性匹配聊天，用户通
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>bitcoin</title>
-    <link href="https://oceanoverflow.github.io/2018/06/06/bitcoin/"/>
-    <id>https://oceanoverflow.github.io/2018/06/06/bitcoin/</id>
-    <published>2018-06-06T14:19:02.000Z</published>
-    <updated>2018-06-26T08:43:51.798Z</updated>
-    
-    <content type="html"><![CDATA[<p>如果有时光机的话，我要做的第一件事情肯定就是穿梭回过去买比特币：），算了，不意淫了，还是学习要紧，虽然再也不能靠买比特币一夜暴富了，但是自己按照比特币实现一个山寨比特币的能力还是有的，比特币可以说是现在大红大紫的区块链的始祖，要全部了解它的原理可能还是要埋头啃个几个月的（并不简单）。</p><p>虽然比特币交易确认时间长，消耗资源多，但依旧无法掩盖其作为区块链始祖的光环。</p><p><img src="https://cdn-images-1.medium.com/max/1600/1*_RY4v9D5-BOVMzFMr8Dk4A.png" alt="bitcoin"></p><h2 id="Block-amp-BlockChain"><a href="#Block-amp-BlockChain" class="headerlink" title="Block &amp; BlockChain"></a>Block &amp; BlockChain</h2><p>比特币中有两个重要的基本概念，区块和区块链，如果将区块想象成珍珠，那么区块链就是将这些珍珠都串起来的珍珠项链，这个珍珠项链没有尽头，新加入的珍珠和次新的珍珠彼此靠近，并通过某种关系紧密联系在一起，牢不可破。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Block <span class="keyword">struct</span> &#123;</span><br><span class="line">    idx        <span class="keyword">int</span></span><br><span class="line">    timestamp  <span class="keyword">string</span></span><br><span class="line">    hash       <span class="keyword">string</span></span><br><span class="line">    prevHash   <span class="keyword">string</span></span><br><span class="line">    difficulty <span class="keyword">int</span></span><br><span class="line">    nonce      <span class="keyword">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> BlockChain <span class="keyword">struct</span> &#123;</span><br><span class="line">    sync.Mutex</span><br><span class="line">    blocks []Block</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(bc *BlockChain)</span> <span class="title">AddBlock</span><span class="params">(block Block)</span></span> &#123;</span><br><span class="line">    bc.Lock()</span><br><span class="line">    <span class="keyword">defer</span> bc.Unlock()</span><br><span class="line">    bc.blocks = <span class="built_in">append</span>(bc.blocks, block)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> blockchain BlockChain</span><br></pre></td></tr></table></figure><h2 id="Proof-of-Work"><a href="#Proof-of-Work" class="headerlink" title="Proof of Work"></a>Proof of Work</h2><p>生成区块的过程就相当于打磨珍珠的过程，只有符合要求的珍珠才能最终被加入到珍珠项链中去，那么话说回来生成区块的过程是怎么样的呢，对于一个特定的区块，需要不断改变其中一个值（nonce），这里的 <code>nonce</code> 值从0开始逐渐递增，然后计算特定 <code>nonce</code> 对应的区块哈希值，只有哈希值符合相应的要求之后，才能说这个区块是有效的，才能被加入到区块链中，生成区块的过程也被叫做挖矿。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">generateBlock</span><span class="params">(oldBlock Block, difficulty <span class="keyword">int</span>)</span> <span class="title">Block</span></span> &#123;</span><br><span class="line">    <span class="keyword">var</span> newBlock Block</span><br><span class="line"></span><br><span class="line">    newBlock.idx = oldBlock.idx + <span class="number">1</span></span><br><span class="line">    newBlock.timestamp = time.Now().String()</span><br><span class="line">    newBlock.prevHash = oldBlock.hash</span><br><span class="line">  newBlock.difficulty = diff</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i := <span class="number">0</span>; ; i++ &#123;</span><br><span class="line">        hex := fmt.Sprintf(<span class="string">"%x"</span>, i)</span><br><span class="line">        newBlock.nonce = hex</span><br><span class="line">        <span class="keyword">if</span> !isHashValid(calculateHash(newBlock), newBlock.difficulty) &#123;</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            fmt.Println(calculateHash(newBlock), <span class="string">" work done!"</span>)</span><br><span class="line">            newBlock.Hash = calculateHash(newBlock)</span><br><span class="line">            <span class="keyword">break</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> newBlock</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">calculateHash</span><span class="params">(block Block)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    record := strconv.Itoa(block.idx) + block.timestamp + block.prevHash + block.difficulty + block.nonce</span><br><span class="line">    h := sha256.New()</span><br><span class="line">    h.Write([]<span class="keyword">byte</span>(record))</span><br><span class="line">    hashed := h.Sum(<span class="literal">nil</span>)</span><br><span class="line">    <span class="keyword">return</span> hex.EncodeToString(hashed)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>那么什么样的区块才是有效的呢，简单来说就是对于一个哈希值，其开头部分都是0就可以了（0越多，难度越高）。像这种，找到答案很困难但验证答案却非常轻松的算法就是 <code>Proof of Work</code> 的精髓。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">isHashValid</span><span class="params">(hash <span class="keyword">string</span>, difficulty <span class="keyword">int</span>)</span> <span class="title">bool</span></span> &#123;</span><br><span class="line">    prefix := strings.Repeat(<span class="string">"0"</span>, difficulty)</span><br><span class="line">    <span class="keyword">return</span> strings.HasPrefix(hash, prefix)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="一个难度逐渐递增的区块链"><a href="#一个难度逐渐递增的区块链" class="headerlink" title="一个难度逐渐递增的区块链"></a>一个难度逐渐递增的区块链</h2><p>下面实现了一个难度逐渐递增的区块链，运行时就会发现产生区块的时间间隔越来越长，因为 <code>CPU</code> 需要经过更多的计算才能找到符合条件的哈希值。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    difficulty := <span class="number">1</span></span><br><span class="line">    genesisBlock := Block&#123;&#125;</span><br><span class="line">    genesisBlock = Block&#123;</span><br><span class="line">        idx:        <span class="number">0</span>, </span><br><span class="line">        timestamp:  time.Now().String(), </span><br><span class="line">        hash:       calculateHash(genesisBlock),</span><br><span class="line">        prevHash:   <span class="string">""</span>, </span><br><span class="line">        difficulty: difficulty, </span><br><span class="line">        nonce:      <span class="string">""</span>,</span><br><span class="line">    &#125;</span><br><span class="line">    blockchain.AddBlock(genesisBlock)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> block Block</span><br><span class="line">    block = genesisBlock</span><br><span class="line">    <span class="keyword">for</span> &#123;</span><br><span class="line">        block = generateBlock(block, diff)</span><br><span class="line">        difficulty++</span><br><span class="line">        blockchain.AddBlock(block)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;如果有时光机的话，我要做的第一件事情肯定就是穿梭回过去买比特币：），算了，不意淫了，还是学习要紧，虽然再也不能靠买比特币一夜暴富了，但是自己按照比特币实现一个山寨比特币的能力还是有的，比特币可以说是现在大红大紫的区块链的始祖，要全部了解它的原理可能还是要埋头啃个几个月的（并
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Magic Number</title>
-    <link href="https://oceanoverflow.github.io/2018/06/05/MagicNumber/"/>
-    <id>https://oceanoverflow.github.io/2018/06/05/MagicNumber/</id>
-    <published>2018-06-05T08:27:07.000Z</published>
-    <updated>2018-06-26T08:46:45.861Z</updated>
-    
-    <content type="html"><![CDATA[<p>微笑.jpg，这里年轻人们聊天时经常使用的说法，但是！作为一个严谨的程序员，我们能不能通过文件的后缀来判断这个文件的类型呢？例如看到电脑上存在“微笑.jpg”这个文件，通过后缀 <code>jpg</code> 来判断它就是一个 <code>JPEG</code> 文件呢，答案肯定是否定的，因为文件名可以被轻松篡改，例如这个文件本来是“微笑.gif”，有人想不开就将它改成“微笑.jpg”，虽然没有什么影响，但是可以说明一个问题，我们不能通过文件后缀来判断文件的类型。</p><p>如果不使用文件后缀，我们应该如何判断文件的类型呢，答案就是我们今天要讨论的<code>Magic Number</code> ，即魔术数，因为文件的本质就是字节数组，所以在一般的操作系统中，对于特定类型的文件，其开头的几个字节都是相同的，例如对于 <code>JPEG</code> 格式的文件，开头的字节都是 <code>\xff\xd8\xff</code> ，我们可以通过读取文件开头的字节来确定文件的类型，这种方法准确性更高。</p><p>下面我们准备一个魔术数到类型的字典，注意，这里只列举了几个例子，还可以按照这样的格式增加字典项。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> magicNumber = <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span> &#123;</span><br><span class="line">    <span class="string">"\xff\xd8\xff"</span>:      <span class="string">"image/jpeg"</span>,</span><br><span class="line">    <span class="string">"\x89PNG\r\n\x1a\n"</span>: <span class="string">"image/png"</span>,</span><br><span class="line">    <span class="string">"GIF87a"</span>:            <span class="string">"image/gif"</span>,</span><br><span class="line">    <span class="string">"GIF89a"</span>:            <span class="string">"image/gif"</span>,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getFileType</span><span class="params">(incipit []<span class="keyword">byte</span>)</span> <span class="title">string</span></span> &#123;</span><br><span class="line">    incipitStr := <span class="keyword">string</span>(incipit)</span><br><span class="line">    <span class="keyword">for</span> magic, mime := <span class="keyword">range</span> magicNumber &#123;</span><br><span class="line">        <span class="keyword">if</span> strings.HasPrefix(incipitStr, magic) &#123;</span><br><span class="line">            <span class="keyword">return</span> mime</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">""</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>真正匹配格式的逻辑比较简单，遍历 <code>magicNumber</code> 这个 <code>map</code> ，判断每个 <code>key</code> 是不是某个字符串的前缀，因为魔术数符合前缀编码的特点，即任何一个编码都不是另一个编码的前缀，所以我们能保证判断文件类型时，不会有二义。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">    filepath := os.Args[<span class="number">1</span>]</span><br><span class="line">    file, err := os.Open(filepath)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">defer</span> file.Close()</span><br><span class="line"></span><br><span class="line">    buff := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">512</span>)</span><br><span class="line">    _, err = file.Read(buff)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="built_in">panic</span>(err)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    file.Seek(<span class="number">0</span>, os.SEEK_SET)</span><br><span class="line">    typ := getFileType(buff)</span><br><span class="line">    fmt.Println(typ)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="gate-upload"><a href="#gate-upload" class="headerlink" title="gate upload"></a>gate upload</h2><p>下面我们来看一个 <code>Magic Number</code> 的应用场景，例如我们有一个图片上传程序，但是只能允许上传 <code>JPEG</code> 格式的文件，给定一个 <code>io.Reader</code> ， 我们先读取前两个字节，判断其值是否等于 <code>JPEG</code> 的 <code>Magic Number</code> ，如果不等，则直接停止上传，如果相等，则继续上传。由于此时 <code>r</code> 已经读取了两个字节了，所以需要重新构造一个 <code>io.Reader</code>（ <code>r := io.MultiReader(bytes.NewReader(b), r)</code> ）继续上传。利用 <code>Magic Number</code> 我们可以避免将整个文件读入内存中，增加程序的运行效率。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">handleUpload</span><span class="params">(r io.Reader)</span> <span class="title">error</span></span> &#123;</span><br><span class="line">    b := <span class="built_in">make</span>([]<span class="keyword">byte</span>, <span class="number">2</span>)</span><br><span class="line">    _, err := r.Read(b)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    jpeg := []<span class="keyword">byte</span>&#123;<span class="number">0xFF</span>, <span class="number">0xD8</span>&#125;</span><br><span class="line">    <span class="keyword">if</span> bytes.Equal(b, jprg) &#123;</span><br><span class="line">        <span class="keyword">return</span> error.New(<span class="string">"not a JPEG"</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    r := io.MultiReader(bytes.NewReader(b), r)</span><br><span class="line"></span><br><span class="line">    err = uploadFile(r)</span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;微笑.jpg，这里年轻人们聊天时经常使用的说法，但是！作为一个严谨的程序员，我们能不能通过文件的后缀来判断这个文件的类型呢？例如看到电脑上存在“微笑.jpg”这个文件，通过后缀 &lt;code&gt;jpg&lt;/code&gt; 来判断它就是一个 &lt;code&gt;JPEG&lt;/code&gt; 文件呢，
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Raft</title>
-    <link href="https://oceanoverflow.github.io/2018/06/03/Raft/"/>
-    <id>https://oceanoverflow.github.io/2018/06/03/Raft/</id>
-    <published>2018-06-03T12:59:23.000Z</published>
-    <updated>2018-06-26T08:48:15.739Z</updated>
-    
-    <content type="html"><![CDATA[<ul><li>Raft stands for Replicated and Fault Tolerant</li><li>Raft is something you can build out of a collection of logs</li><li>Raft is something you can use to get away from the island of Paxos</li></ul><h2 id="Goal-Replicated-Log"><a href="#Goal-Replicated-Log" class="headerlink" title="Goal: Replicated Log"></a>Goal: Replicated Log</h2><ul><li>Replicated log =&gt; replicated state machine<ul><li>All servers execute same commands in same order</li></ul></li><li>Consensus module ensures proper log replication</li><li>System makes progress as long as any majority of servers are up</li><li>Failure model: fail-stop(not Byzantine), delayed/lost messages    </li></ul><h2 id="Approaches-to-Consensus"><a href="#Approaches-to-Consensus" class="headerlink" title="Approaches to Consensus"></a>Approaches to Consensus</h2><p>Two possible approaches to consensus:</p><ul><li>Symmetric, leader-less:<ul><li>All servers have equal roles</li><li>Clients can contact any server </li></ul></li><li>Asymmetric, leader-based:<ul><li>At any given time, one server is in charge, others accept its decision</li><li>Clients communicate with the leader </li></ul></li><li>Raft uses a leader:<ul><li>Decomposes the problem (normal operation, leader changes)</li><li>Simplifies normal operation (no conflicts)</li><li>More efficient than leader-less approaches  </li></ul></li></ul><h2 id="Leader-Election"><a href="#Leader-Election" class="headerlink" title="Leader Election"></a>Leader Election</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">                  +------------------+</span><br><span class="line">                  | Become Candidate |</span><br><span class="line">                  +------------------+</span><br><span class="line">                           |</span><br><span class="line">                           v</span><br><span class="line">                   +---------------+    timeout</span><br><span class="line">                   | currentTerm++ |&lt;--------------+</span><br><span class="line">                   | vote for self |               |</span><br><span class="line">                   +---------------+               |</span><br><span class="line">                           |                       |</span><br><span class="line">                           v                       |</span><br><span class="line">               +-----------------------+           |</span><br><span class="line">               | Send RequestVote RPCs |-----------+</span><br><span class="line">               |    to other servers   |</span><br><span class="line">               +-----------------------+</span><br><span class="line">votes from majority |              | RPC from Leader</span><br><span class="line">                    v              v</span><br><span class="line">           +----------------+  +---------+</span><br><span class="line">           | Become Leader, |  | Become  |</span><br><span class="line">           | send heartbeats|  | Follower|</span><br><span class="line">           +----------------+  +---------+</span><br></pre></td></tr></table></figure><ul><li>Safety: allow at most one winner per term<ul><li>Each server gives only one vote per term(persist on disk)</li><li>Majority required to win election</li></ul></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">   B can&apos;t also                  Voted for</span><br><span class="line">   get majority                candidate A</span><br><span class="line">+-----------------+     +-------------------------+</span><br><span class="line">| +-----+ +-----+ |     | +-----+ +-----+ +-----+ |     </span><br><span class="line">| |     | |     | |     | |     | |     | |     | | </span><br><span class="line">| +-----+ +-----+ |     | +-----+ +-----+ +-----+ |</span><br><span class="line">+-----------------+     +-------------------------+</span><br><span class="line">                  Servers</span><br></pre></td></tr></table></figure><ul><li>Livebess: some candidate must eventually win<ul><li>Choose election timeout randomly in [T, 2T] (e.g. 150-300ms)</li><li>One server usually times out and wins election before others time out</li><li>Works well if T &gt;&gt; broadcast time</li></ul></li></ul><p>Randomized approach simpler than ranking</p><h2 id="Normal-Operation"><a href="#Normal-Operation" class="headerlink" title="Normal Operation"></a>Normal Operation</h2><ul><li>Client sends command to leader</li><li>Leader appends command to its log</li><li>Leader send AppendEntries RPCs to all followers</li><li>Once new entry committed<ul><li>Leader executes command in its state machine, returns result to client</li><li>Leader notifies followers of committed entries in subsequent AppendEntries RPCs</li><li>Followers execute committed commands in their state machines  </li></ul></li><li>Crashed/slow followers<ul><li>Leader retries AppendEntries RPCs until they succeed</li></ul></li><li>Optimal performance in common case:<ul><li>One successful RPC to any majority of servers</li></ul></li></ul><h2 id="Log-Structure"><a href="#Log-Structure" class="headerlink" title="Log Structure"></a>Log Structure</h2><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Command <span class="keyword">string</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Log <span class="keyword">struct</span> &#123;</span><br><span class="line">    Term <span class="keyword">int</span></span><br><span class="line">    Command Command</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Logs []Log</span><br></pre></td></tr></table></figure><ul><li>Must survive crashes (store on disk)</li><li>Entry committed if safe to execute in state machines<ul><li>Replicated on majority of servers by leader of its term</li></ul></li></ul><h2 id="Log-Inconsistencies"><a href="#Log-Inconsistencies" class="headerlink" title="Log Inconsistencies"></a>Log Inconsistencies</h2><p>Crashes can result in log inconsistencies</p><ul><li>Raft minimizes special code for repairing inconsistencies<ul><li>Leader assumes its log is correct</li><li>Normal operation will repair all inconsistencies </li></ul></li></ul>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;ul&gt;
-&lt;li&gt;Raft stands for Replicated and Fault Tolerant&lt;/li&gt;
-&lt;li&gt;Raft is something you can build out of a collection of logs&lt;/li&gt;
-&lt;li&gt;Raft is
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Replicated Service Client</title>
-    <link href="https://oceanoverflow.github.io/2018/06/02/ReplicatedServiceClient/"/>
-    <id>https://oceanoverflow.github.io/2018/06/02/ReplicatedServiceClient/</id>
-    <published>2018-06-02T07:01:00.000Z</published>
-    <updated>2018-06-26T08:48:13.702Z</updated>
-    
-    <content type="html"><![CDATA[<p>Self-explanatory :-)<br>Actually cause I feel lazy today.</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> ReplicatedClient <span class="keyword">interface</span> &#123;</span><br><span class="line">    <span class="comment">// Init initializes the client to use the given servers.</span></span><br><span class="line">    <span class="comment">// To make a particular request later,</span></span><br><span class="line">    <span class="comment">// the client can use callOne(srv, args), where srv </span></span><br><span class="line">    <span class="comment">// is one of the servers from the list</span></span><br><span class="line">    Init(servers []<span class="keyword">string</span>, callOne(<span class="keyword">string</span>, Args) Reply)</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// Call makes a request to an available server.</span></span><br><span class="line">    <span class="comment">// Multiple gouroutines may call Call concurrently.</span></span><br><span class="line">    Call(args Args) Reply </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Client <span class="keyword">struct</span> &#123;</span><br><span class="line">    servers []<span class="keyword">string</span></span><br><span class="line">    callOne <span class="function"><span class="keyword">func</span><span class="params">(<span class="keyword">string</span>, Args)</span> <span class="title">Reply</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function">    <span class="title">mu</span> <span class="title">sync</span>.<span class="title">Mutex</span></span></span><br><span class="line"><span class="function">    <span class="title">prefer</span> <span class="title">int</span></span></span><br><span class="line"><span class="function">&#125;</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">func</span> <span class="params">(c *Client)</span> <span class="title">Init</span><span class="params">(servers []<span class="keyword">string</span>, callOne <span class="keyword">func</span>(<span class="keyword">string</span>, Args)</span> <span class="title">Reply</span>)</span> &#123;</span><br><span class="line">    c.servers = servers</span><br><span class="line">    c.callOne = callOne</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *Client)</span> <span class="title">Call</span><span class="params">(args Args)</span> <span class="title">Reply</span></span> &#123;</span><br><span class="line">    <span class="keyword">type</span> result <span class="keyword">struct</span> &#123;</span><br><span class="line">        serverID <span class="keyword">int</span></span><br><span class="line">        reply Reply</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> timeout = <span class="number">1</span> * time.Second</span><br><span class="line">    t := time.NewTimer(timeout)</span><br><span class="line">    <span class="keyword">defer</span> t.Stop()</span><br><span class="line"></span><br><span class="line">    done := <span class="built_in">make</span>(<span class="keyword">chan</span> result, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">    c.mu.Lock()</span><br><span class="line">    prefer := c.prefer</span><br><span class="line">    c.mu.Unlock()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> r result</span><br><span class="line">    <span class="keyword">for</span> off := <span class="number">0</span>; off &lt; <span class="built_in">len</span>(c.servers); off++ &#123;</span><br><span class="line">        id := (prefer + off) % <span class="built_in">len</span>(c.servers)</span><br><span class="line">        <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">            done &lt;- result&#123;id, c.callOne(c.servers[id], args)&#125;</span><br><span class="line">        &#125;()</span><br><span class="line">        <span class="keyword">select</span> &#123;</span><br><span class="line">        <span class="keyword">case</span> r = &lt;-done:</span><br><span class="line">            goro Done</span><br><span class="line">        <span class="keyword">case</span> &lt;-t.C:</span><br><span class="line">            t.Reset(timeout)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">Done:</span><br><span class="line">    c.mu.Lock()</span><br><span class="line">    c.prefer = r.serverID</span><br><span class="line">    c.mu.Unlock()</span><br><span class="line">    <span class="keyword">return</span> r.reply  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;Self-explanatory :-)&lt;br&gt;Actually cause I feel lazy today.&lt;/p&gt;
-&lt;figure class=&quot;highlight golang&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span c
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-  <entry>
-    <title>Semaphore</title>
-    <link href="https://oceanoverflow.github.io/2018/06/01/Semaphore/"/>
-    <id>https://oceanoverflow.github.io/2018/06/01/Semaphore/</id>
-    <published>2018-06-01T13:07:44.000Z</published>
-    <updated>2018-06-26T08:48:01.794Z</updated>
-    
-    <content type="html"><![CDATA[<p>现在要完成一个非常简单的任务，给定很多图片的 <code>URL</code> ，将它们下载到本地，你会怎么做？</p><h2 id="Sequential"><a href="#Sequential" class="headerlink" title="Sequential"></a>Sequential</h2><p>如果你想也不想，就写下了下面这种代码，说明你是一个能干活的程序员，但这并不意味着你是一个优秀的程序员。下面的代码虽然没有什么致命的错误，但是效率非常低，程序运行时 <code>CPU</code> 大部分时间都在等待网络 <code>I/O</code> 而处于空闲状态，导致 <code>CPU</code> 的利用率非常低。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> idx, task := <span class="keyword">range</span> tasks &#123;</span><br><span class="line">    <span class="keyword">if</span> err := Do(idx, task); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        fmt.Println(err)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="Parallel"><a href="#Parallel" class="headerlink" title="Parallel"></a>Parallel</h2><p>这种完全由相互独立的子任务组成的任务，被称为 <em>embarrassingly parallel</em> ，这种问题可以通过并行的方法提高程序的性能，而且并行程度越高，性能越好，在程序中我们通过添加 <code>go</code> 这个关键字来创建多个 <code>goroutine</code> ，使多个子任务并发执行，以减少网络 <code>I/O</code> 延迟，提高 <code>CPU</code> 的利用率 。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line"><span class="keyword">for</span> idx, task := <span class="keyword">range</span> tasks &#123;</span><br><span class="line">    wg.Add(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(i <span class="keyword">int</span>, v <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> wg.Done()</span><br><span class="line">        <span class="keyword">if</span> err := Do(i, v); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            fmt.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;(idx, task)</span><br><span class="line">&#125;</span><br><span class="line">wg.Wait()</span><br></pre></td></tr></table></figure><h2 id="Parallel-with-Semaphore"><a href="#Parallel-with-Semaphore" class="headerlink" title="Parallel with Semaphore"></a>Parallel with Semaphore</h2><p>但是通过创建多个 <code>goroutine</code> 提高并行度从而提高性能的方法有其局限性，例如一次性创建过多的网络连接，超出了进程打开文件的数量限制时，程序就会报错。所以我们需要限制单位时间内并行程序的个数，通过信号量（ <code>semaphore</code> ）来限制并行度。在 <code>golang</code> 中，我们可以使用容量为 n 的 <code>buffered channel</code> 来模拟 <code>counting semaphore</code> ，这样以来在每个子任务执行前需要通过 <code>sem &lt;- struct{}{}</code> 来获取执行许可，如果 <code>sem</code> 通道已满，说明当前已经有n个子任务正在执行，该操作就会阻塞等待，直到通道空闲。当任务执行完成后，使用 <code>&lt;-sem</code> 释放执行许可。</p><figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">sem := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;, <span class="number">8</span>) <span class="comment">// 8 jobs at once</span></span><br><span class="line"><span class="keyword">var</span> wg sync.WaitGroup</span><br><span class="line"><span class="keyword">for</span> idx, task := <span class="keyword">range</span> tasks &#123;</span><br><span class="line">    wg.Add(<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(i <span class="keyword">int</span>, v <span class="keyword">string</span>)</span></span> &#123;</span><br><span class="line">        <span class="keyword">defer</span> wg.Done()</span><br><span class="line">        sem &lt;- <span class="keyword">struct</span>&#123;&#125;&#123;&#125;</span><br><span class="line">        <span class="keyword">if</span> err := Do(i, v); err != <span class="literal">nil</span> &#123;</span><br><span class="line">            fmt.Println(err)</span><br><span class="line">        &#125;</span><br><span class="line">        &lt;-sem</span><br><span class="line">    &#125;(idx, task)</span><br><span class="line">&#125;</span><br><span class="line">wg.Wait()</span><br><span class="line"><span class="built_in">close</span>(sem)</span><br></pre></td></tr></table></figure>]]></content>
-    
-    <summary type="html">
-    
-      
-      
-        &lt;p&gt;现在要完成一个非常简单的任务，给定很多图片的 &lt;code&gt;URL&lt;/code&gt; ，将它们下载到本地，你会怎么做？&lt;/p&gt;
-&lt;h2 id=&quot;Sequential&quot;&gt;&lt;a href=&quot;#Sequential&quot; class=&quot;headerlink&quot; title=&quot;Sequenti
-      
-    
-    </summary>
-    
-    
-  </entry>
-  
-</feed>
diff --git a/dep.md b/dep.md
new file mode 100644
index 0000000..1e7b491
--- /dev/null
+++ b/dep.md
@@ -0,0 +1,100 @@
+# dep
+
+  在写大型工程项目的时候，难免会依赖第三方的库（自己重复造轮子肯定不现实），如果依赖的库数量非常多时，自己去手动管理肯定是不现实的，所以我们需要一个依
+赖管理工具帮助我们管理依赖的库。就像 `node` 有 `npm` ，`java` 有 `maven` 。而 `golang` 之前一直没有一个官方推荐的依赖管理工具，所以第三方的依赖
+管理工具 `glide` ，`govendor` 之类的就应运而生，但由于不是官方出品的，自己用起来心里总有些毛毛的，后来，`golang` 官方终于推出了 `dep` 这个依赖管
+理工具，终于给我们这些强迫症患者安了一个心。下面我们就以一个demo为例子，看看`dep` 如何使用吧。
+
+![godep](https://github.com/golang/dep/raw/master/docs/assets/DigbyShadows.png)
+
+## 安装
+
+  由于 `dep` 是一个命令行工具，安装起来也非常的方便，下面给出两种安装方式。
+
+#### 二进制安装
+
+  这种安装方法通用型比较强，下面的命令会根据你的操作系统直接安装相应的二进制。
+
+`$ curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh`
+
+#### macOS 安装
+
+  但是 `macOS` 用户一般还是比较习惯于使用`brew` 的，使用 `brew` 也是`no-brainer` 。
+
+```
+$ brew install dep
+$ brew upgrade dep
+```
+
+## vendor 机制
+  要了解 `dep` 存在的必要性就不得不提 `vendor` 机制了，我们都知道如果我们在 `go` 文件中导入一个非标准库，在编译时 `go` 会在 `$GOPATH` 下面去寻
+找它，但是这就导致一个问题，如果两个项目A和B同时用到了这个库，但是A和B对这个库的版本需求是不同的，这样就很难办了，毕竟在 `$GOPATH` 下面只能存在一个
+版本的库，所以为了解决这种情况，在`Go1.5`的时候，就出现 `vendor` 文件夹这个机制，也就是说，`go` 在编译项目的时候，会去这个项目目录下面寻找是否存在
+`vendor` 这个文件夹，并且 `vendor` 下面是否存在我们需要的库，如果有则使用它，如果没有则去 `$GOPATH` 下去寻找。
+
+  例如项目C依赖 `github.com/aaa/bbb` 这个库，那么 `go` 在编译时回去查看当前项目目录下有没有 `vendor/github.com/aaa/bbb` 这个文件夹目录，如
+果有则使用这个版本，如果没有再去 `$GOPATH` 下面去找。而 `dep` 就是为了帮我们管理 `vendor` 这个目录下面的依赖而存在的。
+
+## 新建项目
+  例如我们要写一个与 `WebSocket` 相关的项目，无奈 `golang` 的标准库里实现的 `WebSocket` 我们并不是非常满意，所以我们去 `github` 上面搜了一下
+，最后发现 `girilla` 家的 `websocket` 库还是比较符合我们项目的需求的，所以决定使用它。
+
+  第一步就是新建一个 `dep` 项目，使用 `dep init` 命令，会帮我们生成两个文件和一个空的 `vendor` 文件夹。
+
+```
+$ dep init
+$ ls
+Gopkg.toml Gopkg.lock vendor/
+```
+
+  然后我们写了一个 `main.go` 文件用于存放我们项目的所有逻辑（bad practice），这个文件除了标准库之外当然还导入了我们需要的 `websocket` 依赖。
+
+```golang
+import (
+    "flag"
+    "html/template"
+    "io/ioutil"
+    "log"
+    "net/http"
+    "os"
+    "strconv"
+    "time"
+    
+    "github.com/gorilla/websocket"
+)
+```
+
+  编辑完之后，在命令行中输入 `dep ensure` ，`dep` 会扫描我们当前项目中所有的依赖，并找出我们依赖的三方库，然后更新相应的文件（Gopkg.toml 和
+Gopkg.lock），并更新我们的 `vendor` 文件夹，如下所示。
+
+```
+.
+├── Gopkg.lock
+├── Gopkg.toml
+├── main.go
+└── vendor
+    └── github.com
+        └── gorilla
+            └── websocket
+                ├── AUTHORS
+                ├── LICENSE
+                ├── README.md
+                ├── client.go
+                ├── client_clone.go
+                ├── client_clone_legacy.go
+                ├── compression.go
+                ├── conn.go
+                ├── conn_read.go
+                ├── conn_read_legacy.go
+                ├── doc.go
+                ├── json.go
+                ├── mask.go
+                ├── mask_safe.go
+                ├── prepared.go
+                ├── server.go
+                └── util.go
+```
+
+## 总结
+
+  反正以后用 `dep` 作为go项目的依赖管理工具准没错的，如果你用 `glide` 或者 `govendor` 之类的还是趁早投靠 `dep` 吧。
diff --git a/etcd.md b/etcd.md
new file mode 100644
index 0000000..fbb1b35
--- /dev/null
+++ b/etcd.md
@@ -0,0 +1,221 @@
+# 使用 etcd 来提供服务注册与发现功能
+ 
+  `etcd` 是一个用于存储分布式系统中重要数据结构的存储引擎，而其本身就是一个分布式的键值数据库，例如在微服务架构中的服务注册和发现机制，就可以利用
+`etcd` 作为我们的注册中心进行服务，用于存储服务注册信息。
+
+  但是，什么又是服务注册和发现呢，其实这和现在盛行的微服务架构有着密切的联系，在以前那种非微服务时代，应用运行在物理机上面，服务实例对应的网络地址也是
+相对固定不变的，而到了微服务时代，很多服务实例的网络地址则是动态分配的，而且服务实例也经常面临着失败或者更新的情况，所以这些服务实例对应的网络地址也经
+常会变化，这对应用的开发者和使用者都是非常不利的，所以引入服务注册和发现这种机制，来适应微服务的这种问题。
+
+![alt text](https://code.aliyun.com/middlewarerace2018/docs/raw/master/assets/dubbo-architecture.png)
+
+  我们以 `Dubbo` 中的服务注册与发现为例，深入理解一下到底什么是服务注册与发现，这里有几个角色需要注意一下，`Registry` 用于服务信息的登记和提供，
+`Provider` 是服务的提供商，它会将自己提供的服务信息注册到`Registry` 上，而 `Consumer` 则是相应服务的消费者，它会从 `Registry` 那里获取服务的
+信息（一般来说就是接口的地址），再调用 `Provider` 上提供的真实服务，`Monitor` 这里仅仅作为记录一些调用次数之类的元信息。注意到这里 `Registry` 
+通知 `Consumer` 服务信息是一个异步的过程，而 `Consumer` 调用 `Provider` 的服务则是同步的。
+
+  `etcd` 底层使用 `raft` 协议来维持集群中服务器间数据的一致性，这在之后的博客中会详细探讨。而 `etcd` 也提供了非常简单的客户端接口供我们使用，今天
+我们的目标就是写一个 `etcd` 的客户端供我们进行服务注册和发现等相关方面的使用。
+
+  `etcd` 无论作为什么用途，其本质都是一个kv存储引擎，而我们要实现的客户端必须提供以下接口的服务。例如向 `etcd` 写入键值对，获取相应键对应的值，还有
+获取相应键最新值的机制（通过watch机制）等等。
+
+```golang
+type Store interface {
+    Put(key string, value []byte, options *WriteOptions) error
+    Get(key string) (*KVPair, error)
+    Delete(key string) error
+    Exists(key string) (bool, error)
+    Watch(key string, stopCh <-chan struct{}) (<-chan *KVPair, error)
+    WatchTree(directory string, stopCh <-chan struct{}) (<-chan []*KVPair, error)
+    NewLock(key string, options *LockOptions) (Locker, error)
+    List(directory string) ([]*KVPair, error)
+    DeleteTree(directory string) error
+    AtomicPut(key string, value []byte, previous *KVPair, options *WriteOptions) (bool, *KVPair, error)
+    AtomicDelete(key string, previous *KVPair) (bool, error)
+    Close() 
+}
+
+type KVPair struct {
+    Key       string
+    Value     []byte
+    LastIndex uint64
+}
+
+type WriteOptions struct {
+    IsDir bool
+    TTL   time.Duration
+}
+
+type LockOptions struct {
+    Value     []byte
+    TTL       time.Duration
+    RenewLock chan struct{}
+}
+```
+
+  `etcd` 官方已经给我们提供了一个client接口了（ github.com/coreos/etcd/client），我们只要在文件头导入它就行了。
+
+`import etcd "github.com/coreos/etcd/client`
+
+  我们对该服务进行一层封装以便实现我们的 `Store` 接口。
+
+```golang
+type Etcd struct {
+    client etcd.KeysAPI
+}
+
+func New(addrs []string, options *Config) (Store, error) {
+    s := &Etcd{}
+
+    cfg := &etcd.Config{
+        Endpoints:               entries,
+        Transport:               etcd.DefaultTransport,
+        HeaderTimeoutPerRequest: 3 * time.Second,
+    }
+
+    // Set options
+    if options != nil {
+        if options.TLS != nil {
+            setTLS(cfg, options.TLS, addrs)
+        }
+        if options.ConnectionTimeout != 0 {
+            setTimeout(cfg, options.ConnectionTimeout)
+        }
+        if options.Username != "" {
+            setCredentials(cfg, options.Username, options.Password)
+        }
+    }
+    
+    c, err := etcd.New(*cfg)
+    if err != nil {
+        log.Fatal(err)
+    }
+
+    s.client = etcd.NewKeysAPI(c)
+
+    // Periodic Cluster Sync
+    go func() {
+        for {
+            if err := c.AutoSync(context.Background(), periodicSync); err != nil {
+                return
+            }
+        }
+    }()
+
+    return s, nil
+}
+```
+
+  当然，客户端与 `etcd` 服务器的通信一般都不是明文传输的，所以还需要定义用于传输加密相关的结构体。一般在通信过程中会使用TLS加密，所以安全性问题我们
+就可以不用担心了。
+
+```golang
+type Config struct {
+    ClientTLS         *ClientTLSConfig
+    TLS               *tls.Config
+    ConnectionTimeout time.Duration
+    Bucket            string
+    PersistConnection bool
+    UserName          string
+    Password          string
+}
+
+type ClientTLSConfig struct {
+    CertFile   string
+    KeyFile    string
+    CACertFile string
+}
+```
+
+  下面我们来重点看一下三个接口的实现，分别是 `Put` ，`Get` 和 `Watch` ，分别应对现实生活中，`Provider` 向 `etcd` 写入可以提供的服务信息，
+`Consumer` 在 `etcd` 中读取服务信息，还有就是在 `etcd` 上注册的服务信息改变时，`Consumer` 可以及时获得改变后的值。
+
+  `Get` 操作获取当前 `etcd` 已经注册的服务信息，也就是服务发现的过程。
+
+```golang
+func (s *Etcd) Get(key string) (pair *KVPair, err error) {
+    getOpts := &etcd.GetOptions{
+        Quorum: true,
+    }
+
+    result, err := s.client.Get(context.Background(), s.normalize(key), getOpts)
+
+    if err != nil {
+        return nil, err
+    }
+
+    pair = &KVPair{
+        Key:       key,
+        Value:     []byte(result.Node.Value)
+        LastIndex: result.Node.ModifieIndex,
+    }
+
+    return pair, nil
+}
+```
+
+  `Put` 操作可以向 `etcd` 注册相应的服务信息，简单的说就是服务注册。
+
+```golang
+func (s *Etcd) Put(key string, value []byte, opts *WriteOptions) error {
+    setOpts := &etcd.SetOptions{}
+
+    if opts != nil {
+        setOpts.Dir = opts.IsDir
+        setOpts.TTL = opts.TTL
+    }
+
+    _, err := s.client.Set(context.Background(), s.normalize(key), string(value), setOpts)
+    return err
+}
+```
+
+  当我们关心的某一项键值（对应服务）发生变化时候，我们需要及时获取最新的值以免我们的服务出现过期不可用的情况，例如我们我们提供服务的服务端的一个实例
+挂掉了，某些编排系统如 `k8s` 会自动重启这些实例，但是重启后的实例的服务地址可能会出现改变，我们使用这些服务的客户端肯定需要知道更新过后的值，通过
+`watch` 机制就可以及时获取更新后的键值对。
+
+```golang
+func (s *Etcd) Watch(key string, stopCh <-chan struct{}) (<-chan *KVPair, error) {
+    opts := &etcd.WatcherOptions{Recursive: false}
+    watcher := s.client.Watcher(s.normalize(key), opts)
+    watchCh := make(chan *KVPair)
+
+    go func() {
+        defer close(watchCh)
+
+        pair, err := s.Get(key)
+        if err != nil {
+            return
+        }
+
+        watchCh <- pair
+        for {
+            select {
+            case <-stopCh:
+                return
+            default:
+            }
+           
+            result, err := watcher.Next(context.Background())
+            if err != nil {
+                return
+            }
+
+            watchCh <- KVPair{
+                Key:       key,
+                Value:     []byte(result.Node.Value),
+                LastIndex: result.Node.ModifiedIndex,
+            }
+        }
+    }()
+
+    retrun watchCh, nil
+}
+```
+
+### 后记
+
+  主要是笔者最近要参加阿里的第四届中间件大赛，所以对服务注册和发现做了一些调研工作。在像阿里这种大公司就会提供各种各样的服务端口，而且由于分布式的特性
+，服务间通讯就变得尤为重要，通常服务提供者暴露服务，服务消费者调用服务，而它们之间的中介服务通常就由`etcd`，`consul` 或者 `zookeeper` 这样的高性
+能键值数据库来提供。
diff --git a/favicon.png b/favicon.png
deleted file mode 100644
index 9bde79f..0000000
Binary files a/favicon.png and /dev/null differ
diff --git a/gRPC.md b/gRPC.md
new file mode 100644
index 0000000..a86b6c2
--- /dev/null
+++ b/gRPC.md
@@ -0,0 +1,194 @@
+# gRPC
+  
+  首先，在了解 `gRPC` 之前，要搞清楚什么是 `RPC` ，`RPC` ， `Remote Procedure Call` ，即远程过程调度，它采用 `C/S`模型，本质就是客户端通过网
+络向远程计算机程序也就是服务端发送请求服务，远程服务器执行后向客户端返回答复，`RPC` 是分布式系统中非常重要的一个组成部分。
+
+  `RPC` 和本地方法调用最大的区别就在于程序是否在一个地址空间内执行，那么我们为什么要用到 `RPC` 呢，例如我们要写一个分布式爬虫的框架，因为自己的笔记
+本电脑处理能力有限，为了提高爬虫效率，我们租借了几台 `8C16G` 的高性能服务器帮我们完成任务，这样就可以由客户端发送爬虫指令，具体的粗活累活可以由服务器
+代替完成，如下面 `client` 向服务器发送一个 `crawl request` ，里面包含了我们要爬取的网站的具体信息，在服务器完成任务之后，向 `client` 返回一个
+`crawl response`，也就是爬虫的结果。
+
+![grpc](https://camo.githubusercontent.com/e4deb67aa41f71d46774f192b05b75be5c3da112/68747470733a2f2f7261772e6769746875622e636f6d2f6875696368656e2f7a6572672f6d61737465722f646f632f7a6572672e706e67)
+
+  关于 `RPC` ，不同的语言有不同的解决方案，例如在golang的标准库中就提供了 `net/rpc` 这个解决方案，虽然这个方法效率很高，但是它的缺点也是比较致命
+的，就是它仅能在golang程序中使用，而我们今天的主角，`gRPC` 就是一个跨语言平台的通用高性能 `RPC` 库，听着是不是很酷炫，下面就让我们来仔细学习一下吧
+。
+
+## 利用gRPC定义我们的服务
+
+  在使用 `gRPC` 之前我们需要安装它，在命令行中输入以下命令。
+
+`$ go get -u google.golang.org/grpc`
+
+  `gRPC` 在定义服务时采用了 `protobuf` 的语法格式，我们需要定义 `gRPC` 中请求消息和答复消息的数据格式，这个我们应该已经非常熟悉了，就是定义两个
+`message` （详情可以参考 `protobuf` 的官方文档），`CrawlRequest` 和 `CrawlResponse` ，除此之外我们还要定义一个 `service` ，说白了也就是我
+们要定义的 `RPC` 方法。也就是说我们向服务器发送一个 `CrawlRequest` 消息，服务器处理完成后会向我们返回一个 `CrawlResponse` 。
+
+```protobuf
+service Crawl {
+    rpc Crawl (CrawlRequest) returns (CrawlResponse) {}
+}
+
+message CrawlRequest {
+    string url = 1;
+    int64 timeout = 2;
+}
+
+message CrawlResponse {
+    string content = 1;
+}
+```
+
+  使用 `gRPC` 的好处就在于它可以根据我们定义的服务自动生成相应的服务端和客户端的代码，也就是说我们只要关心具体调用服务的逻辑，剩下具体的实现由框架帮
+我们干就可以了。
+
+  由于是 `protobuf` 文件，我们使用 `protoc` 来编译它就可以了。
+
+`$ protoc --go_out=plugins=grpc:. *.proto`
+
+## gRPC 原理
+
+  `gRPC` 相当于给我们一个框架，具体的代码就在我们的 `crawl.proto` 这个文件经过 `protoc` 编译后的得到的 `crawl.pb.go` 这个文件中，下面的代码
+都是由 `protoc` 经过编译后自动生成的，编译后的文件都具有类似的格式，基本看一个例子就可以一通百通了。
+
+  编译后得到的代码在客户端部分定义了一个大写的 `CrawlClient` 这个interface，而小写的 `crawlClient` 结构体则具体实现了它，注意到一个
+`crawlClient` 中包含了一个`grpc.ClientConn` 结构体，与 `net.Conn` 类似，它是真正发送网络请求的结构体，`grpc.Invoke` 则才是具体发送网络请求
+的行为。
+
+```golang
+type CrawlClient interface {
+    Crawl(ctx context.Context, in *CrawlRequest, opts ...grpc.CallOption) (*CrawlResponse, error)
+}
+
+type crawlClient struct {
+    cc *grpc.ClientConn
+}
+
+type NewCrawlClient(cc *grpc.ClientConn) CrawlClient {
+    return &crawlClient{cc}
+}
+
+func (c *crawlClient) Crawl(ctx context.Context, 
+                            in *CrawlRequest, 
+                            opts ...grpc.CallOption) (*CrawlResponse, error) {
+    out := new(CrawlResponse)
+    err := grpc.Invoke(ctx, "/protos.Crawl/Crawl", in, out, c.cc, opts...)
+    if err != nil {
+        return nil, err
+    }
+    return out, nil
+}
+```
+
+  与 `CrawClient` 不同的是，并没有结构体直接实现 `CrawlServer` 这个接口，毕竟 `gRPC` 仅仅是一个框架，具体的逻辑代码还是需要我们自己去填充的。
+`RegisterCrawlServer` 方法则向 `gRPC` 注册该服务，注册的过程也需要我们自己在代码中调用。
+
+```golang
+type CrawlServer interface {
+    Crawl(context.Context, *CrawlRequest) (*CrawlResponse, error)
+}
+
+func RegisterCrawlServer(s *grpc.Server, srv CrawlServer) {
+    s.RegisterService(&_Crawl_serviceDesc, srv)
+}
+
+func _Crawl_Crawl_Handler(srv interface{}, 
+                          ctx context.Context, 
+                          dec func(interface{}) error, 
+                          interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+    in := new(CrawlRequest)
+    if err := dec(in); err != nil {
+        return nil, err
+    }
+    if interceptor == nil {
+        return srv.(CrawlServer).Crawl(ctx, in)
+    }
+    info := &grpc.UnaryServerInfo{
+        Server:     srv,
+        FullMethod: "/protos.Crawl/Crawl",
+    }
+    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+        return srv.(CrawlServer).Crawl(ctx, req.(*CrawlRequest))
+    }
+    return interceptor(ctx, in, info, handler)
+}
+
+var _Crawl_serviceDesc = grpc.ServiceDesc{
+    ServiceName: "protos.Crawl",
+    HandlerType: (*CrawlServer)(nil),
+    Methods: []grpc.MethodDesc{
+        {
+            MethodName: "Crawl",
+            Handler:    _Crawl_Crawl_Handler,
+        },
+    },
+    Streams:  []grpc.StreamDesc{},
+    Metadata: "crawl.proto",
+}
+```
+
+## Server
+  
+  下面需要我们自己实现具体的业务逻辑（这里就是爬虫的业务逻辑），毕竟 `gRPC` 可不能猜到我们究竟要干什么事情，我们先定义一个包含 `http.Client` 的结
+构体 `crawlServer` ，当然了，`crawlServer` 究竟要包含什么要看具体的业务场景了，这里因为是爬虫所以要包含 `http.Client` 用于发送http请求。
+
+所以我们在 `Crawl` 方法中实现具体的爬虫逻辑。
+
+```golang
+type crawlServer struct{
+    client *http.Client
+}
+
+func (s *crawlServer) Crawl(ctx context.Context, in *pb.CrawlRequest) (*pb.CrawlResponse, error) {
+    return s.internalCrawl(in)
+}
+
+func (s *crawlServer) internalCrawl(in *pb.CrawlRequest) (*pb.CrawlResponse, error) {
+    // .... 具体的爬虫逻辑
+}
+```
+
+  与普通的 `tcp` 网络编程类似的，我们需要监听特定的端口，当这个端口监听到来自客户端的连接请求时，`gRPC` 会接受该连接请求，并且新起一个 `goroutine`
+去处理该请求，然后读取该请求的消息类型，`gRPC` 内部会去检查这个消息的类型，最后决定调用哪个 handler（也就是之前Register过的）去处理该请求，具体处
+理后向客户端返回答复。
+
+```golang
+listener, err := net.Listen("tcp", *address)
+if err != nil {
+    log.Fatal(err)
+}
+s:= grpc.NewServer()
+pb.RegisterCrawlServer(s, &crawlServer{})
+s.Serve(listener)
+```
+
+## Client
+
+  在客户端这里，我们需要一个类似 `net.Conn` 这样的结构体用于发送和接受消息，在 `gRPC` 中，我们可以通过类似 `net.Dial` 的方法 `grpc.Dial` 来返
+回一个 `grpc.ClientConn` 结构体，然后通过该结构体新建一个客户端 `pb.NewCrawlClient` ，最后用这个客户端发送我们的请求就可以了，在很多地方，客户
+端也被叫做 `stub`， 因为它仅仅有方法调用的接口，而真正实现业务逻辑的方法还是在服务端上面。
+
+```golang
+conn, err := grpc.Dial(*address, grpc.WithInsecure())
+if err != nil {
+    log.Fatal(err)
+}
+client := pb.NewCrawlClient(conn)
+
+request := pb.CrawlRequest{
+    Url:     *url,
+    Timeout: 10000,
+}
+response, err := client.Crawl(context.Background(), &request)
+if err != nil {
+    log.Fatal(err)
+}
+```
+
+## 总结
+  
+  在使用 `gRPC` 时，我们需要明确自己的责任与分工，什么事情应该我们自己干，而什么事情又是框架帮我们干好而我们不需要重复去做的。其实说到底，我们使用
+`RPC` 的目的就是让任务在远程执行后返回处理结果，具体的任务该怎么执行 `gRPC` 肯定是不知道的，所以相关的业务逻辑应该在服务端进行定义，毕竟活是服务端干
+的（如上面结构体 `crawlServer` 实现的 `Crawl` 方法），我们只需要定义相关的 `Request` 和 `Response` 消息，再定义一个 `service` 服务，用
+`protoc` 编译生成相应的代码，最后再定义服务端上面的处理逻辑就可以了。
+
diff --git a/git.md b/git.md
new file mode 100644
index 0000000..8f0d624
--- /dev/null
+++ b/git.md
@@ -0,0 +1,22 @@
+# git 系列
+
+Git 中一些不常用，但可能很有用的一些命令整理
+TODO // 待填坑
+
+## bisect
+
+## blame
+
+## cherrypick
+
+## clean
+
+## gui
+
+## merge
+
+## mergetool
+
+## reset
+
+## stash
diff --git a/icomoon/Read Me.txt b/icomoon/Read Me.txt
deleted file mode 100644
index 8491652..0000000
--- a/icomoon/Read Me.txt	
+++ /dev/null
@@ -1,7 +0,0 @@
-Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures.
-
-To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts
-
-You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects.
-
-You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection.
diff --git a/icomoon/demo-files/demo.css b/icomoon/demo-files/demo.css
deleted file mode 100644
index e1376f5..0000000
--- a/icomoon/demo-files/demo.css
+++ /dev/null
@@ -1,155 +0,0 @@
-body {
-  padding: 0;
-  margin: 0;
-  font-family: sans-serif;
-  font-size: 1em;
-  line-height: 1.5;
-  color: #555;
-  background: #fff;
-}
-h1 {
-  font-size: 1.5em;
-  font-weight: normal;
-}
-small {
-  font-size: .66666667em;
-}
-a {
-  color: #e74c3c;
-  text-decoration: none;
-}
-a:hover, a:focus {
-  box-shadow: 0 1px #e74c3c;
-}
-.bshadow0, input {
-  box-shadow: inset 0 -2px #e7e7e7;
-}
-input:hover {
-  box-shadow: inset 0 -2px #ccc;
-}
-input, fieldset {
-  font-family: sans-serif;
-  font-size: 1em;
-  margin: 0;
-  padding: 0;
-  border: 0;
-}
-input {
-  color: inherit;
-  line-height: 1.5;
-  height: 1.5em;
-  padding: .25em 0;
-}
-input:focus {
-  outline: none;
-  box-shadow: inset 0 -2px #449fdb;
-}
-.glyph {
-  font-size: 16px;
-  width: 15em;
-  padding-bottom: 1em;
-  margin-right: 4em;
-  margin-bottom: 1em;
-  float: left;
-  overflow: hidden;
-}
-.liga {
-  width: 80%;
-  width: calc(100% - 2.5em);
-}
-.talign-right {
-  text-align: right;
-}
-.talign-center {
-  text-align: center;
-}
-.bgc1 {
-  background: #f1f1f1;
-}
-.fgc1 {
-  color: #999;
-}
-.fgc0 {
-  color: #000;
-}
-p {
-  margin-top: 1em;
-  margin-bottom: 1em;
-}
-.mvm {
-  margin-top: .75em;
-  margin-bottom: .75em;
-}
-.mtn {
-  margin-top: 0;
-}
-.mtl, .mal {
-  margin-top: 1.5em;
-}
-.mbl, .mal {
-  margin-bottom: 1.5em;
-}
-.mal, .mhl {
-  margin-left: 1.5em;
-  margin-right: 1.5em;
-}
-.mhmm {
-  margin-left: 1em;
-  margin-right: 1em;
-}
-.mls {
-  margin-left: .25em;
-}
-.ptl {
-  padding-top: 1.5em;
-}
-.pbs, .pvs {
-  padding-bottom: .25em;
-}
-.pvs, .pts {
-  padding-top: .25em;
-}
-.unit {
-  float: left;
-}
-.unitRight {
-  float: right;
-}
-.size1of2 {
-  width: 50%;
-}
-.size1of1 {
-  width: 100%;
-}
-.clearfix:before, .clearfix:after {
-  content: " ";
-  display: table;
-}
-.clearfix:after {
-  clear: both;
-}
-.hidden-true {
-  display: none;
-}
-.textbox0 {
-  width: 3em;
-  background: #f1f1f1;
-  padding: .25em .5em;
-  line-height: 1.5;
-  height: 1.5em;
-}
-#testDrive {
-  display: block;
-  padding-top: 24px;
-  line-height: 1.5;
-}
-.fs0 {
-  font-size: 16px;
-}
-.fs1 {
-  font-size: 24px;
-}
-.fs2 {
-  font-size: 20px;
-}
-
diff --git a/icomoon/demo-files/demo.js b/icomoon/demo-files/demo.js
deleted file mode 100644
index 6f45f1c..0000000
--- a/icomoon/demo-files/demo.js
+++ /dev/null
@@ -1,30 +0,0 @@
-if (!('boxShadow' in document.body.style)) {
-    document.body.setAttribute('class', 'noBoxShadow');
-}
-
-document.body.addEventListener("click", function(e) {
-    var target = e.target;
-    if (target.tagName === "INPUT" &&
-        target.getAttribute('class').indexOf('liga') === -1) {
-        target.select();
-    }
-});
-
-(function() {
-    var fontSize = document.getElementById('fontSize'),
-        testDrive = document.getElementById('testDrive'),
-        testText = document.getElementById('testText');
-    function updateTest() {
-        testDrive.innerHTML = testText.value || String.fromCharCode(160);
-        if (window.icomoonLiga) {
-            window.icomoonLiga(testDrive);
-        }
-    }
-    function updateSize() {
-        testDrive.style.fontSize = fontSize.value + 'px';
-    }
-    fontSize.addEventListener('change', updateSize, false);
-    testText.addEventListener('input', updateTest, false);
-    testText.addEventListener('change', updateTest, false);
-    updateSize();
-}());
diff --git a/icomoon/demo.html b/icomoon/demo.html
deleted file mode 100644
index 557cc80..0000000
--- a/icomoon/demo.html
+++ /dev/null
@@ -1,490 +0,0 @@
-<!doctype html>
-<html>
-<head>
-    <meta charset="utf-8">
-    <title>IcoMoon Demo</title>
-    <meta name="description" content="An Icon Font Generated By IcoMoon.io">
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="stylesheet" href="demo-files/demo.css">
-    <link rel="stylesheet" href="style.css"></head>
-<body>
-    <div class="bgc1 clearfix">
-        <h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;28)</small></h1>
-    </div>
-    <div class="clearfix mhl ptl">
-        <h1 class="mvm mtn fgc1">Grid Size: 24</h1>
-        <div class="glyph fs1">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-close">
-                
-                </span>
-                <span class="mls"> icon-close</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e5cd" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe5cd;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="clear, close" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs1">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-list">
-                
-                </span>
-                <span class="mls"> icon-list</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e896" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe896;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="list" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs1">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-menu">
-                
-                </span>
-                <span class="mls"> icon-menu</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e5d2" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe5d2;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="menu" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs1">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-person">
-                
-                </span>
-                <span class="mls"> icon-person</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e7fd" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe7fd;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="person" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs1">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-search">
-                
-                </span>
-                <span class="mls"> icon-search</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e8b6" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe8b6;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="search" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs1">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-share">
-                
-                </span>
-                <span class="mls"> icon-share</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e80d" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe80d;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="share" class="liga unitRight" />
-            </div>
-        </div>
-  </div>
-    <div class="clearfix mhl ptl">
-        <h1 class="mvm mtn fgc1">Grid Size: 20</h1>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-creative-commons">
-                
-                </span>
-                <span class="mls"> icon-creative-commons</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e918" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe918;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-down">
-                
-                </span>
-                <span class="mls"> icon-chevron-down</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e900" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe900;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-left">
-                
-                </span>
-                <span class="mls"> icon-chevron-left</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e901" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe901;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-right">
-                
-                </span>
-                <span class="mls"> icon-chevron-right</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e902" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe902;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-thin-down">
-                
-                </span>
-                <span class="mls"> icon-chevron-thin-down</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e903" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe903;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-thin-left">
-                
-                </span>
-                <span class="mls"> icon-chevron-thin-left</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e904" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe904;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-thin-right">
-                
-                </span>
-                <span class="mls"> icon-chevron-thin-right</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e905" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe905;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-thin-up">
-                
-                </span>
-                <span class="mls"> icon-chevron-thin-up</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e906" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe906;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-chevron-up">
-                
-                </span>
-                <span class="mls"> icon-chevron-up</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e907" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe907;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-mail">
-                
-                </span>
-                <span class="mls"> icon-mail</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e90d" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe90d;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-feed">
-                
-                </span>
-                <span class="mls"> icon-feed</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e90a" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe90a;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-behance">
-                
-                </span>
-                <span class="mls"> icon-behance</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e90c" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe90c;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-weibo">
-                
-                </span>
-                <span class="mls"> icon-weibo</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e90e" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe90e;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-dribbble">
-                
-                </span>
-                <span class="mls"> icon-dribbble</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e916" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe916;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-facebook">
-                
-                </span>
-                <span class="mls"> icon-facebook</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e90f" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe90f;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-github">
-                
-                </span>
-                <span class="mls"> icon-github</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e910" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe910;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-google">
-                
-                </span>
-                <span class="mls"> icon-google</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e911" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe911;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-instagram">
-                
-                </span>
-                <span class="mls"> icon-instagram</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e912" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe912;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-linkedin">
-                
-                </span>
-                <span class="mls"> icon-linkedin</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e917" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe917;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-pinterest">
-                
-                </span>
-                <span class="mls"> icon-pinterest</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e913" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe913;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-tumblr">
-                
-                </span>
-                <span class="mls"> icon-tumblr</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e914" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe914;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-        <div class="glyph fs2">
-            <div class="clearfix bshadow0 pbs">
-                <span class="icon-twitter">
-                
-                </span>
-                <span class="mls"> icon-twitter</span>
-            </div>
-            <fieldset class="fs0 size1of1 clearfix hidden-false">
-                <input type="text" readonly value="e915" class="unit size1of2" />
-                <input type="text" maxlength="1" readonly value="&#xe915;" class="unitRight size1of2 talign-right" />
-            </fieldset>
-            <div class="fs0 bshadow0 clearfix hidden-true">
-                <span class="unit pvs fgc1">liga: </span>
-                <input type="text" readonly value="" class="liga unitRight" />
-            </div>
-        </div>
-  </div>
-
-    <!--[if gt IE 8]><!-->
-    <div class="mhl clearfix mbl">
-        <h1>Font Test Drive</h1>
-        <label>
-            Font Size: <input id="fontSize" type="number" class="textbox0 mbm"
-            min="8" value="48" />
-            px
-        </label>
-        <input id="testText" type="text" class="phl size1of1 mvl"
-        placeholder="Type some text to test..." value=""/>
-        </label>
-        <div id="testDrive" class="icon-">&nbsp;
-        </div>
-    </div>
-    <!--<![endif]-->
-    <div class="bgc1 clearfix">
-        <p class="mhl">Generated by <a href="https://icomoon.io/app">IcoMoon</a></p>
-    </div>
-
-    <script src="demo-files/demo.js"></script>
-</body>
-</html>
diff --git a/icomoon/fonts/icomoon.eot b/icomoon/fonts/icomoon.eot
deleted file mode 100644
index cbc814f..0000000
Binary files a/icomoon/fonts/icomoon.eot and /dev/null differ
diff --git a/icomoon/fonts/icomoon.svg b/icomoon/fonts/icomoon.svg
deleted file mode 100644
index 7b38feb..0000000
--- a/icomoon/fonts/icomoon.svg
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata>Generated by IcoMoon</metadata>
-<defs>
-<font id="icomoon" horiz-adv-x="1024">
-<font-face units-per-em="1024" ascent="960" descent="-64" />
-<missing-glyph horiz-adv-x="1024" />
-<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
-<glyph unicode="&#xe5cd;" glyph-name="close" d="M810 664.667l-238-238 238-238-60-60-238 238-238-238-60 60 238 238-238 238 60 60 238-238 238 238z" />
-<glyph unicode="&#xe5d2;" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
-<glyph unicode="&#xe7fd;" glyph-name="person" d="M512 340.667c114 0 342-56 342-170v-86h-684v86c0 114 228 170 342 170zM512 426.667c-94 0-170 76-170 170s76 172 170 172 170-78 170-172-76-170-170-170z" />
-<glyph unicode="&#xe80d;" glyph-name="share" d="M768 252.667c68 0 124-56 124-124s-56-126-124-126-124 58-124 126c0 10 0 20 2 28l-302 176c-24-22-54-34-88-34-70 0-128 58-128 128s58 128 128 128c34 0 64-12 88-34l300 174c-2 10-4 20-4 30 0 70 58 128 128 128s128-58 128-128-58-128-128-128c-34 0-64 14-88 36l-300-176c2-10 4-20 4-30s-2-20-4-30l304-176c22 20 52 32 84 32z" />
-<glyph unicode="&#xe896;" glyph-name="list" d="M298 640.667h598v-86h-598v86zM298 212.667v86h598v-86h-598zM298 384.667v84h598v-84h-598zM128 554.667v86h86v-86h-86zM128 212.667v86h86v-86h-86zM128 384.667v84h86v-84h-86z" />
-<glyph unicode="&#xe8b6;" glyph-name="search" d="M406 340.667c106 0 192 86 192 192s-86 192-192 192-192-86-192-192 86-192 192-192zM662 340.667l212-212-64-64-212 212v34l-12 12c-48-42-112-66-180-66-154 0-278 122-278 276s124 278 278 278 276-124 276-278c0-68-24-132-66-180l12-12h34z" />
-<glyph unicode="&#xe900;" glyph-name="chevron-down" d="M231.219 586.342c22.323 22.835 53.402 24.627 80.691 0l200.090-191.846 200.090 191.846c27.29 24.627 58.419 22.835 80.589 0 22.323-22.784 20.89-61.286 0-82.688-20.787-21.402-240.384-230.502-240.384-230.502-11.11-11.418-25.702-17.152-40.294-17.152s-29.184 5.734-40.397 17.152c0 0-219.494 209.101-240.384 230.502-20.941 21.402-22.323 59.904 0 82.688z" />
-<glyph unicode="&#xe901;" glyph-name="chevron-left" d="M637.542 741.581c22.835-22.323 24.627-53.402 0-80.691l-191.846-200.090 191.846-200.090c24.627-27.29 22.835-58.419 0-80.589-22.784-22.323-61.286-20.89-82.688 0-21.402 20.787-230.502 240.384-230.502 240.384-11.418 11.11-17.152 25.702-17.152 40.294s5.734 29.184 17.152 40.397c0 0 209.101 219.494 230.502 240.384 21.402 20.941 59.904 22.323 82.688 0z" />
-<glyph unicode="&#xe902;" glyph-name="chevron-right" d="M469.146 741.581c21.402-20.89 230.502-240.384 230.502-240.384 11.418-11.213 17.152-25.805 17.152-40.397s-5.734-29.184-17.152-40.294c0 0-209.101-219.597-230.502-240.384-21.402-20.89-59.904-22.323-82.688 0-22.835 22.221-24.627 53.299 0 80.589l191.846 200.090-191.846 200.090c-24.627 27.29-22.835 58.419 0 80.691 22.784 22.323 61.286 20.941 82.688 0z" />
-<glyph unicode="&#xe903;" glyph-name="chevron-thin-down" d="M891.802 660.019c13.926 13.722 36.301 13.722 50.125 0s13.875-35.891 0-49.613l-404.89-400.896c-13.824-13.722-36.198-13.722-50.125 0l-404.89 400.896c-13.824 13.722-13.824 35.891 0 49.613 13.875 13.722 36.301 13.722 50.125 0l379.853-365.619 379.802 365.619z" />
-<glyph unicode="&#xe904;" glyph-name="chevron-thin-left" d="M711.219 80.998c13.722-13.926 13.722-36.301 0-50.125s-35.891-13.875-49.613 0l-400.896 404.89c-13.722 13.824-13.722 36.198 0 50.125l400.896 404.89c13.722 13.824 35.891 13.824 49.613 0 13.722-13.875 13.722-36.301 0-50.125l-365.619-379.853 365.619-379.802z" />
-<glyph unicode="&#xe905;" glyph-name="chevron-thin-right" d="M678.4 460.8l-365.619 379.904c-13.722 13.824-13.722 36.198 0 50.125 13.722 13.824 35.891 13.824 49.613 0l400.896-404.89c13.722-13.875 13.722-36.301 0-50.125l-400.896-404.89c-13.722-13.875-35.891-13.824-49.613 0-13.722 13.773-13.722 36.198 0 50.125l365.619 379.75z" />
-<glyph unicode="&#xe906;" glyph-name="chevron-thin-up" d="M132.198 261.581c-13.926-13.722-36.301-13.722-50.125 0s-13.875 35.891 0 49.613l404.89 400.896c13.824 13.722 36.198 13.722 50.125 0l404.89-400.896c13.824-13.722 13.824-35.891 0-49.613-13.875-13.722-36.301-13.722-50.074 0l-379.904 365.619-379.802-365.619z" />
-<glyph unicode="&#xe907;" glyph-name="chevron-up" d="M792.781 335.258c-22.323-22.835-53.402-24.627-80.691 0l-200.090 191.846-200.090-191.846c-27.29-24.627-58.419-22.835-80.589 0-22.323 22.784-20.89 61.286 0 82.688 20.787 21.402 240.384 230.502 240.384 230.502 11.11 11.418 25.702 17.152 40.294 17.152s29.184-5.734 40.397-17.152c0 0 219.494-209.101 240.384-230.502 20.941-21.402 22.323-59.904 0-82.688z" />
-<glyph unicode="&#xe90a;" glyph-name="feed" d="M122.88 849.92v-121.19c362.803 0 656.896-294.195 656.896-656.998h121.293c0 429.773-348.416 778.189-778.189 778.189zM122.88 607.386v-121.293c228.813 0 414.362-185.498 414.362-414.413h121.242c0 295.834-239.821 535.706-535.603 535.706zM239.053 304.179c-64.205 0-116.224-52.122-116.224-116.275s52.019-116.224 116.224-116.224 116.173 52.019 116.173 116.224-51.968 116.275-116.173 116.275z" />
-<glyph unicode="&#xe90c;" glyph-name="behance" d="M413.286 496.589c0 0 96.87 7.526 96.87 125.901 0 118.528-79.258 176.179-179.712 176.179h-330.445v-661.811h330.445c0 0 201.779-6.605 201.779 195.379-0.051 0.051 8.755 164.352-118.938 164.352zM145.613 681.114h184.832c0 0 44.954 0 44.954-68.813 0-68.915-26.419-78.899-56.422-78.899h-173.363v147.712zM321.075 254.515h-175.462v176.896h184.832c0 0 66.97 0.922 66.97-90.88 0-77.414-50.022-85.453-76.339-86.016zM801.229 630.374c-244.275 0-244.070-254.31-244.070-254.31s-16.691-252.979 244.070-252.979c0 0 217.242-13.005 217.242 175.974h-111.718c0 0 3.686-71.219-101.786-71.219 0 0-111.821-7.782-111.821 115.2h328.858c0.051 0.051 36.301 287.334-220.774 287.334zM900.608 431.411h-208.589c0 0 13.619 101.99 111.718 101.99s96.87-101.99 96.87-101.99zM926.566 759.808h-261.99v-81.613h261.99v81.613z" />
-<glyph unicode="&#xe90d;" glyph-name="mail" d="M80.589 702.157c24.986-13.414 371.098-199.373 384-206.285s29.594-10.189 46.387-10.189c16.794 0 33.485 3.277 46.387 10.189s359.014 192.87 384 206.285c25.037 13.466 48.691 65.843 2.765 65.843h-866.253c-45.926 0-22.272-52.378 2.714-65.843zM952.986 589.363c-28.416-14.797-378.214-197.069-395.622-206.182s-29.594-10.189-46.387-10.189-28.979 1.075-46.387 10.189-365.21 191.437-393.626 206.234c-19.968 10.445-19.763-1.792-19.763-11.213s0-373.402 0-373.402c0-21.504 28.979-51.2 51.2-51.2h819.2c22.221 0 51.2 29.696 51.2 51.2 0 0 0 363.93 0 373.35s0.205 21.658-19.814 11.213z" />
-<glyph unicode="&#xe90e;" glyph-name="weibo" d="M752.026 457.318c-14.029 4.301-23.706 7.27-16.333 26.010 15.923 40.806 17.613 75.981 0.358 101.12-32.41 47.104-121.037 44.595-222.618 1.28 0 0.102-31.898-14.182-23.757 11.622 15.667 51.046 13.261 93.85-11.059 118.528-55.091 56.218-201.574-2.099-327.27-129.997-94.157-95.795-148.787-197.274-148.787-285.082 0-167.987 211.558-280.32 418.56-280.32 271.309 0 451.84 170.701 451.84 298.086 0 77.056-63.693 120.73-120.934 138.752zM421.683 95.795c-165.12-16.384-307.763 58.726-318.464 167.68-10.701 109.005 114.483 210.688 279.654 227.226 165.171 16.384 307.763-58.675 318.464-167.68 10.701-109.107-114.483-210.842-279.654-227.226zM1021.44 594.074c-0.051 169.574-137.523 306.995-307.2 306.995-19.814 0-35.789-15.974-35.789-35.789s15.974-35.789 35.789-35.789c130.099 0 235.571-105.523 235.571-235.622 0-19.814 16.026-35.789 35.84-35.789s35.789 16.026 35.789 35.84v0.154zM879.053 599.296c-16.333 79.974-79.411 143.002-159.386 159.386-19.354 3.994-38.298-8.499-42.291-27.904-3.942-19.302 8.499-38.298 27.904-42.291 52.019-10.598 92.979-51.61 103.629-103.578 3.994-19.405 22.938-31.795 42.291-27.904 19.302 3.994 31.846 22.989 27.853 42.291zM336.998 383.898c-66.56-13.414-111.462-69.222-100.301-124.621 11.162-55.501 74.086-89.6 140.646-76.186 66.509 13.414 111.411 69.222 100.301 124.621-11.162 55.398-74.189 89.6-140.646 76.186z" />
-<glyph unicode="&#xe90f;" glyph-name="facebook" d="M870.4 921.6h-716.8c-56.32 0-102.4-46.080-102.4-102.4v-716.8c0-56.371 46.080-102.4 102.4-102.4h358.4v358.4h-102.4v126.72h102.4v104.96c0 110.797 62.054 188.621 192.819 188.621l92.314-0.102v-133.376h-61.286c-50.893 0-70.246-38.195-70.246-73.626v-86.528h131.482l-29.082-126.669h-102.4v-358.4h204.8c56.32 0 102.4 46.029 102.4 102.4v716.8c0 56.32-46.080 102.4-102.4 102.4z" />
-<glyph unicode="&#xe910;" glyph-name="github" d="M674.816 393.779c-36.762 0-66.56-41.318-66.56-92.109 0-50.893 29.798-92.211 66.56-92.211s66.56 41.318 66.56 92.211c-0.051 50.79-29.798 92.109-66.56 92.109zM906.547 633.549c7.629 18.688 7.936 124.877-32.512 226.611 0 0-92.723-10.189-233.011-106.496-29.44 8.192-79.258 12.186-128.973 12.186-49.818 0-99.584-3.994-129.024-12.186-140.339 96.307-233.062 106.496-233.062 106.496-40.397-101.734-39.987-207.923-32.461-226.611-47.514-51.61-76.544-113.613-76.544-198.195 0-367.923 305.306-373.811 382.31-373.811 17.51 0 52.122-0.102 88.781-0.102 36.608 0 71.27 0.102 88.678 0.102 77.107 0 382.31 5.888 382.31 373.811 0 84.582-28.979 146.586-76.493 198.195zM513.434 106.752h-2.867c-193.075 0-343.501 22.989-343.501 210.688 0 45.005 15.872 86.682 53.606 121.293 62.822 57.702 169.216 27.187 289.894 27.187 0.512 0 1.024 0 1.485 0 0.512 0 0.922 0 1.382 0 120.678 0 227.123 30.515 289.997-27.187 37.632-34.611 53.504-76.288 53.504-121.293 0-187.699-150.374-210.688-343.501-210.688zM349.235 393.779c-36.762 0-66.56-41.318-66.56-92.109 0-50.893 29.798-92.211 66.56-92.211 36.813 0 66.611 41.318 66.611 92.211 0 50.79-29.798 92.109-66.611 92.109z" />
-<glyph unicode="&#xe911;" glyph-name="google" d="M101.837 686.643c0-76.493 25.549-131.686 75.878-164.096 41.267-26.624 89.088-30.618 113.971-30.618 6.042 0 10.906 0.307 14.285 0.512 0 0-7.885-51.405 30.208-102.195h-1.741c-65.997 0-281.242-13.773-281.242-190.822 0-180.019 197.683-189.184 237.363-189.184 3.123 0 4.966 0.102 4.966 0.102 0.41 0 3.226-0.102 8.090-0.102 25.446 0 91.238 3.174 152.32 32.922 79.258 38.4 119.45 105.421 119.45 198.912 0 90.317-61.235 144.077-105.933 183.398-27.29 24.013-50.893 44.698-50.893 64.819 0 20.48 17.254 35.891 39.014 55.398 35.277 31.488 68.557 76.39 68.557 161.28 0 74.598-9.677 124.723-69.325 156.518 6.195 3.174 28.211 5.478 39.066 7.014 32.307 4.403 79.565 9.421 79.565 35.789v5.069h-235.469c-2.355-0.102-238.131-8.806-238.131-224.717zM481.946 225.178c4.506-71.987-57.088-125.082-149.606-131.789-93.952-6.912-171.264 35.379-175.77 107.315-2.202 34.611 13.005 68.403 42.752 95.386 30.157 27.29 71.578 44.186 116.634 47.514 5.325 0.307 10.598 0.614 15.872 0.614 86.989-0.051 145.869-51.149 150.118-119.040zM420.454 735.949c23.091-81.306-11.776-166.195-67.379-181.914-6.4-1.792-12.954-2.662-19.661-2.662-50.893 0-101.325 51.507-120.064 122.522-10.445 39.731-9.574 74.65 2.406 108.134 11.725 33.024 32.922 55.194 59.546 62.72 6.4 1.792 13.005 2.714 19.712 2.714 61.44 0 100.966-25.498 125.44-111.514zM819.2 563.2v153.6h-102.4v-153.6h-153.6v-102.4h153.6v-153.6h102.4v153.6h153.6v102.4h-153.6z" />
-<glyph unicode="&#xe912;" glyph-name="instagram" d="M870.4 921.6h-716.8c-56.32 0-102.4-46.080-102.4-102.4v-716.8c0-56.371 46.080-102.4 102.4-102.4h716.8c56.32 0 102.4 46.029 102.4 102.4v716.8c0 56.32-46.080 102.4-102.4 102.4zM511.181 178.022c156.621 0 283.546 127.027 283.546 283.597 0 17.306-2.202 33.997-5.274 50.381h80.947v-369.459c0-19.558-15.872-35.328-35.482-35.328h-645.837c-19.61 0-35.482 15.77-35.482 35.328v369.459h79.309c-3.123-16.384-5.325-33.075-5.325-50.381 0-156.621 127.027-283.597 283.597-283.597zM333.978 461.619c0 97.894 79.36 177.203 177.254 177.203 97.843 0 177.254-79.309 177.254-177.203s-79.411-177.254-177.254-177.254c-97.946 0-177.254 79.36-177.254 177.254zM834.918 665.6h-82.688c-19.558 0-35.43 15.974-35.43 35.43v82.79c0 19.558 15.872 35.379 35.379 35.379h82.688c19.661 0 35.533-15.821 35.533-35.379v-82.739c0-19.507-15.872-35.482-35.482-35.482z" />
-<glyph unicode="&#xe913;" glyph-name="pinterest" d="M441.19 295.578c-26.931-141.005-59.75-276.173-157.082-346.778-30.003 213.094 44.083 373.094 78.541 542.976-58.726 98.816 7.066 297.574 130.816 248.576 152.32-60.211-131.891-367.206 58.88-405.606 199.219-39.987 280.525 345.6 156.979 470.989-178.432 181.146-519.475 4.25-477.491-255.078 10.189-63.386 75.674-82.586 26.163-170.086-114.227 25.293-148.326 115.405-143.923 235.52 7.066 196.608 176.589 334.182 346.675 353.28 215.091 24.115 416.973-79.002 444.877-281.293 31.386-228.403-97.075-475.802-327.117-457.984-62.362 4.864-88.474 35.789-137.318 65.485z" />
-<glyph unicode="&#xe914;" glyph-name="tumblr" d="M798.72 41.165c-39.782-18.995-75.776-32.307-107.981-39.987-32.256-7.578-67.123-11.418-104.602-11.418-42.547 0-80.179 5.478-112.896 16.282-32.717 10.906-60.57 26.419-83.712 46.49-23.091 20.224-39.117 41.574-48.026 64.205-8.909 22.682-13.363 55.603-13.363 98.611v330.496h-102.861v133.325c36.557 11.981 67.891 29.184 93.952 51.712 26.112 22.426 47.002 49.408 62.822 80.896 15.77 31.386 26.573 71.475 32.563 120.064h132.352v-238.182h220.877v-147.814h-220.877v-241.613c0-54.579 2.867-89.702 8.602-105.216 5.683-15.514 16.333-27.904 31.846-37.12 20.634-12.493 44.186-18.79 70.707-18.79 47.104 0 94.003 15.514 140.595 46.49v-148.429z" />
-<glyph unicode="&#xe915;" glyph-name="twitter" d="M886.579 653.005c0.41-8.294 0.563-16.691 0.563-24.986 0-255.488-194.406-549.99-549.888-549.99-109.21 0-210.739 32-296.294 86.886 15.155-1.792 30.515-2.714 46.080-2.714 90.624 0 173.926 30.925 240.026 82.688-84.531 1.587-155.955 57.395-180.531 134.195 11.776-2.202 23.91-3.379 36.352-3.379 17.664 0 34.765 2.304 50.944 6.707-88.422 17.818-155.034 95.898-155.034 189.594 0 0.819 0 1.587 0 2.406 26.061-14.49 55.91-23.194 87.552-24.218-51.866 34.714-86.016 93.798-86.016 160.922 0 35.379 9.523 68.608 26.214 97.178 95.283-116.992 237.773-193.894 398.387-201.984-3.277 14.182-4.966 28.877-4.966 44.083 0 106.701 86.477 193.178 193.229 193.178 55.603 0 105.83-23.398 141.107-60.979 43.981 8.704 85.35 24.781 122.726 46.899-14.438-45.107-45.107-82.995-84.992-106.906 39.117 4.71 76.288 15.002 111.002 30.413-25.907-38.81-58.675-72.806-96.461-99.994z" />
-<glyph unicode="&#xe916;" glyph-name="dribbble" d="M489.728 592.845c-69.53 123.597-143.923 224.41-149.35 231.834-112.179-53.043-195.891-156.416-222.054-280.934 10.547-0.205 178.278-2.202 371.405 49.101zM539.802 457.677c5.222 1.69 10.547 3.277 15.821 4.813-10.086 22.886-21.094 45.824-32.614 68.403-207.155-62.054-405.914-57.549-412.928-57.344-0.154-4.301-0.358-8.499-0.358-12.8 0-103.373 39.066-197.683 103.219-268.902l-0.256 0.307c0 0 110.080 195.277 327.117 265.523zM264.755 143.667v0.205c-2.97 2.304-6.144 4.403-9.114 6.912 5.427-4.352 9.114-7.117 9.114-7.117zM415.642 851.354c-0.358-0.102-0.768-0.205-0.768-0.205 0.307 0.102 0.717 0.102 0.717 0.102l0.051 0.102zM777.677 762.675c-70.861 62.362-163.789 100.403-265.677 100.403-32.717 0-64.41-3.994-94.822-11.315 6.144-8.192 81.664-108.493 150.426-234.701 151.654 56.781 208.947 143.974 210.074 145.613zM512-10.24c-260.096 0-470.989 210.893-470.989 470.989-0.051 260.198 210.842 471.091 470.989 471.091 260.198 0 471.040-210.893 471.040-471.091 0-260.096-210.842-470.989-471.040-470.989zM580.403 394.957c-236.083-82.278-314.061-247.706-315.648-251.085 68.301-53.299 153.907-85.299 247.194-85.299 55.706 0 108.8 11.315 157.030 31.795-5.939 35.277-29.338 158.515-85.965 305.51-0.819-0.307-1.69-0.614-2.611-0.922zM598.528 557.056c9.421-19.098 18.33-38.605 26.778-58.317 3.021-6.912 5.837-13.926 8.704-20.787 138.906 17.51 275.712-12.186 280.218-13.107-0.973 95.386-35.123 182.886-91.494 251.494-0.922-1.178-65.485-94.362-224.205-159.283zM658.483 414.464c52.787-145.203 74.189-263.27 78.285-287.283 90.317 60.979 154.522 157.696 172.39 269.824-7.987 2.56-120.627 38.246-250.675 17.459z" />
-<glyph unicode="&#xe917;" glyph-name="linkedin" d="M256 819.2c0-54.374-36.352-101.171-102.451-101.171-62.208 0-102.349 44.134-102.349 98.509 0 55.808 38.912 105.062 102.4 105.062s101.171-46.592 102.4-102.4zM51.2 0v665.6h204.8v-665.6h-204.8zM358.4 438.067c0 79.104-2.611 145.203-5.222 202.291h184.013l9.114-88.218h3.891c25.907 41.523 89.395 102.4 195.686 102.4 129.638 0 226.918-86.784 226.918-273.51v-381.030h-204.8v351.283c0 81.613-31.078 143.872-102.4 143.872-54.374 0-81.613-44.032-95.898-80.333-5.222-13.005-6.502-31.13-6.502-49.306v-365.517h-204.8v438.067z" />
-<glyph unicode="&#xe918;" glyph-name="creative-commons" d="M391.75 377.447c-20.797 0-36.5 7.603-47.1 22.806-10.7 15.097-16 35.297-16 60.497 0 55.5 20.997 83.303 63.1 83.303 8.4 0 17.5-2.803 27.3-8.403s18.097-15.4 24.8-29.4l63.1 32.8c-25.2 45.4-67 68.1-125.303 68.1-39.85 0-72.797-13.2-98.794-39.5-26.103-26.4-39.206-61.997-39.206-106.9 0-46 12.956-81.9 38.703-107.7 25.8-25.8 59.803-38.6 101.8-38.6 26.4 0 50.5 6.6 72.353 19.697 21.847 13.206 38.947 31.303 51.347 54.303l-58.1 29.4c-11.2-26.9-30.553-40.403-58-40.403zM663.447 377.447c-20.797 0-36.494 7.603-47.1 22.806-10.7 15.097-16 35.297-16 60.497 0 55.5 21.003 83.303 63.1 83.303 8.903 0 18.303-2.803 28.103-8.403 9.853-5.6 18.1-15.4 24.9-29.4l62.197 32.8c-24.7 45.4-66.197 68.1-124.497 68.1-39.8 0-72.75-13.2-98.8-39.5-26.097-26.4-39.103-61.997-39.103-106.9 0-46 12.703-81.9 38.253-107.7 25.5-25.8 59.55-38.6 102.2-38.6 25.747 0 49.647 6.6 71.45 19.697 21.903 13.206 39.3 31.303 52.203 54.303l-58.903 29.4c-11.2-26.9-30.6-40.403-58.003-40.403zM860.816 809.787c-95.159 95.038-211.659 142.525-349.463 142.525-136.134 0-251.391-47.487-345.709-142.525-96.778-98.306-145.163-214.613-145.163-348.978 0-134.353 48.384-249.85 145.163-346.506 96.778-96.687 212.034-145.016 345.709-145.016 135.344 0 252.656 48.747 351.922 146.216 93.478 92.578 140.244 207.684 140.244 345.306 0 137.634-47.575 253.972-142.703 348.978zM799.284 179.403c-81.206-80.281-176.769-120.419-286.7-120.419-109.916 0-204.622 39.75-284.181 119.219-79.556 79.434-119.337 173.662-119.337 282.606 0 108.956 40.169 203.994 120.566 285.081 77.1 78.656 171.416 117.988 282.953 117.988 111.581 0 206.306-39.331 284.244-117.988 78.747-77.819 118.103-172.825 118.103-285.081 0-113.053-38.547-206.859-115.647-281.406z" />
-</font></defs></svg>
\ No newline at end of file
diff --git a/icomoon/fonts/icomoon.ttf b/icomoon/fonts/icomoon.ttf
deleted file mode 100644
index 524884c..0000000
Binary files a/icomoon/fonts/icomoon.ttf and /dev/null differ
diff --git a/icomoon/fonts/icomoon.woff b/icomoon/fonts/icomoon.woff
deleted file mode 100644
index c7c5179..0000000
Binary files a/icomoon/fonts/icomoon.woff and /dev/null differ
diff --git a/icomoon/selection.json b/icomoon/selection.json
deleted file mode 100644
index 4826a2f..0000000
--- a/icomoon/selection.json
+++ /dev/null
@@ -1 +0,0 @@
-{"IcoMoonType":"selection","icons":[{"icon":{"paths":["M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["close"],"defaultCode":58829,"grid":24},"attrs":[],"properties":{"order":39,"ligatures":"clear, close","id":157,"prevSize":24,"code":58829,"name":"close"},"setIdx":1,"setId":6,"iconIdx":157},{"icon":{"paths":["M298 298h598v86h-598v-86zM298 726v-86h598v86h-598zM298 554v-84h598v84h-598zM128 384v-86h86v86h-86zM128 726v-86h86v86h-86zM128 554v-84h86v84h-86z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["list"],"defaultCode":59542,"grid":24},"attrs":[],"properties":{"order":50,"ligatures":"list","id":442,"prevSize":24,"code":59542,"name":"list"},"setIdx":1,"setId":6,"iconIdx":442},{"icon":{"paths":["M128 256h768v86h-768v-86zM128 554v-84h768v84h-768zM128 768v-86h768v86h-768z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["menu"],"defaultCode":58834,"grid":24},"attrs":[],"properties":{"order":48,"ligatures":"menu","id":489,"prevSize":24,"code":58834,"name":"menu"},"setIdx":1,"setId":6,"iconIdx":489},{"icon":{"paths":["M512 598c114 0 342 56 342 170v86h-684v-86c0-114 228-170 342-170zM512 512c-94 0-170-76-170-170s76-172 170-172 170 78 170 172-76 170-170 170z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["person"],"defaultCode":59389,"grid":24},"attrs":[],"properties":{"order":42,"ligatures":"person","id":557,"prevSize":24,"code":59389,"name":"person"},"setIdx":1,"setId":6,"iconIdx":557},{"icon":{"paths":["M406 598c106 0 192-86 192-192s-86-192-192-192-192 86-192 192 86 192 192 192zM662 598l212 212-64 64-212-212v-34l-12-12c-48 42-112 66-180 66-154 0-278-122-278-276s124-278 278-278 276 124 276 278c0 68-24 132-66 180l12 12h34z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["search"],"defaultCode":59574,"grid":24},"attrs":[],"properties":{"order":46,"ligatures":"search","id":655,"prevSize":24,"code":59574,"name":"search"},"setIdx":1,"setId":6,"iconIdx":655},{"icon":{"paths":["M768 686c68 0 124 56 124 124s-56 126-124 126-124-58-124-126c0-10 0-20 2-28l-302-176c-24 22-54 34-88 34-70 0-128-58-128-128s58-128 128-128c34 0 64 12 88 34l300-174c-2-10-4-20-4-30 0-70 58-128 128-128s128 58 128 128-58 128-128 128c-34 0-64-14-88-36l-300 176c2 10 4 20 4 30s-2 20-4 30l304 176c22-20 52-32 84-32z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["share"],"defaultCode":59405,"grid":24},"attrs":[],"properties":{"order":51,"ligatures":"share","id":681,"prevSize":24,"code":59405,"name":"share"},"setIdx":1,"setId":6,"iconIdx":681},{"icon":{"paths":["M391.75 595.353c-20.797 0-36.5-7.603-47.1-22.806-10.7-15.097-16-35.297-16-60.497 0-55.5 20.997-83.303 63.1-83.303 8.4 0 17.5 2.803 27.3 8.403s18.097 15.4 24.8 29.4l63.1-32.8c-25.2-45.4-67-68.1-125.303-68.1-39.85 0-72.797 13.2-98.794 39.5-26.103 26.4-39.206 61.997-39.206 106.9 0 46 12.956 81.9 38.703 107.7 25.8 25.8 59.803 38.6 101.8 38.6 26.4 0 50.5-6.6 72.353-19.697 21.847-13.206 38.947-31.303 51.347-54.303l-58.1-29.4c-11.2 26.9-30.553 40.403-58 40.403zM663.447 595.353c-20.797 0-36.494-7.603-47.1-22.806-10.7-15.097-16-35.297-16-60.497 0-55.5 21.003-83.303 63.1-83.303 8.903 0 18.303 2.803 28.103 8.403 9.853 5.6 18.1 15.4 24.9 29.4l62.197-32.8c-24.7-45.4-66.197-68.1-124.497-68.1-39.8 0-72.75 13.2-98.8 39.5-26.097 26.4-39.103 61.997-39.103 106.9 0 46 12.703 81.9 38.253 107.7 25.5 25.8 59.55 38.6 102.2 38.6 25.747 0 49.647-6.6 71.45-19.697 21.903-13.206 39.3-31.303 52.203-54.303l-58.903-29.4c-11.2 26.9-30.6 40.403-58.003 40.403zM860.816 163.013c-95.159-95.038-211.659-142.525-349.463-142.525-136.134 0-251.391 47.487-345.709 142.525-96.778 98.306-145.163 214.613-145.163 348.978 0 134.353 48.384 249.85 145.163 346.506 96.778 96.687 212.034 145.016 345.709 145.016 135.344 0 252.656-48.747 351.922-146.216 93.478-92.578 140.244-207.684 140.244-345.306 0-137.634-47.575-253.972-142.703-348.978zM799.284 793.397c-81.206 80.281-176.769 120.419-286.7 120.419-109.916 0-204.622-39.75-284.181-119.219-79.556-79.434-119.337-173.662-119.337-282.606 0-108.956 40.169-203.994 120.566-285.081 77.1-78.656 171.416-117.988 282.953-117.988 111.581 0 206.306 39.331 284.244 117.988 78.747 77.819 118.103 172.825 118.103 285.081 0 113.053-38.547 206.859-115.647 281.406z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["creative-commons"],"grid":20},"attrs":[],"properties":{"id":12,"order":47,"prevSize":20,"code":59672,"name":"creative-commons"},"setIdx":2,"setId":5,"iconIdx":11},{"icon":{"paths":["M231.219 386.458c22.323-22.835 53.402-24.627 80.691 0l200.090 191.846 200.090-191.846c27.29-24.627 58.419-22.835 80.589 0 22.323 22.784 20.89 61.286 0 82.688-20.787 21.402-240.384 230.502-240.384 230.502-11.11 11.418-25.702 17.152-40.294 17.152s-29.184-5.734-40.397-17.152c0 0-219.494-209.101-240.384-230.502-20.941-21.402-22.323-59.904 0-82.688z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-down"],"grid":20},"attrs":[],"properties":{"id":34,"order":17,"prevSize":20,"code":59648,"name":"chevron-down"},"setIdx":2,"setId":5,"iconIdx":33},{"icon":{"paths":["M637.542 231.219c22.835 22.323 24.627 53.402 0 80.691l-191.846 200.090 191.846 200.090c24.627 27.29 22.835 58.419 0 80.589-22.784 22.323-61.286 20.89-82.688 0-21.402-20.787-230.502-240.384-230.502-240.384-11.418-11.11-17.152-25.702-17.152-40.294s5.734-29.184 17.152-40.397c0 0 209.101-219.494 230.502-240.384 21.402-20.941 59.904-22.323 82.688 0z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-left"],"grid":20},"attrs":[],"properties":{"id":35,"order":16,"prevSize":20,"code":59649,"name":"chevron-left"},"setIdx":2,"setId":5,"iconIdx":34},{"icon":{"paths":["M469.146 231.219c21.402 20.89 230.502 240.384 230.502 240.384 11.418 11.213 17.152 25.805 17.152 40.397s-5.734 29.184-17.152 40.294c0 0-209.101 219.597-230.502 240.384-21.402 20.89-59.904 22.323-82.688 0-22.835-22.221-24.627-53.299 0-80.589l191.846-200.090-191.846-200.090c-24.627-27.29-22.835-58.419 0-80.691 22.784-22.323 61.286-20.941 82.688 0z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-right"],"grid":20},"attrs":[],"properties":{"id":36,"order":15,"prevSize":20,"code":59650,"name":"chevron-right"},"setIdx":2,"setId":5,"iconIdx":35},{"icon":{"paths":["M891.802 312.781c13.926-13.722 36.301-13.722 50.125 0s13.875 35.891 0 49.613l-404.89 400.896c-13.824 13.722-36.198 13.722-50.125 0l-404.89-400.896c-13.824-13.722-13.824-35.891 0-49.613 13.875-13.722 36.301-13.722 50.125 0l379.853 365.619 379.802-365.619z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-thin-down"],"grid":20},"attrs":[],"properties":{"id":41,"order":18,"prevSize":20,"code":59651,"name":"chevron-thin-down"},"setIdx":2,"setId":5,"iconIdx":40},{"icon":{"paths":["M711.219 891.802c13.722 13.926 13.722 36.301 0 50.125s-35.891 13.875-49.613 0l-400.896-404.89c-13.722-13.824-13.722-36.198 0-50.125l400.896-404.89c13.722-13.824 35.891-13.824 49.613 0 13.722 13.875 13.722 36.301 0 50.125l-365.619 379.853 365.619 379.802z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-thin-left"],"grid":20},"attrs":[],"properties":{"id":42,"order":19,"prevSize":20,"code":59652,"name":"chevron-thin-left"},"setIdx":2,"setId":5,"iconIdx":41},{"icon":{"paths":["M678.4 512l-365.619-379.904c-13.722-13.824-13.722-36.198 0-50.125 13.722-13.824 35.891-13.824 49.613 0l400.896 404.89c13.722 13.875 13.722 36.301 0 50.125l-400.896 404.89c-13.722 13.875-35.891 13.824-49.613 0-13.722-13.773-13.722-36.198 0-50.125l365.619-379.75z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-thin-right"],"grid":20},"attrs":[],"properties":{"id":43,"order":20,"prevSize":20,"code":59653,"name":"chevron-thin-right"},"setIdx":2,"setId":5,"iconIdx":42},{"icon":{"paths":["M132.198 711.219c-13.926 13.722-36.301 13.722-50.125 0s-13.875-35.891 0-49.613l404.89-400.896c13.824-13.722 36.198-13.722 50.125 0l404.89 400.896c13.824 13.722 13.824 35.891 0 49.613-13.875 13.722-36.301 13.722-50.074 0l-379.904-365.619-379.802 365.619z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-thin-up"],"grid":20},"attrs":[],"properties":{"id":44,"order":21,"prevSize":20,"code":59654,"name":"chevron-thin-up"},"setIdx":2,"setId":5,"iconIdx":43},{"icon":{"paths":["M792.781 637.542c-22.323 22.835-53.402 24.627-80.691 0l-200.090-191.846-200.090 191.846c-27.29 24.627-58.419 22.835-80.589 0-22.323-22.784-20.89-61.286 0-82.688 20.787-21.402 240.384-230.502 240.384-230.502 11.11-11.418 25.702-17.152 40.294-17.152s29.184 5.734 40.397 17.152c0 0 219.494 209.101 240.384 230.502 20.941 21.402 22.323 59.904 0 82.688z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["chevron-up"],"grid":20},"attrs":[],"properties":{"id":45,"order":22,"prevSize":20,"code":59655,"name":"chevron-up"},"setIdx":2,"setId":5,"iconIdx":44},{"icon":{"paths":["M80.589 270.643c24.986 13.414 371.098 199.373 384 206.285s29.594 10.189 46.387 10.189c16.794 0 33.485-3.277 46.387-10.189s359.014-192.87 384-206.285c25.037-13.466 48.691-65.843 2.765-65.843h-866.253c-45.926 0-22.272 52.378 2.714 65.843zM952.986 383.437c-28.416 14.797-378.214 197.069-395.622 206.182s-29.594 10.189-46.387 10.189-28.979-1.075-46.387-10.189-365.21-191.437-393.626-206.234c-19.968-10.445-19.763 1.792-19.763 11.213s0 373.402 0 373.402c0 21.504 28.979 51.2 51.2 51.2h819.2c22.221 0 51.2-29.696 51.2-51.2 0 0 0-363.93 0-373.35s0.205-21.658-19.814-11.213z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["mail"],"grid":20},"attrs":[],"properties":{"id":219,"order":36,"prevSize":20,"code":59661,"name":"mail"},"setIdx":2,"setId":5,"iconIdx":218},{"icon":{"paths":["M122.88 122.88v121.19c362.803 0 656.896 294.195 656.896 656.998h121.293c0-429.773-348.416-778.189-778.189-778.189zM122.88 365.414v121.293c228.813 0 414.362 185.498 414.362 414.413h121.242c0-295.834-239.821-535.706-535.603-535.706zM239.053 668.621c-64.205 0-116.224 52.122-116.224 116.275s52.019 116.224 116.224 116.224 116.173-52.019 116.173-116.224-51.968-116.275-116.173-116.275z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["rss"],"grid":20},"attrs":[],"properties":{"id":266,"order":25,"prevSize":20,"code":59658,"name":"feed"},"setIdx":2,"setId":5,"iconIdx":265},{"icon":{"paths":["M413.286 476.211c0 0 96.87-7.526 96.87-125.901 0-118.528-79.258-176.179-179.712-176.179h-330.445v661.811h330.445c0 0 201.779 6.605 201.779-195.379-0.051-0.051 8.755-164.352-118.938-164.352zM145.613 291.686h184.832c0 0 44.954 0 44.954 68.813 0 68.915-26.419 78.899-56.422 78.899h-173.363v-147.712zM321.075 718.285h-175.462v-176.896h184.832c0 0 66.97-0.922 66.97 90.88 0 77.414-50.022 85.453-76.339 86.016zM801.229 342.426c-244.275 0-244.070 254.31-244.070 254.31s-16.691 252.979 244.070 252.979c0 0 217.242 13.005 217.242-175.974h-111.718c0 0 3.686 71.219-101.786 71.219 0 0-111.821 7.782-111.821-115.2h328.858c0.051-0.051 36.301-287.334-220.774-287.334zM900.608 541.389h-208.589c0 0 13.619-101.99 111.718-101.99s96.87 101.99 96.87 101.99zM926.566 212.992h-261.99v81.613h261.99v-81.613z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["behance"],"grid":20},"attrs":[],"properties":{"id":322,"order":43,"prevSize":20,"code":59660,"name":"behance"},"setIdx":2,"setId":5,"iconIdx":321},{"icon":{"paths":["M752.026 515.482c-14.029-4.301-23.706-7.27-16.333-26.010 15.923-40.806 17.613-75.981 0.358-101.12-32.41-47.104-121.037-44.595-222.618-1.28 0-0.102-31.898 14.182-23.757-11.622 15.667-51.046 13.261-93.85-11.059-118.528-55.091-56.218-201.574 2.099-327.27 129.997-94.157 95.795-148.787 197.274-148.787 285.082 0 167.987 211.558 280.32 418.56 280.32 271.309 0 451.84-170.701 451.84-298.086 0-77.056-63.693-120.73-120.934-138.752zM421.683 877.005c-165.12 16.384-307.763-58.726-318.464-167.68-10.701-109.005 114.483-210.688 279.654-227.226 165.171-16.384 307.763 58.675 318.464 167.68 10.701 109.107-114.483 210.842-279.654 227.226zM1021.44 378.726c-0.051-169.574-137.523-306.995-307.2-306.995-19.814 0-35.789 15.974-35.789 35.789s15.974 35.789 35.789 35.789c130.099 0 235.571 105.523 235.571 235.622 0 19.814 16.026 35.789 35.84 35.789s35.789-16.026 35.789-35.84v-0.154zM879.053 373.504c-16.333-79.974-79.411-143.002-159.386-159.386-19.354-3.994-38.298 8.499-42.291 27.904-3.942 19.302 8.499 38.298 27.904 42.291 52.019 10.598 92.979 51.61 103.629 103.578 3.994 19.405 22.938 31.795 42.291 27.904 19.302-3.994 31.846-22.989 27.853-42.291zM336.998 588.902c-66.56 13.414-111.462 69.222-100.301 124.621 11.162 55.501 74.086 89.6 140.646 76.186 66.509-13.414 111.411-69.222 100.301-124.621-11.162-55.398-74.189-89.6-140.646-76.186z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["sina-weibo"],"grid":20},"attrs":[],"properties":{"id":340,"order":27,"prevSize":20,"code":59662,"name":"weibo"},"setIdx":2,"setId":5,"iconIdx":339},{"icon":{"paths":["M489.728 379.955c-69.53-123.597-143.923-224.41-149.35-231.834-112.179 53.043-195.891 156.416-222.054 280.934 10.547 0.205 178.278 2.202 371.405-49.101zM539.802 515.123c5.222-1.69 10.547-3.277 15.821-4.813-10.086-22.886-21.094-45.824-32.614-68.403-207.155 62.054-405.914 57.549-412.928 57.344-0.154 4.301-0.358 8.499-0.358 12.8 0 103.373 39.066 197.683 103.219 268.902l-0.256-0.307c0 0 110.080-195.277 327.117-265.523zM264.755 829.133v-0.205c-2.97-2.304-6.144-4.403-9.114-6.912 5.427 4.352 9.114 7.117 9.114 7.117zM415.642 121.446c-0.358 0.102-0.768 0.205-0.768 0.205 0.307-0.102 0.717-0.102 0.717-0.102l0.051-0.102zM777.677 210.125c-70.861-62.362-163.789-100.403-265.677-100.403-32.717 0-64.41 3.994-94.822 11.315 6.144 8.192 81.664 108.493 150.426 234.701 151.654-56.781 208.947-143.974 210.074-145.613zM512 983.040c-260.096 0-470.989-210.893-470.989-470.989-0.051-260.198 210.842-471.091 470.989-471.091 260.198 0 471.040 210.893 471.040 471.091 0 260.096-210.842 470.989-471.040 470.989zM580.403 577.843c-236.083 82.278-314.061 247.706-315.648 251.085 68.301 53.299 153.907 85.299 247.194 85.299 55.706 0 108.8-11.315 157.030-31.795-5.939-35.277-29.338-158.515-85.965-305.51-0.819 0.307-1.69 0.614-2.611 0.922zM598.528 415.744c9.421 19.098 18.33 38.605 26.778 58.317 3.021 6.912 5.837 13.926 8.704 20.787 138.906-17.51 275.712 12.186 280.218 13.107-0.973-95.386-35.123-182.886-91.494-251.494-0.922 1.178-65.485 94.362-224.205 159.283zM658.483 558.336c52.787 145.203 74.189 263.27 78.285 287.283 90.317-60.979 154.522-157.696 172.39-269.824-7.987-2.56-120.627-38.246-250.675-17.459z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["dribbble"],"grid":20},"attrs":[],"properties":{"id":358,"order":44,"prevSize":20,"code":59670,"name":"dribbble"},"setIdx":2,"setId":5,"iconIdx":357},{"icon":{"paths":["M870.4 51.2h-716.8c-56.32 0-102.4 46.080-102.4 102.4v716.8c0 56.371 46.080 102.4 102.4 102.4h358.4v-358.4h-102.4v-126.72h102.4v-104.96c0-110.797 62.054-188.621 192.819-188.621l92.314 0.102v133.376h-61.286c-50.893 0-70.246 38.195-70.246 73.626v86.528h131.482l-29.082 126.669h-102.4v358.4h204.8c56.32 0 102.4-46.029 102.4-102.4v-716.8c0-56.32-46.080-102.4-102.4-102.4z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["facebook"],"grid":20},"attrs":[],"properties":{"id":360,"order":33,"prevSize":20,"code":59663,"name":"facebook"},"setIdx":2,"setId":5,"iconIdx":359},{"icon":{"paths":["M674.816 579.021c-36.762 0-66.56 41.318-66.56 92.109 0 50.893 29.798 92.211 66.56 92.211s66.56-41.318 66.56-92.211c-0.051-50.79-29.798-92.109-66.56-92.109zM906.547 339.251c7.629-18.688 7.936-124.877-32.512-226.611 0 0-92.723 10.189-233.011 106.496-29.44-8.192-79.258-12.186-128.973-12.186-49.818 0-99.584 3.994-129.024 12.186-140.339-96.307-233.062-106.496-233.062-106.496-40.397 101.734-39.987 207.923-32.461 226.611-47.514 51.61-76.544 113.613-76.544 198.195 0 367.923 305.306 373.811 382.31 373.811 17.51 0 52.122 0.102 88.781 0.102 36.608 0 71.27-0.102 88.678-0.102 77.107 0 382.31-5.888 382.31-373.811 0-84.582-28.979-146.586-76.493-198.195zM513.434 866.048h-2.867c-193.075 0-343.501-22.989-343.501-210.688 0-45.005 15.872-86.682 53.606-121.293 62.822-57.702 169.216-27.187 289.894-27.187 0.512 0 1.024 0 1.485 0 0.512 0 0.922 0 1.382 0 120.678 0 227.123-30.515 289.997 27.187 37.632 34.611 53.504 76.288 53.504 121.293 0 187.699-150.374 210.688-343.501 210.688zM349.235 579.021c-36.762 0-66.56 41.318-66.56 92.109 0 50.893 29.798 92.211 66.56 92.211 36.813 0 66.611-41.318 66.611-92.211 0-50.79-29.798-92.109-66.611-92.109z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["github"],"grid":20},"attrs":[],"properties":{"id":364,"order":32,"prevSize":20,"code":59664,"name":"github"},"setIdx":2,"setId":5,"iconIdx":363},{"icon":{"paths":["M101.837 286.157c0 76.493 25.549 131.686 75.878 164.096 41.267 26.624 89.088 30.618 113.971 30.618 6.042 0 10.906-0.307 14.285-0.512 0 0-7.885 51.405 30.208 102.195h-1.741c-65.997 0-281.242 13.773-281.242 190.822 0 180.019 197.683 189.184 237.363 189.184 3.123 0 4.966-0.102 4.966-0.102 0.41 0 3.226 0.102 8.090 0.102 25.446 0 91.238-3.174 152.32-32.922 79.258-38.4 119.45-105.421 119.45-198.912 0-90.317-61.235-144.077-105.933-183.398-27.29-24.013-50.893-44.698-50.893-64.819 0-20.48 17.254-35.891 39.014-55.398 35.277-31.488 68.557-76.39 68.557-161.28 0-74.598-9.677-124.723-69.325-156.518 6.195-3.174 28.211-5.478 39.066-7.014 32.307-4.403 79.565-9.421 79.565-35.789v-5.069h-235.469c-2.355 0.102-238.131 8.806-238.131 224.717zM481.946 747.622c4.506 71.987-57.088 125.082-149.606 131.789-93.952 6.912-171.264-35.379-175.77-107.315-2.202-34.611 13.005-68.403 42.752-95.386 30.157-27.29 71.578-44.186 116.634-47.514 5.325-0.307 10.598-0.614 15.872-0.614 86.989 0.051 145.869 51.149 150.118 119.040zM420.454 236.851c23.091 81.306-11.776 166.195-67.379 181.914-6.4 1.792-12.954 2.662-19.661 2.662-50.893 0-101.325-51.507-120.064-122.522-10.445-39.731-9.574-74.65 2.406-108.134 11.725-33.024 32.922-55.194 59.546-62.72 6.4-1.792 13.005-2.714 19.712-2.714 61.44 0 100.966 25.498 125.44 111.514zM819.2 409.6v-153.6h-102.4v153.6h-153.6v102.4h153.6v153.6h102.4v-153.6h153.6v-102.4h-153.6z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["google+"],"grid":20},"attrs":[],"properties":{"id":366,"order":28,"prevSize":20,"code":59665,"name":"google"},"setIdx":2,"setId":5,"iconIdx":365},{"icon":{"paths":["M870.4 51.2h-716.8c-56.32 0-102.4 46.080-102.4 102.4v716.8c0 56.371 46.080 102.4 102.4 102.4h716.8c56.32 0 102.4-46.029 102.4-102.4v-716.8c0-56.32-46.080-102.4-102.4-102.4zM511.181 794.778c156.621 0 283.546-127.027 283.546-283.597 0-17.306-2.202-33.997-5.274-50.381h80.947v369.459c0 19.558-15.872 35.328-35.482 35.328h-645.837c-19.61-0-35.482-15.77-35.482-35.328v-369.459h79.309c-3.123 16.384-5.325 33.075-5.325 50.381 0 156.621 127.027 283.597 283.597 283.597zM333.978 511.181c0-97.894 79.36-177.203 177.254-177.203 97.843 0 177.254 79.309 177.254 177.203s-79.411 177.254-177.254 177.254c-97.946 0-177.254-79.36-177.254-177.254zM834.918 307.2h-82.688c-19.558 0-35.43-15.974-35.43-35.43v-82.79c0-19.558 15.872-35.379 35.379-35.379h82.688c19.661 0 35.533 15.821 35.533 35.379v82.739c0 19.507-15.872 35.482-35.482 35.482z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["instagram"],"grid":20},"attrs":[],"properties":{"id":368,"order":29,"prevSize":20,"code":59666,"name":"instagram"},"setIdx":2,"setId":5,"iconIdx":367},{"icon":{"paths":["M256 153.6c0 54.374-36.352 101.171-102.451 101.171-62.208 0-102.349-44.134-102.349-98.509 0-55.808 38.912-105.062 102.4-105.062s101.171 46.592 102.4 102.4zM51.2 972.8v-665.6h204.8v665.6h-204.8z","M358.4 534.733c0-79.104-2.611-145.203-5.222-202.291h184.013l9.114 88.218h3.891c25.907-41.523 89.395-102.4 195.686-102.4 129.638 0 226.918 86.784 226.918 273.51v381.030h-204.8v-351.283c0-81.613-31.078-143.872-102.4-143.872-54.374 0-81.613 44.032-95.898 80.333-5.222 13.005-6.502 31.13-6.502 49.306v365.517h-204.8v-438.067z"],"attrs":[{},{}],"isMulticolor":false,"isMulticolor2":false,"tags":["linkedin"],"grid":20},"attrs":[{},{}],"properties":{"id":372,"order":45,"prevSize":20,"code":59671,"name":"linkedin"},"setIdx":2,"setId":5,"iconIdx":371},{"icon":{"paths":["M441.19 677.222c-26.931 141.005-59.75 276.173-157.082 346.778-30.003-213.094 44.083-373.094 78.541-542.976-58.726-98.816 7.066-297.574 130.816-248.576 152.32 60.211-131.891 367.206 58.88 405.606 199.219 39.987 280.525-345.6 156.979-470.989-178.432-181.146-519.475-4.25-477.491 255.078 10.189 63.386 75.674 82.586 26.163 170.086-114.227-25.293-148.326-115.405-143.923-235.52 7.066-196.608 176.589-334.182 346.675-353.28 215.091-24.115 416.973 79.002 444.877 281.293 31.386 228.403-97.075 475.802-327.117 457.984-62.362-4.864-88.474-35.789-137.318-65.485z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["pinterest"],"grid":20},"attrs":[],"properties":{"id":374,"order":31,"prevSize":20,"code":59667,"name":"pinterest"},"setIdx":2,"setId":5,"iconIdx":373},{"icon":{"paths":["M798.72 931.635c-39.782 18.995-75.776 32.307-107.981 39.987-32.256 7.578-67.123 11.418-104.602 11.418-42.547 0-80.179-5.478-112.896-16.282-32.717-10.906-60.57-26.419-83.712-46.49-23.091-20.224-39.117-41.574-48.026-64.205-8.909-22.682-13.363-55.603-13.363-98.611v-330.496h-102.861v-133.325c36.557-11.981 67.891-29.184 93.952-51.712 26.112-22.426 47.002-49.408 62.822-80.896 15.77-31.386 26.573-71.475 32.563-120.064h132.352v238.182h220.877v147.814h-220.877v241.613c0 54.579 2.867 89.702 8.602 105.216 5.683 15.514 16.333 27.904 31.846 37.12 20.634 12.493 44.186 18.79 70.707 18.79 47.104 0 94.003-15.514 140.595-46.49v148.429z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["tumblr"],"grid":20},"attrs":[],"properties":{"id":379,"order":34,"prevSize":20,"code":59668,"name":"tumblr"},"setIdx":2,"setId":5,"iconIdx":378},{"icon":{"paths":["M886.579 319.795c0.41 8.294 0.563 16.691 0.563 24.986 0 255.488-194.406 549.99-549.888 549.99-109.21 0-210.739-32-296.294-86.886 15.155 1.792 30.515 2.714 46.080 2.714 90.624 0 173.926-30.925 240.026-82.688-84.531-1.587-155.955-57.395-180.531-134.195 11.776 2.202 23.91 3.379 36.352 3.379 17.664 0 34.765-2.304 50.944-6.707-88.422-17.818-155.034-95.898-155.034-189.594 0-0.819 0-1.587 0-2.406 26.061 14.49 55.91 23.194 87.552 24.218-51.866-34.714-86.016-93.798-86.016-160.922 0-35.379 9.523-68.608 26.214-97.178 95.283 116.992 237.773 193.894 398.387 201.984-3.277-14.182-4.966-28.877-4.966-44.083 0-106.701 86.477-193.178 193.229-193.178 55.603 0 105.83 23.398 141.107 60.979 43.981-8.704 85.35-24.781 122.726-46.899-14.438 45.107-45.107 82.995-84.992 106.906 39.117-4.71 76.288-15.002 111.002-30.413-25.907 38.81-58.675 72.806-96.461 99.994z"],"attrs":[],"isMulticolor":false,"isMulticolor2":false,"tags":["twitter"],"grid":20},"attrs":[],"properties":{"id":381,"order":30,"prevSize":20,"code":59669,"name":"twitter"},"setIdx":2,"setId":5,"iconIdx":380}],"height":1024,"metadata":{"name":"icomoon"},"preferences":{"showGlyphs":true,"showQuickUse":true,"showQuickUse2":true,"showSVGs":true,"fontPref":{"prefix":"icon-","metadata":{"fontFamily":"icomoon"},"metrics":{"emSize":1024,"baseline":6.25,"whitespace":50},"embed":false},"imagePref":{"prefix":"icon-","png":true,"useClassSelector":true,"color":0,"bgColor":16777215,"classSelector":".icon"},"historySize":100,"showCodes":true,"gridSize":16}}
\ No newline at end of file
diff --git a/icomoon/style.css b/icomoon/style.css
deleted file mode 100644
index 450ee46..0000000
--- a/icomoon/style.css
+++ /dev/null
@@ -1,111 +0,0 @@
-@font-face {
-  font-family: 'icomoon';
-  src:  url('fonts/icomoon.eot?uxdgz6');
-  src:  url('fonts/icomoon.eot?uxdgz6#iefix') format('embedded-opentype'),
-    url('fonts/icomoon.ttf?uxdgz6') format('truetype'),
-    url('fonts/icomoon.woff?uxdgz6') format('woff'),
-    url('fonts/icomoon.svg?uxdgz6#icomoon') format('svg');
-  font-weight: normal;
-  font-style: normal;
-}
-
-[class^="icon-"], [class*=" icon-"] {
-  /* use !important to prevent issues with browser extensions that change fonts */
-  font-family: 'icomoon' !important;
-  speak: none;
-  font-style: normal;
-  font-weight: normal;
-  font-variant: normal;
-  text-transform: none;
-  line-height: 1;
-
-  /* Better Font Rendering =========== */
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-}
-
-.icon-close:before {
-  content: "\e5cd";
-}
-.icon-list:before {
-  content: "\e896";
-}
-.icon-menu:before {
-  content: "\e5d2";
-}
-.icon-person:before {
-  content: "\e7fd";
-}
-.icon-search:before {
-  content: "\e8b6";
-}
-.icon-share:before {
-  content: "\e80d";
-}
-.icon-creative-commons:before {
-  content: "\e918";
-}
-.icon-chevron-down:before {
-  content: "\e900";
-}
-.icon-chevron-left:before {
-  content: "\e901";
-}
-.icon-chevron-right:before {
-  content: "\e902";
-}
-.icon-chevron-thin-down:before {
-  content: "\e903";
-}
-.icon-chevron-thin-left:before {
-  content: "\e904";
-}
-.icon-chevron-thin-right:before {
-  content: "\e905";
-}
-.icon-chevron-thin-up:before {
-  content: "\e906";
-}
-.icon-chevron-up:before {
-  content: "\e907";
-}
-.icon-mail:before {
-  content: "\e90d";
-}
-.icon-feed:before {
-  content: "\e90a";
-}
-.icon-behance:before {
-  content: "\e90c";
-}
-.icon-weibo:before {
-  content: "\e90e";
-}
-.icon-dribbble:before {
-  content: "\e916";
-}
-.icon-facebook:before {
-  content: "\e90f";
-}
-.icon-github:before {
-  content: "\e910";
-}
-.icon-google:before {
-  content: "\e911";
-}
-.icon-instagram:before {
-  content: "\e912";
-}
-.icon-linkedin:before {
-  content: "\e917";
-}
-.icon-pinterest:before {
-  content: "\e913";
-}
-.icon-tumblr:before {
-  content: "\e914";
-}
-.icon-twitter:before {
-  content: "\e915";
-}
-
diff --git a/img/algolia.svg b/img/algolia.svg
deleted file mode 100644
index 64ce5db..0000000
--- a/img/algolia.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="391px" height="124px" viewBox="0 0 391 124" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
-    <!-- Generator: Sketch 3.0.4 (8053) - http://www.bohemiancoding.com/sketch -->
-    <title>Algolia_logo_bg-white</title>
-    <desc>Created with Sketch.</desc>
-    <defs></defs>
-    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
-        <g id="Algolia_logo_bg-white" sketch:type="MSLayerGroup" transform="translate(1.000000, 0.000000)">
-            <path d="M234.602907,47.0181121 L228.907729,67.1993038 L247.249783,57.1465713 C244.58596,52.2621928 240.040498,48.5689338 234.602907,47.0181121 Z" id="Fill-1" fill="#46AEDA" sketch:type="MSShapeGroup"></path>
-            <path d="M202.455755,33.4002509 C200.002399,30.9359747 196.022371,30.9375523 193.569015,33.4002509 L192.458566,34.5156436 C190.00521,36.9783421 190.006781,40.976086 192.458566,43.4403623 L193.641265,44.6267488 C196.159018,40.5690545 199.364715,36.987808 203.090297,34.0391958 L202.455755,33.4002509 Z" id="Fill-2" fill="#46AEDA" sketch:type="MSShapeGroup"></path>
-            <path d="M240.840877,27.223784 C240.850301,27.0881068 240.880143,26.9587402 240.880143,26.8199077 L240.880143,23.6646244 C240.878572,20.1811917 238.067108,17.3556356 234.597542,17.3540579 L223.601419,17.3540579 C220.133424,17.3556356 217.320389,20.1796141 217.320389,23.6646244 L217.320389,26.7646902 C220.821368,25.7802419 224.504543,25.2422661 228.314941,25.2422661 C232.682919,25.2422661 236.890691,25.9427389 240.840877,27.223784" id="Fill-3" fill="#46AEDA" sketch:type="MSShapeGroup"></path>
-            <path d="M228.760635,41.5528326 C242.54501,41.5528326 253.760635,52.7684576 253.760635,66.5528326 C253.760635,80.3372076 242.54501,91.5528326 228.760635,91.5528326 C214.97626,91.5528326 203.760635,80.3372076 203.760635,66.5528326 C203.760635,52.7684576 214.97626,41.5528326 228.760635,41.5528326 M193.760635,66.5528326 C193.760635,85.8807871 209.427907,101.552833 228.760635,101.552833 C248.093362,101.552833 263.760635,85.8807871 263.760635,66.5528326 C263.760635,47.224878 248.093362,31.5528326 228.760635,31.5528326 C209.427907,31.5528326 193.760635,47.224878 193.760635,66.5528326 Z" id="Fill-4" fill="#46AEDA" sketch:type="MSShapeGroup"></path>
-            <path d="M68.5829487,99.6564664 C67.1395211,95.8212196 65.7840499,92.0522338 64.5118232,88.3463536 C63.2395965,84.6404734 61.9233915,80.8699099 60.5679203,77.0362407 L20.6200011,77.0362407 L12.6049727,99.6564664 L-0.244517215,99.6564664 C3.14651674,90.2852752 6.32708356,81.617712 9.29718324,73.6506218 C12.2657123,65.6851092 15.168274,58.1234729 18.0127216,50.9688681 C20.8524573,43.811108 23.6733452,36.9751869 26.472244,30.4579493 C29.2711428,23.9407117 32.1972643,17.4881575 35.2506085,11.0987089 L46.5734263,11.0987089 C49.6267705,17.4881575 52.5528919,23.9407117 55.3517907,30.4579493 C58.1506895,36.9751869 60.9700068,43.811108 63.8128838,50.9688681 C66.6526195,58.1234729 69.5567519,65.6851092 72.5268516,73.6506218 C75.4953806,81.617712 78.6759474,90.2852752 82.068552,99.6564664 L68.5829487,99.6564664 L68.5829487,99.6564664 Z M57.0056855,66.8147006 C54.2900312,59.4013626 51.5979366,52.2262485 48.9278311,45.28147 C46.2545843,38.3382692 43.476104,31.6727333 40.5939607,25.2817071 C37.623861,31.6727333 34.8045438,38.3382692 32.1344383,45.28147 C29.4627622,52.2262485 26.8099339,59.4013626 24.1822359,66.8147006 L57.0056855,66.8147006 L57.0056855,66.8147006 Z" id="Fill-5" fill="#0C1724" sketch:type="MSShapeGroup"></path>
-            <path d="M113.109313,100.932779 C105.815214,100.762393 100.643062,99.1879069 97.5897181,96.2045865 C94.5348033,93.2244215 93.0112725,88.5814222 93.0112725,82.2755886 L93.0112725,2.5352701 L104.83984,0.490646547 L104.83984,80.358754 C104.83984,82.3213402 105.011041,83.9384229 105.34873,85.2163126 C105.689562,86.4926247 106.24086,87.5165141 107.002625,88.2832479 C107.765961,89.0484041 108.785313,89.6242433 110.05754,90.0076102 C111.331337,90.3909771 112.898846,90.7112384 114.763208,90.9668163 L113.109313,100.932779" id="Fill-6" fill="#0C1724" sketch:type="MSShapeGroup"></path>
-            <path d="M169.468957,93.0098622 C168.452747,93.6945587 166.48001,94.5654169 163.553889,95.630325 C160.627767,96.6952331 157.213173,97.228476 153.311678,97.228476 C149.325368,97.228476 145.571513,96.5879535 142.053257,95.3116414 C138.53343,94.032174 135.458096,92.0522338 132.828828,89.3686654 C130.199559,86.6835193 128.121589,83.3420743 126.594917,79.3380199 C125.069815,75.3339654 124.304909,70.5631771 124.304909,65.025655 C124.304909,60.1696741 125.024267,55.7175694 126.467694,51.6709186 C127.909551,47.6258455 130.00794,44.1313693 132.766002,41.1922229 C135.520922,38.2530766 138.891538,35.9528751 142.879419,34.2916185 C146.865729,32.6303618 151.36093,31.7989447 156.365022,31.7989447 C161.878005,31.7989447 166.690477,32.2059762 170.805581,33.0137287 C174.919114,33.8246365 178.374545,34.5692834 181.173443,35.2492469 L181.173443,94.5449075 C181.173443,104.768025 178.545745,112.178208 173.287208,116.778611 C168.02553,121.379014 160.05448,123.677638 149.367775,123.677638 C145.211835,123.677638 141.289921,123.340023 137.600463,122.658481 C133.911006,121.973785 130.70845,121.16761 127.995937,120.230491 L130.158722,109.879584 C132.531975,110.813548 135.437678,111.646543 138.87269,112.37068 C142.307702,113.09324 145.890355,113.457675 149.622221,113.457675 C156.661875,113.457675 161.728793,112.051997 164.826115,109.239062 C167.921867,106.429282 169.468957,101.95509 169.468957,95.8212196 L169.468957,93.0098622 L169.468957,93.0098622 Z M164.57167,42.7256906 C162.576944,42.429094 159.884849,42.2776404 156.493816,42.2776404 C150.132682,42.2776404 145.233824,44.3680155 141.798812,48.5408776 C138.363799,52.7153174 136.647079,58.2512619 136.647079,65.1518664 C136.647079,68.9871132 137.13241,72.2670301 138.109354,74.9931948 C139.084728,77.7209372 140.399362,79.9753871 142.053257,81.7660104 C143.707152,83.5534783 145.615492,84.875542 147.778277,85.7258908 C149.941063,86.579395 152.168245,87.0037806 154.458253,87.0037806 C157.594841,87.0037806 160.478555,86.557308 163.107824,85.6627852 C165.735522,84.7666847 167.815063,83.7254413 169.341735,82.5327442 L169.341735,43.6848967 C168.152753,43.3441261 166.564825,43.0254425 164.57167,42.7256906 Z" id="Fill-7" fill="#0C1724" sketch:type="MSShapeGroup"></path>
-            <path d="M296.035098,100.934356 C288.739428,100.762393 283.567276,99.1894845 280.513932,96.2061642 C277.460588,93.2259991 275.933916,88.5814222 275.933916,82.2771662 L275.933916,2.53684774 L287.767195,0.492224188 L287.767195,80.358754 C287.767195,82.3213402 287.935255,83.9384229 288.274515,85.2163126 C288.613776,86.4942023 289.165074,87.5165141 289.929981,88.2832479 C290.691746,89.0499818 291.707957,89.6258209 292.981754,90.0091879 C294.253981,90.3925548 295.82149,90.7112384 297.688993,90.9668163 L296.035098,100.934356" id="Fill-8" fill="#0C1724" sketch:type="MSShapeGroup"></path>
-            <path d="M316.770823,21.1940376 C314.652016,21.1940376 312.847339,20.4904095 311.366216,19.0863084 C309.880381,17.6790521 309.139034,15.7858821 309.139034,13.3989104 C309.139034,11.0135162 309.880381,9.11719097 311.366216,7.71308992 C312.847339,6.30583359 314.652016,5.60378307 316.770823,5.60378307 C318.891201,5.60378307 320.694308,6.30583359 322.180143,7.71308992 C323.661266,9.11719097 324.405754,11.0135162 324.405754,13.3989104 C324.405754,15.7858821 323.661266,17.6790521 322.180143,19.0863084 C320.694308,20.4904095 318.891201,21.1940376 316.770823,21.1940376 L316.770823,21.1940376 Z M310.920151,33.206201 L322.75186,33.206201 L322.75186,99.6564664 L310.920151,99.6564664 L310.920151,33.206201 Z" id="Fill-9" fill="#0C1724" sketch:type="MSShapeGroup"></path>
-            <path d="M364.479326,31.5449444 C369.228972,31.5449444 373.235701,32.1649575 376.502653,33.3986733 C379.766465,34.6339667 382.395733,36.380416 384.388889,38.6364435 C386.382044,40.8956263 387.803482,43.5791947 388.651633,46.6887264 C389.498214,49.798258 389.92386,53.2264733 389.92386,56.9749498 L389.92386,98.5079433 C388.906079,98.6783286 387.48464,98.9118196 385.662686,99.2099938 C383.83759,99.5081681 381.781609,99.7842554 379.491601,100.039833 C377.201593,100.295411 374.719965,100.528902 372.04986,100.741884 C369.376613,100.953288 366.725355,101.062145 364.097658,101.062145 C360.364222,101.062145 356.93078,100.678778 353.792621,99.9120444 C350.654462,99.1453105 347.940378,97.9305265 345.65037,96.2708475 C343.360362,94.6095909 341.579245,92.416669 340.307018,89.6889266 C339.034791,86.9627619 338.398678,83.6828449 338.398678,79.8491758 C338.398678,76.1874696 339.140025,73.0337639 340.62586,70.3927918 C342.106983,67.7533974 344.122127,65.6235812 346.668151,64.0033433 C349.212605,62.3862606 352.181134,61.1919859 355.573739,60.425252 C358.964772,59.6585182 362.527007,59.2751513 366.260443,59.2751513 C367.446284,59.2751513 368.677674,59.338257 369.949901,59.4660459 C371.222127,59.5938349 372.431528,59.7673755 373.574961,59.9787795 C374.719965,60.1917611 375.717328,60.3826557 376.56705,60.553041 C377.413631,60.7250039 378.007336,60.8527929 378.346597,60.9364079 L378.346597,57.6138947 C378.346597,55.6544637 378.134559,53.7171198 377.710484,51.7987076 C377.284837,49.881873 376.521501,48.1795977 375.420475,46.6887264 C374.317879,45.197855 372.811625,44.005158 370.903285,43.1090575 C368.994945,42.2161124 366.513318,41.7680621 363.461544,41.7680621 C359.558478,41.7680621 356.147026,42.0457271 353.219334,42.5994793 C350.294783,43.1532315 348.110008,43.7290707 346.668151,44.3238416 L345.268702,34.4840907 C346.795374,33.8041272 349.341398,33.1430953 352.902062,32.5041505 C356.464297,31.863628 360.323385,31.5449444 364.479326,31.5449444 L364.479326,31.5449444 Z M365.497107,91.0946053 C368.296006,91.0946053 370.777633,91.029922 372.940419,90.902133 C375.103204,90.7743441 376.90474,90.5424307 378.346597,90.2000825 L378.346597,70.3927918 C377.496875,69.9684063 376.119415,69.6055487 374.212645,69.3073744 C372.302735,69.0092001 369.992308,68.8577465 367.278224,68.8577465 C365.497107,68.8577465 363.609185,68.9871132 361.617601,69.2426911 C359.624446,69.498269 357.79935,70.0315119 356.147026,70.8392644 C354.49156,71.6501722 353.11253,72.756099 352.011504,74.1633553 C350.908907,75.5674564 350.357609,77.4211853 350.357609,79.7213868 C350.357609,83.9810192 351.71308,86.9406749 354.428734,88.6019315 C357.142818,90.2647658 360.832276,91.0946053 365.497107,91.0946053 L365.497107,91.0946053 Z" id="Fill-10" fill="#0C1724" sketch:type="MSShapeGroup"></path>
-        </g>
-    </g>
-</svg>
\ No newline at end of file
diff --git a/img/avatar.png b/img/avatar.png
deleted file mode 100644
index e3fd2aa..0000000
Binary files a/img/avatar.png and /dev/null differ
diff --git a/img/azure.svg b/img/azure.svg
deleted file mode 100644
index ba99b8f..0000000
--- a/img/azure.svg
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?><!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" id="svg2" inkscape:version="0.48.5 r10040" sodipodi:docname="windows.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="760.825px" height="105.942px" viewBox="0.501 0.498 760.825 105.942" style="enable-background:new 0.501 0.498 760.825 105.942;" xml:space="preserve"><sodipodi:namedview fit-margin-bottom="0.5" fit-margin-right="0.5" inkscape:pageshadow="2" inkscape:window-y="-8" inkscape:window-height="716" inkscape:window-x="-8" inkscape:current-layer="g3000" inkscape:pageopacity="0" inkscape:window-maximized="1" inkscape:window-width="1366" gridtolerance="10" showgrid="false" inkscape:cx="398.69968" inkscape:cy="92.560761" bordercolor="#666666" pagecolor="#ffffff" objecttolerance="10" guidetolerance="10" inkscape:zoom="1.1441038" id="namedview21" borderopacity="1" fit-margin-left="0.5" fit-margin-top="0.5"></sodipodi:namedview><g id="Livello_x0020_1" transform="translate(9.0774947,-38070.588)"><g id="g3000" transform="matrix(0.04824549,0,0,0.04824549,0,38079.698)"><path id="path13" inkscape:connector-curvature="0" style="fill:#0DADEA;" d="M-177.77,123.629L722.723-0.149v868.978h-900.434	L-177.77,123.629z M722.723,980.036v859.14l-900.371-123.596l-0.062-735.504h900.434V980.036z M822.332-13.812l1198.23-164.707	V868.828H822.332V-13.812z M2020.562,980.036v1037.368l-1198.23-164.565V980.036H2020.562z"/><g id="flowRoot2989" transform="matrix(89.561227,0,0,88.070452,150957.32,17842.049)"><path id="path3031" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1640.247-184.778h-2.324v-9.139	c0-0.749,0.046-1.664,0.138-2.748h-0.039c-0.145,0.617-0.273,1.06-0.384,1.33l-4.215,10.557h-1.615l-4.225-10.478	c-0.118-0.308-0.243-0.778-0.374-1.408h-0.039c0.053,0.565,0.079,1.487,0.079,2.767v9.119h-2.167V-198.9h3.299l3.713,9.405	c0.282,0.722,0.466,1.261,0.551,1.615h0.049c0.243-0.742,0.44-1.294,0.591-1.655l3.782-9.365h3.181L-1640.247-184.778z"/><path id="path3033" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1635.884-196.98	c-0.374,0-0.695-0.121-0.96-0.364c-0.266-0.243-0.399-0.552-0.399-0.926s0.133-0.686,0.399-0.936	c0.266-0.249,0.586-0.374,0.96-0.374c0.387,0,0.716,0.125,0.985,0.374c0.269,0.25,0.404,0.561,0.404,0.936	c0,0.354-0.135,0.658-0.404,0.911C-1635.169-197.106-1635.497-196.98-1635.884-196.98z M-1634.752-184.778h-2.284v-10.085h2.284	V-184.778z"/><path id="path3035" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1624.539-185.241	c-0.807,0.466-1.763,0.699-2.866,0.699c-1.497,0-2.705-0.468-3.624-1.403c-0.919-0.935-1.379-2.148-1.379-3.639	c0-1.661,0.494-2.995,1.482-4.003c0.988-1.008,2.309-1.512,3.964-1.512c0.919,0,1.73,0.161,2.432,0.483v2.127	c-0.703-0.525-1.451-0.788-2.245-0.788c-0.965,0-1.756,0.327-2.373,0.98c-0.617,0.653-0.926,1.508-0.926,2.565	c0,1.044,0.29,1.868,0.871,2.472c0.581,0.604,1.361,0.906,2.339,0.906c0.821,0,1.595-0.292,2.324-0.876L-1624.539-185.241z"/><path id="path3037" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1616.415-192.686	c-0.276-0.217-0.673-0.325-1.192-0.325c-0.676,0-1.241,0.305-1.694,0.916c-0.453,0.61-0.68,1.441-0.68,2.491v4.826h-2.285	v-10.085h2.285v2.078h0.039c0.223-0.709,0.566-1.262,1.029-1.659c0.463-0.397,0.98-0.596,1.551-0.596	c0.414,0,0.729,0.063,0.946,0.187L-1616.415-192.686z"/><path id="path3039" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1610.309-184.542	c-1.556,0-2.798-0.471-3.728-1.413c-0.929-0.942-1.394-2.191-1.394-3.747c0-1.694,0.484-3.017,1.453-3.969	c0.969-0.952,2.273-1.428,3.915-1.428c1.576,0,2.803,0.463,3.683,1.389c0.88,0.926,1.319,2.209,1.319,3.85	c0,1.609-0.474,2.897-1.423,3.865C-1607.432-185.026-1608.707-184.542-1610.309-184.542L-1610.309-184.542z M-1610.201-193.277	c-0.893,0-1.599,0.312-2.117,0.935c-0.519,0.624-0.778,1.484-0.778,2.58c0,1.057,0.263,1.889,0.788,2.496	c0.525,0.607,1.228,0.911,2.108,0.911c0.9,0,1.591-0.299,2.073-0.896c0.482-0.598,0.724-1.448,0.724-2.551	c0-1.109-0.241-1.966-0.724-2.57C-1608.61-192.975-1609.301-193.277-1610.201-193.277L-1610.201-193.277z"/><path id="path3041" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1603.356-185.093v-2.117	c0.854,0.65,1.796,0.975,2.826,0.975c1.379,0,2.068-0.407,2.068-1.221c0-0.23-0.059-0.425-0.177-0.586	c-0.118-0.161-0.277-0.304-0.478-0.428s-0.437-0.236-0.709-0.335c-0.273-0.099-0.576-0.21-0.911-0.335	c-0.414-0.164-0.786-0.338-1.118-0.522c-0.332-0.184-0.607-0.392-0.827-0.625c-0.22-0.233-0.386-0.497-0.497-0.793	c-0.112-0.295-0.167-0.64-0.167-1.034c0-0.486,0.115-0.914,0.345-1.285c0.23-0.371,0.538-0.683,0.925-0.935	c0.388-0.253,0.827-0.443,1.32-0.571c0.492-0.128,1.001-0.192,1.526-0.192c0.932,0,1.766,0.141,2.501,0.423v1.999	c-0.709-0.486-1.523-0.729-2.442-0.729c-0.289,0-0.55,0.03-0.783,0.088c-0.233,0.059-0.432,0.141-0.596,0.246	c-0.164,0.105-0.292,0.231-0.384,0.379c-0.092,0.148-0.138,0.31-0.138,0.487c0,0.217,0.046,0.401,0.138,0.552	c0.092,0.151,0.228,0.284,0.409,0.399c0.18,0.115,0.397,0.22,0.65,0.315c0.253,0.095,0.543,0.199,0.872,0.31	c0.433,0.177,0.822,0.358,1.167,0.542c0.345,0.184,0.639,0.392,0.882,0.625c0.243,0.233,0.43,0.502,0.561,0.808	c0.131,0.305,0.197,0.668,0.197,1.088c0,0.512-0.118,0.958-0.355,1.339c-0.236,0.381-0.552,0.696-0.945,0.945	c-0.394,0.25-0.849,0.435-1.364,0.556c-0.516,0.122-1.059,0.182-1.63,0.182C-1601.594-184.542-1602.549-184.725-1603.356-185.093	z"/><path id="path3043" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1589.549-184.542	c-1.556,0-2.799-0.471-3.728-1.413c-0.929-0.942-1.393-2.191-1.393-3.747c0-1.694,0.484-3.017,1.453-3.969	c0.968-0.952,2.273-1.428,3.914-1.428c1.576,0,2.803,0.463,3.683,1.389c0.88,0.926,1.32,2.209,1.32,3.85	c0,1.609-0.474,2.897-1.423,3.865C-1586.672-185.026-1587.948-184.542-1589.549-184.542L-1589.549-184.542z M-1589.441-193.277	c-0.893,0-1.599,0.312-2.118,0.935c-0.519,0.624-0.778,1.484-0.778,2.58c0,1.057,0.263,1.889,0.788,2.496	c0.525,0.607,1.228,0.911,2.108,0.911c0.899,0,1.59-0.299,2.073-0.896c0.483-0.598,0.724-1.448,0.724-2.551	c0-1.109-0.241-1.966-0.724-2.57C-1587.851-192.975-1588.542-193.277-1589.441-193.277z"/><path id="path3045" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1576.264-197.846	c-0.308-0.177-0.66-0.266-1.054-0.266c-1.11,0-1.664,0.627-1.664,1.881v1.369h2.344v1.792h-2.334v8.292h-2.285v-8.292h-1.723	v-1.792h1.723v-1.635c0-1.064,0.348-1.902,1.044-2.516c0.696-0.614,1.566-0.921,2.61-0.921c0.565,0,1.011,0.062,1.339,0.187	V-197.846z"/><path id="path3047" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1569.676-184.886	c-0.446,0.223-1.034,0.335-1.763,0.335c-1.956,0-2.934-0.939-2.934-2.816v-5.702h-1.684v-1.792h1.684v-2.334l2.285-0.65v2.984	h2.413v1.792h-2.413v5.042c0,0.597,0.108,1.024,0.325,1.28c0.217,0.256,0.578,0.384,1.083,0.384c0.387,0,0.722-0.111,1.004-0.335	V-184.886z"/><path id="path3049" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1550.295-184.778h-2.57l-1.27-3.595h-5.554	l-1.221,3.595h-2.561l5.288-14.122h2.639L-1550.295-184.778z M-1554.756-190.283l-1.959-5.633	c-0.059-0.184-0.122-0.479-0.187-0.886h-0.039c-0.059,0.374-0.125,0.67-0.197,0.886l-1.94,5.633H-1554.756z"/><path id="path3051" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1541.156-193.907l-5.446,7.346h5.426v1.783	h-8.627v-0.857l5.564-7.445h-5.032v-1.783h8.115L-1541.156-193.907z"/><path id="path3053" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1530.432-184.778h-2.284v-1.596h-0.039	c-0.663,1.221-1.694,1.832-3.092,1.832c-2.383,0-3.575-1.431-3.575-4.294v-6.027h2.285v5.791c0,1.812,0.699,2.718,2.098,2.718	c0.676,0,1.232-0.249,1.669-0.748c0.437-0.499,0.655-1.152,0.655-1.96v-5.801h2.285L-1530.432-184.778z"/><path id="path3055" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1521.598-192.686	c-0.276-0.217-0.673-0.325-1.192-0.325c-0.676,0-1.241,0.305-1.694,0.916c-0.453,0.61-0.68,1.441-0.68,2.491v4.826h-2.284	v-10.085h2.284v2.078h0.039c0.223-0.709,0.566-1.262,1.029-1.659c0.463-0.397,0.98-0.596,1.551-0.596	c0.413,0,0.729,0.063,0.945,0.187L-1521.598-192.686z"/><path id="path3057" inkscape:connector-curvature="0" style="fill:#00ADEF;" d="M-1511.425-189.2h-6.874	c0.026,0.932,0.313,1.651,0.862,2.157c0.548,0.505,1.301,0.758,2.26,0.758c1.077,0,2.065-0.322,2.964-0.965v1.841	c-0.919,0.578-2.134,0.867-3.644,0.867c-1.484,0-2.647-0.458-3.491-1.374c-0.844-0.916-1.265-2.204-1.265-3.865	c0-1.569,0.464-2.848,1.394-3.836c0.929-0.988,2.083-1.482,3.462-1.482c1.379,0,2.445,0.443,3.2,1.329	c0.755,0.886,1.133,2.117,1.133,3.693L-1511.425-189.2z M-1513.631-190.815c-0.01-0.821-0.2-1.459-0.581-1.915	c-0.381-0.456-0.906-0.684-1.576-0.684c-0.656,0-1.213,0.24-1.669,0.719s-0.737,1.106-0.842,1.881H-1513.631z"/></g></g></g></svg>
\ No newline at end of file
diff --git a/img/baidu.svg b/img/baidu.svg
deleted file mode 100644
index f2f8fbf..0000000
--- a/img/baidu.svg
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?><!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="221.827px" height="71.304px" viewBox="0 0 221.827 71.304" style="enable-background:new 0 0 221.827 71.304;" xml:space="preserve"><g><path style="fill:#226CB4;" d="M86.45,37.576c7.75-1.665,6.692-10.937,6.465-12.962c-0.382-3.125-4.055-8.582-9.039-8.146	c-6.275,0.559-7.191,9.623-7.191,9.623C75.835,30.288,78.713,39.246,86.45,37.576 M100.842,22.033c4.278,0,7.736-4.93,7.736-11.021	C108.578,4.922,105.12,0,100.842,0c-4.28,0-7.747,4.922-7.747,11.013C93.095,17.103,96.562,22.033,100.842,22.033 M119.286,22.758	c5.726,0.75,9.396-5.359,10.13-9.988c0.75-4.623-2.949-10-6.995-10.923c-4.063-0.934-9.135,5.57-9.592,9.813	C112.271,16.851,113.566,22.025,119.286,22.758 M141.965,30.535c0-2.214-1.833-8.888-8.66-8.888c-6.839,0-7.744,6.298-7.744,10.748	c0,4.248,0.354,10.171,8.848,9.987C142.895,42.194,141.965,32.765,141.965,30.535 M133.305,49.97c0,0-8.852-6.846-14.019-14.251	c-7.015-10.918-16.97-6.471-20.298-0.927c-3.318,5.558-8.476,9.068-9.214,10c-0.745,0.912-10.692,6.287-8.485,16.101	c2.212,9.808,9.969,9.622,9.969,9.622s5.717,0.559,12.347-0.924c6.644-1.479,12.36,0.363,12.36,0.363s15.498,5.197,19.732-4.803	C139.939,55.16,133.305,49.97,133.305,49.97"/><path style="fill:#FFFFFF;" d="M102.217,40.425v6.588h-5.368c0,0-5.365,0.445-7.243,6.525c-0.655,4.06,0.578,6.451,0.793,6.963	c0.217,0.51,1.951,3.479,6.305,4.35h10.073V40.496L102.217,40.425z M102.136,60.854h-4.058c0,0-2.827-0.147-3.688-3.401	c-0.444-1.443,0.066-3.109,0.29-3.764c0.205-0.656,1.154-2.172,3.111-2.755h4.344L102.136,60.854L102.136,60.854z"/><path style="fill:#FFFFFF;" d="M109.246,47.604v12.823c0,0,0.21,3.193,4.71,4.355h11.592V47.604h-5.003v12.897h-4.775	c0,0-1.526-0.221-1.812-1.449V47.528L109.246,47.604z"/><path style="fill:#CC2229;" d="M180.779,39.185v-5.407h-35.612l-0.046,5.486h15.309l-1.435,3.28h-13.019v27.131h30.928	c3.234,0,2.947-3.266,2.947-3.266V42.544h-13.039l1.146-3.359H180.779z M173.863,63.88c0,0-0.375,0.902-0.905,0.902h-20.524v-6.328	h21.43V63.88L173.863,63.88z M173.828,53.229h-21.396v-5.933h21.396V53.229z"/><path style="fill:#CC2229;" d="M221.471,33.922h-13.972v-2.737h-6.554v2.602h-16.027v35.832h5.766V38.41h30.787V33.922z M217.703,41.337v-2.073h-5.633v2.073h-11.588v-2h-5.336v2h-3.606l0.071,4.058h3.535v7.623h19.492c2.705,0,3.063-2.853,3.063-2.853	v-4.771h4.125v-4.059h-4.124V41.337z M212.07,48.167c0,0-0.502,0.924-1.145,0.924H200.42v-3.775h11.65V48.167L212.07,48.167z M192.327,58.576l8.972,5.203c-0.71,0.782-3.775,1.773-3.775,1.773h-5.982v4h8.122c2.424-0.496,6.909-2.776,6.909-2.776	c1.857,1.705,5.426,2.415,5.426,2.415h9.258v-3.99h-6.979c-1.881-0.281-3.57-1.353-3.57-1.353l10.55-6.058v-3.281h-28.928v4.066	H192.327z M210.997,58.509l-5.132,2.705l-4.704-2.705H210.997z"/><path style="fill:#CC2229;" d="M65.929,39.626h7.773v-6.847h-7.773V39.626z M65.929,69.474h7.773V42.61h-7.773V69.474z"/><path style="fill:#CC2229;" d="M53.29,42.634l-16.584-0.043v5.646h14.542c0,0,3.461,0.854,3.461,3.051v1.988H41.55	c0,0-5.175,0.477-6.837,6.66c-0.286,2.895,0.095,4.316,0.29,4.846c0.187,0.523,1.703,3.936,6.216,4.791h20.953V50.33	C62.172,50.33,61.174,43.728,53.29,42.634 M54.709,64.255h-10.59c-1.423-0.574-1.897-1.522-1.997-1.76	c-0.098-0.234-0.428-1.084-0.044-1.945c0.857-1.659,2.277-2.041,2.277-2.041h10.354V64.255z"/><path style="fill:#CC2229;" d="M33.004,60.05c0.229-6.541-5.639-8.801-5.639-8.801c4.967-2.599,4.336-9.146,4.336-9.146	c-0.538-10.021-12.782-9.554-12.782-9.554H0v37.347h21.362C33.907,69.847,33.004,60.05,33.004,60.05 M20.933,62.955v0.016H8.136	v-8.057H20.87L21.301,55c0,0,2.423,0.443,3.301,2.623c0,0,0.508,2.047-0.589,3.568C24.013,61.191,23.206,62.599,20.933,62.955 M23.646,45.639c0,0-0.86,1.581-3.142,1.921H8.136v-7.729h12.315c0,0,2.676-0.125,3.562,2.002	C24.013,41.833,24.545,44.091,23.646,45.639"/></g></svg>
\ No newline at end of file
diff --git a/img/google.svg b/img/google.svg
deleted file mode 100644
index 3790851..0000000
--- a/img/google.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 272 92" width="272" height="92"><path fill="#EA4335" d="M115.75 47.18c0 12.77-9.99 22.18-22.25 22.18s-22.25-9.41-22.25-22.18C71.25 34.32 81.24 25 93.5 25s22.25 9.32 22.25 22.18zm-9.74 0c0-7.98-5.79-13.44-12.51-13.44S80.99 39.2 80.99 47.18c0 7.9 5.79 13.44 12.51 13.44s12.51-5.55 12.51-13.44z"/><path fill="#FBBC05" d="M163.75 47.18c0 12.77-9.99 22.18-22.25 22.18s-22.25-9.41-22.25-22.18c0-12.85 9.99-22.18 22.25-22.18s22.25 9.32 22.25 22.18zm-9.74 0c0-7.98-5.79-13.44-12.51-13.44s-12.51 5.46-12.51 13.44c0 7.9 5.79 13.44 12.51 13.44s12.51-5.55 12.51-13.44z"/><path fill="#4285F4" d="M209.75 26.34v39.82c0 16.38-9.66 23.07-21.08 23.07-10.75 0-17.22-7.19-19.66-13.07l8.48-3.53c1.51 3.61 5.21 7.87 11.17 7.87 7.31 0 11.84-4.51 11.84-13v-3.19h-.34c-2.18 2.69-6.38 5.04-11.68 5.04-11.09 0-21.25-9.66-21.25-22.09 0-12.52 10.16-22.26 21.25-22.26 5.29 0 9.49 2.35 11.68 4.96h.34v-3.61h9.25zm-8.56 20.92c0-7.81-5.21-13.52-11.84-13.52-6.72 0-12.35 5.71-12.35 13.52 0 7.73 5.63 13.36 12.35 13.36 6.63 0 11.84-5.63 11.84-13.36z"/><path fill="#34A853" d="M225 3v65h-9.5V3h9.5z"/><path fill="#EA4335" d="M262.02 54.48l7.56 5.04c-2.44 3.61-8.32 9.83-18.48 9.83-12.6 0-22.01-9.74-22.01-22.18 0-13.19 9.49-22.18 20.92-22.18 11.51 0 17.14 9.16 18.98 14.11l1.01 2.52-29.65 12.28c2.27 4.45 5.8 6.72 10.75 6.72 4.96 0 8.4-2.44 10.92-6.14zm-23.27-7.98l19.82-8.23c-1.09-2.77-4.37-4.7-8.23-4.7-4.95 0-11.84 4.37-11.59 12.93z"/><path fill="#4285F4" d="M35.29 41.41V32H67c.31 1.64.47 3.58.47 5.68 0 7.06-1.93 15.79-8.15 22.01-6.05 6.3-13.78 9.66-24.02 9.66C16.32 69.35.36 53.89.36 34.91.36 15.93 16.32.47 35.3.47c10.5 0 17.98 4.12 23.6 9.49l-6.64 6.64c-4.03-3.78-9.49-6.72-16.97-6.72-13.86 0-24.7 11.17-24.7 25.03 0 13.86 10.84 25.03 24.7 25.03 8.99 0 14.11-3.61 17.39-6.89 2.66-2.66 4.41-6.46 5.1-11.65l-22.49.01z"/></svg>
diff --git a/img/sidebar-bg.png b/img/sidebar-bg.png
deleted file mode 100644
index 13db1c1..0000000
Binary files a/img/sidebar-bg.png and /dev/null differ
diff --git a/index.html b/index.html
deleted file mode 100644
index f96e4c5..0000000
--- a/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/07/01/BarberShop/">
-		<h3 class="post-title">BarberShop</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-07-01T09:34:34.000Z" itemprop="datePublished">
-	      71.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/27/Graphviz/">
-		<h3 class="post-title">Graphviz</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-27T13:37:09.000Z" itemprop="datePublished">
-	      627.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/26/CGO/">
-		<h3 class="post-title">CGO</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-26T08:34:33.000Z" itemprop="datePublished">
-	      626.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/25/Trie/">
-		<h3 class="post-title">Trie</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-25T14:25:54.000Z" itemprop="datePublished">
-	      625.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/23/PageViews/">
-		<h3 class="post-title">Page Views</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-23T15:08:44.000Z" itemprop="datePublished">
-	      623.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/21/SkipList/">
-		<h3 class="post-title">Skip List</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-21T12:53:24.000Z" itemprop="datePublished">
-	      621.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/20/grep/">
-		<h3 class="post-title">grep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-20T06:07:24.000Z" itemprop="datePublished">
-	      620.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/19/Pipeline/">
-		<h3 class="post-title">Pipeline</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-19T08:39:47.000Z" itemprop="datePublished">
-	      619.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/18/imgcat/">
-		<h3 class="post-title">imgcat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-18T14:02:51.000Z" itemprop="datePublished">
-	      618.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/17/WorldCup/">
-		<h3 class="post-title">World Cup</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-17T07:18:49.000Z" itemprop="datePublished">
-	      617.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/2/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/index.md b/index.md
new file mode 100644
index 0000000..f76081a
--- /dev/null
+++ b/index.md
@@ -0,0 +1,48 @@
+- [] [AboutMe](AboutMe.md)
+- [] Golang 设计模式
+- [x] [CircuitBreaker](CircuitBreaker.md)
+- [x] [FactoryPattern](FactoryPattern.md)
+- [x] [Pub/Sub](PubSub.md)
+- [x] [PKCS7_Padding](PKCS7_Padding.md)
+- [] PBFT共识算法
+- [] Paxos共识算法
+- [] Raft共识算法
+- [x] [FSM](FSM.md)
+- [x] [Fan-in](Fanin.md)
+- [x] [EventProcessEngine](EventProcessEngine.md)
+- [x] [EventTimer](EventTimer.md)
+- [] p2p Discoverer
+- [x] [Protobuf](Protobuf.md)
+- [x] [DecodingDubboProtocol](DecodingDubboProtocol.md)
+- [x] [gRPC](gRPC.md)
+- [x] [LeakyBuffer](LeakyBuffer.md)
+- [] 密码学基础
+- [x] [TCP/IP](TCP_IP.md)
+- [x] [TLS](TLS.md)
+- [x] [WebSocket](WebSocket.md)
+- [] 实现一个简单的Shadowsocks
+- [] 使用 Viper & Cobra 快速构建一个命令行工具
+- [x] [Docker](Docker.md)
+- [x] [BloomFilter](BloomFilter.md)
+- [x] [MerkleTree](MerkleTree.md)
+- [] goLevelDB
+- [] 零知识证明ZKP
+- [] 工作量证明POW
+- [] Skip List
+- [] 分布式哈希表DHT
+- [x] [crontab](Crontab.md)
+- [x] [ConsistentHashing](ConsistentHashing.md)
+- [x] [etcd](etcd.md)
+- [x] [LoadBalancing](LoadBalancing.md)
+- [x] [SmoothWeightedRoundRobin](SmoothWeightedRoundRobin.md)
+- [x] [iobridge](iobridge.md)
+- [x] [Screenshot](Screenshot.md)
+- [x] [Port_0](Port_0.md)
+- [] Makefile
+- [] EDC, my Every Day Carry
+- [] Architecture of Open Source Project
+- [] [git](git.md)
+- [x] [dep](dep.md)
+- [x] [Crawler](Crawler.md)
+- [] gossip协议
+- [x] [MagnetLink](MagnetLink.md)
diff --git a/iobridge.md b/iobridge.md
new file mode 100644
index 0000000..08ac346
--- /dev/null
+++ b/iobridge.md
@@ -0,0 +1,115 @@
+# iobridge
+
+  每个人小时候都或多或少经历过父母冷战吧，当他们冷战的时候，我们这些可怜的小屁孩就成了传话筒，一般事情就会发展成下面这种情况了：
+
+  「老爸 -> 我 ：“叫你老妈安静一点”   
+    然后
+   我 -> 老妈 ：“老妈，老爸叫你安静一点”」
+ 
+  「老妈 -> 我 ：“你老爸才需要安静呢”   
+    然后 
+   我 -> 老爸 ：“老爸，老妈说你才需要安静呢”」
+
+  上述对话如此往复，诶，可怜天下小屁孩，要是冷战的话，老爸老妈必须通过一个中介人——我来进行语言上的交流。
+
+  在现代网络编程中，也会出现与上述例子极其相似的情况，例如，现在有三台服务器，分别是A，B，C，其中A能与B直接通信，B能与C直接通信，但是A不能与C直接通
+信，在这种情况下，A要想能与C交流，就必须要经过B，下面我们就来看如何实现上面这种情况吧。
+
+  下面的 `iobridge` 函数就做了一件传话筒的工作，其原理非常简单，就是从我们的数据源 `src` 读取（调用 `Read` 方法）数据，然后将它写到我们的目的地
+（调用 `Write` 方法）。也就是相当于我们上述过程中我从老妈那里获取消息，然后再将这个消息发给老爸的过程，注意到，这里函数中数据流的方法是单向的。
+
+  因为在读数据的过程中经常需要开辟新内存，为了节约运行时的成本，我们通过之前写过的 `LeakyBuffer` 模型来获取内存。
+
+```golang
+func iobridge(src io.Reader, dst io.Writer, shutdown chan struct{}) {
+    defer func() {
+        shutdown <- struct{}
+    }()
+    
+    for {
+        buf := leakyBuffer.Get()
+        n, err := src.Read(buf)
+        if err != nil {
+            if !(err == io.EOF || UseClosedConn(err)) {
+                log.Print("error reading %s:", src, err)
+            }
+            break
+        }
+        _, err := dst.Write(buf[:n])
+        if err != nil {
+            log.Prinf("error writing %s: %s\n", dst, err)
+            break
+        }
+        leakyBuffer.Put(buf)
+    }
+}
+
+func UseClosedConn(err error) bool {
+    operr, ok := err.(*net.OpErr)
+    return ok && operr.Err.Error() == "use of closed network connection"
+}
+```
+
+  因为我们的 `net.Conn` 同时定义了 `Read(b []byte) (n int, err error)` 方法和 `Write(b []byte) (n int, err error)` 方法，而这两个方法
+分别由接口 `io.Reader` 和 `io.Writer` 定义，所以 `net.Conn` 既是 `io.Reader` 也是 `io.Writer` 。故上述方法中的第一个和第二个参数我们都可以
+使用 `net.Conn` 做我们的参数。
+
+```golang
+// defined in package io
+type Reader interface {
+    Read(p []byte) (n int, err error)
+}
+
+// defined in package io
+type Writer interface {
+    Write(p []byte) (n int, err error)
+}
+
+// defined in package net
+type Conn interface {
+    Read(b []byte) (n int, err error)
+    Write(b []byte) (n int, err error)
+    ...
+    ...
+}
+```
+
+  这里的main函数应该运行在中间那台服务器也就是B上面，B作为客户端向远程服务器C发起TCP连接，并返回一个套接字conn1，同时B也作为服务器监听端口，服务来
+自A的连接请求，`Accept` 成功返回另一个套接字conn2，那么如何使得来个无法直接接触的服务器A和C有来有往的进行交流对话呢，这里的技巧就是起两个
+goroutine分别调用 `iobridge` 方法，使得两个 `net.Conn` conn1和conn2相互传递数据以互通有无，`shutdown` 这个通道这里算一个hack，用于阻塞
+main routine 不让其马上返回。
+
+```golang
+func main() {
+    conn1, err := net.Dial("tcp", "remotehost")
+    if err != nil {
+        log.Println("Error Dialing")
+        return
+    }
+
+    l. err := net.Listen("tcp", ":2333")
+    conn2, err := listener.Accept()
+    if err != nil {
+        log.Println("Error Accepting Connection")
+        return
+    }
+
+    shutdown := make(chan struct{}, 2)
+
+    go iobridge(conn1, conn2, shutdown)
+    go iobridge(conn2, conn1, shutdown)
+
+    <-shutdown
+}
+```
+
+## 总结
+  设有服务器A，B，C，除了A与C不能直接接触，其余两两都能沟通，要想A能与C进行沟通交流，解决方案就是A作为客户端调用 `net.Dial` 向B发起TCP连接，如果
+连接成功，则A上会有一个 `net.Conn` sA，B上也有一个 `net.Conn` sB1，此时B也作为客户端向C发起TCP连接，B上又多了一个 `net.Conn` sB2，C上也有一
+个`net.Conn` sC。注意这些 `net.Conn` 的本质都是一个套接字，可以直接当成文件描述符来进行操作。
+
+  此时A和C要想互相交流，唯一的方法就是将sB1和sB2进行某种程度的联系，通过起两个 `iobridge` 函数，我们就将sB1读到的数据发送给sB2，也可sB2读到的数
+据发送给sB1，注意，一旦sB1将读到的数据发送给sB2，sB2会马上把这个数据发送给sC，这样就达到了A与C相互交流的目的了。
+
+  聪明的小伙伴一定注意到了，上面讲的就是代理（shadowsocks）的基本工作原理了，是不是很简单也很有趣呢。
+  
diff --git a/js/app.js b/js/app.js
deleted file mode 100644
index c19d932..0000000
--- a/js/app.js
+++ /dev/null
@@ -1,94 +0,0 @@
-var customSearch;
-
-(function($){
-  "use strict";
-
-	var switchSidebarTab = function(e) {
-		var self = $(this),
-				target = self.attr('data-toggle'),
-				counter_target = target === 'toc' ? 'bio' : 'toc';
-		if (self.hasClass('active')) {
-			return;
-		}
-		toggleActive(self, e);
-		toggleActive(self.siblings('.dark-btn'), e);
-		$('.site-' + counter_target).toggleClass('show');
-		setTimeout(function() {
-			$('.site-' + counter_target).hide();
-			$('.site-' + target).show();
-			setTimeout(function() {
-				$('.site-' + target).toggleClass('show');
-			}, 50);
-		}, 240);
-	};
-  
-  var toggleActive = function(self, e) {
-    e.preventDefault();
-    if (self.hasClass("active") === true) {
-      self.removeClass("active");
-    }
-    else {
-      self.addClass("active");
-    }
-  };
-
-  var scrolltoElement = function(e) {
-    e.preventDefault();
-    var self = $(this),
-        correction = e.data ? e.data.correction ? e.data.correction : 0 : 0;
-    $('html, body').animate({'scrollTop': $(self.attr('href')).offset().top - correction }, 400);
-  };
-
-  var openBio = function(e) {
-    var self = $(this);
-    toggleActive(self, e);
-    $('body').addClass('bio-open');
-  };
-
-  var closeBio = function(e) {
-    $('body').removeClass('bio-open');
-    toggleActive($('.site-nav-switch'), e);
-  };
-  
-  $(function() {
-	  $(".post-list, #footer, #page-nav").addClass('show');
-	  $('.site-nav-switch').on('click', openBio);
-	  $('.site-wrapper .overlay').on('click', closeBio);
-	  $('.window-nav, .go-comment, .site-toc a').on('click', scrolltoElement);
-	  $('.sidebar-switch .dark-btn').on('click', switchSidebarTab);
-	  
-	  setTimeout(function() {
-	    $('#loading-bar-wrapper').fadeOut(500);
-	  }, 300);
-	  
-	  if (SEARCH_SERVICE === 'google') {
-  	  customSearch = new GoogleCustomSearch({
-    	  apiKey: GOOGLE_CUSTOM_SEARCH_API_KEY,
-    	  engineId: GOOGLE_CUSTOM_SEARCH_ENGINE_ID
-  	  });
-	  }
-	  else if (SEARCH_SERVICE === 'algolia') {
-  	  customSearch = new AlgoliaSearch({
-    	  apiKey: ALGOLIA_API_KEY,
-    	  appId: ALGOLIA_APP_ID,
-    	  indexName: ALGOLIA_INDEX_NAME
-  	  });
-	  }
-	  else if (SEARCH_SERVICE === 'hexo') {
-  	  customSearch = new HexoSearch();
-	  }
-	  else if (SEARCH_SERVICE === 'azure') {
-  	  customSearch = new AzureSearch({
-    	  serviceName: AZURE_SERVICE_NAME,
-        indexName: AZURE_INDEX_NAME,
-        queryKey: AZURE_QUERY_KEY
-  	  });
-	  }
-	  else if (SEARCH_SERVICE === 'baidu') {
-  	  customSearch = new BaiduSearch({
-				apiId: BAIDU_API_ID
-			});
-	  }
-	});
-
-})(jQuery);
diff --git a/js/jquery.js b/js/jquery.js
deleted file mode 100644
index fc356ee..0000000
--- a/js/jquery.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */
-!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){
-return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=L.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var Q=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,R=["Top","Right","Bottom","Left"],S=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)},T=/^(?:checkbox|radio)$/i;!function(){var a=l.createDocumentFragment(),b=a.appendChild(l.createElement("div")),c=l.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||l,d=c.documentElement,e=c.body,a.pageX=b.clientX+(d&&d.scrollLeft||e&&e.scrollLeft||0)-(d&&d.clientLeft||e&&e.clientLeft||0),a.pageY=b.clientY+(d&&d.scrollTop||e&&e.scrollTop||0)-(d&&d.clientTop||e&&e.clientTop||0)),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=W.test(e)?this.mouseHooks:V.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new n.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=l),3===a.target.nodeType&&(a.target=a.target.parentNode),g.filter?g.filter(a,f):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==_()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===_()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=n.extend(new n.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?n.event.trigger(e,null,b):n.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?Z:$):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={isDefaultPrevented:$,isPropagationStopped:$,isImmediatePropagationStopped:$,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=Z,a&&a.preventDefault&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=Z,a&&a.stopPropagation&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=Z,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!n.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.focusinBubbles||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a),!0)};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=L.access(d,b);e||d.addEventListener(a,c,!0),L.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=L.access(d,b)-1;e?L.access(d,b,e):(d.removeEventListener(a,c,!0),L.remove(d,b))}}}),n.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(g in a)this.on(g,b,c,a[g],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=$;else if(!d)return this;return 1===e&&(f=d,d=function(a){return n().off(a),f.apply(this,arguments)},d.guid=f.guid||(f.guid=n.guid++)),this.each(function(){n.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=$),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ia={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1></$2>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=qa[0].contentDocument,b.write(),b.close(),c=sa(a,b),qa.detach()),ra[a]=c),c}var ua=/^margin/,va=new RegExp("^("+Q+")(?!px)[a-z%]+$","i"),wa=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)};function xa(a,b,c){var d,e,f,g,h=a.style;return c=c||wa(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),va.test(g)&&ua.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function ya(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d=l.documentElement,e=l.createElement("div"),f=l.createElement("div");if(f.style){f.style.backgroundClip="content-box",f.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===f.style.backgroundClip,e.style.cssText="border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;position:absolute",e.appendChild(f);function g(){f.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",f.innerHTML="",d.appendChild(e);var g=a.getComputedStyle(f,null);b="1%"!==g.top,c="4px"===g.width,d.removeChild(e)}a.getComputedStyle&&n.extend(k,{pixelPosition:function(){return g(),b},boxSizingReliable:function(){return null==c&&g(),c},reliableMarginRight:function(){var b,c=f.appendChild(l.createElement("div"));return c.style.cssText=f.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",f.style.width="1px",d.appendChild(e),b=!parseFloat(a.getComputedStyle(c,null).marginRight),d.removeChild(e),f.removeChild(c),b}})}}(),n.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var za=/^(none|table(?!-c[ea]).+)/,Aa=new RegExp("^("+Q+")(.*)$","i"),Ba=new RegExp("^([+-])=("+Q+")","i"),Ca={position:"absolute",visibility:"hidden",display:"block"},Da={letterSpacing:"0",fontWeight:"400"},Ea=["Webkit","O","Moz","ms"];function Fa(a,b){if(b in a)return b;var c=b[0].toUpperCase()+b.slice(1),d=b,e=Ea.length;while(e--)if(b=Ea[e]+c,b in a)return b;return d}function Ga(a,b,c){var d=Aa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Ha(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+R[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+R[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+R[f]+"Width",!0,e))):(g+=n.css(a,"padding"+R[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+R[f]+"Width",!0,e)));return g}function Ia(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=wa(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=xa(a,b,f),(0>e||null==e)&&(e=a.style[b]),va.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Ha(a,b,c||(g?"border":"content"),d,f)+"px"}function Ja(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=L.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&S(d)&&(f[g]=L.access(d,"olddisplay",ta(d.nodeName)))):(e=S(d),"none"===c&&e||L.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=xa(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Fa(i,h)),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=Ba.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(n.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||n.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Fa(a.style,h)),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=xa(a,b,d)),"normal"===e&&b in Da&&(e=Da[b]),""===c||c?(f=parseFloat(e),c===!0||n.isNumeric(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?za.test(n.css(a,"display"))&&0===a.offsetWidth?n.swap(a,Ca,function(){return Ia(a,b,d)}):Ia(a,b,d):void 0},set:function(a,c,d){var e=d&&wa(a);return Ga(a,c,d?Ha(a,b,d,"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),n.cssHooks.marginRight=ya(k.reliableMarginRight,function(a,b){return b?n.swap(a,{display:"inline-block"},xa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+R[d]+b]=f[d]||f[d-2]||f[0];return e}},ua.test(a)||(n.cssHooks[a+b].set=Ga)}),n.fn.extend({css:function(a,b){return J(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=wa(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Ja(this,!0)},hide:function(){return Ja(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){S(this)?n(this).show():n(this).hide()})}});function Ka(a,b,c,d,e){return new Ka.prototype.init(a,b,c,d,e)}n.Tween=Ka,Ka.prototype={constructor:Ka,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ka.propHooks[this.prop];return a&&a.get?a.get(this):Ka.propHooks._default.get(this)},run:function(a){var b,c=Ka.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ka.propHooks._default.set(this),this}},Ka.prototype.init.prototype=Ka.prototype,Ka.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[n.cssProps[a.prop]]||n.cssHooks[a.prop])?n.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Ka.propHooks.scrollTop=Ka.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},n.fx=Ka.prototype.init,n.fx.step={};var La,Ma,Na=/^(?:toggle|show|hide)$/,Oa=new RegExp("^(?:([+-])=|)("+Q+")([a-z%]*)$","i"),Pa=/queueHooks$/,Qa=[Va],Ra={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=Oa.exec(b),f=e&&e[3]||(n.cssNumber[a]?"":"px"),g=(n.cssNumber[a]||"px"!==f&&+d)&&Oa.exec(n.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,n.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function Sa(){return setTimeout(function(){La=void 0}),La=n.now()}function Ta(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=R[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ua(a,b,c){for(var d,e=(Ra[b]||[]).concat(Ra["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Va(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&S(a),q=L.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?L.get(a,"olddisplay")||ta(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Na.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?ta(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=L.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;L.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ua(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function Wa(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function Xa(a,b,c){var d,e,f=0,g=Qa.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=La||Sa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:La||Sa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(Wa(k,j.opts.specialEasing);g>f;f++)if(d=Qa[f].call(j,a,k,j.opts))return d;return n.map(k,Ua,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(Xa,{tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],Ra[c]=Ra[c]||[],Ra[c].unshift(b)},prefilter:function(a,b){b?Qa.unshift(a):Qa.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(S).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=Xa(this,n.extend({},a),f);(e||L.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=L.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Pa.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=L.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Ta(b,!0),a,d,e)}}),n.each({slideDown:Ta("show"),slideUp:Ta("hide"),slideToggle:Ta("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(La=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),La=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ma||(Ma=setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){clearInterval(Ma),Ma=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(a,b){return a=n.fx?n.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a=l.createElement("input"),b=l.createElement("select"),c=b.appendChild(l.createElement("option"));a.type="checkbox",k.checkOn=""!==a.value,k.optSelected=c.selected,b.disabled=!0,k.optDisabled=!c.disabled,a=l.createElement("input"),a.value="t",a.type="radio",k.radioValue="t"===a.value}();var Ya,Za,$a=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return J(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===U?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),d=n.attrHooks[b]||(n.expr.match.bool.test(b)?Za:Ya)),
-void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void n.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),Za={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=$a[b]||n.find.attr;$a[b]=function(a,b,d){var e,f;return d||(f=$a[b],$a[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,$a[b]=f),e}});var _a=/^(?:input|select|textarea|button)$/i;n.fn.extend({prop:function(a,b){return J(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!n.isXMLDoc(a),f&&(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||_a.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),k.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var ab=/[\t\r\n\f]/g;n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=n.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0===arguments.length||"string"==typeof a&&a,i=0,j=this.length;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(E)||[];j>i;i++)if(c=this[i],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ab," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?n.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(n.isFunction(a)?function(c){n(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=n(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===U||"boolean"===c)&&(this.className&&L.set(this,"__className__",this.className),this.className=this.className||a===!1?"":L.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ab," ").indexOf(b)>=0)return!0;return!1}});var bb=/\r/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(bb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(d.value,f)>=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>=0:void 0}},k.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var cb=n.now(),db=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(d){b=void 0}return(!b||b.getElementsByTagName("parsererror").length)&&n.error("Invalid XML: "+a),b};var eb=/#.*$/,fb=/([?&])_=[^&]*/,gb=/^(.*?):[ \t]*([^\r\n]*)$/gm,hb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,ib=/^(?:GET|HEAD)$/,jb=/^\/\//,kb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,lb={},mb={},nb="*/".concat("*"),ob=a.location.href,pb=kb.exec(ob.toLowerCase())||[];function qb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function rb(a,b,c,d){var e={},f=a===mb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function sb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function tb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function ub(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ob,type:"GET",isLocal:hb.test(pb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":nb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?sb(sb(a,n.ajaxSettings),b):sb(n.ajaxSettings,a)},ajaxPrefilter:qb(lb),ajaxTransport:qb(mb),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=n.ajaxSetup({},b),l=k.context||k,m=k.context&&(l.nodeType||l.jquery)?n(l):n.event,o=n.Deferred(),p=n.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!f){f={};while(b=gb.exec(e))f[b[1].toLowerCase()]=b[2]}b=f[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?e:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return c&&c.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||ob)+"").replace(eb,"").replace(jb,pb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=n.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(h=kb.exec(k.url.toLowerCase()),k.crossDomain=!(!h||h[1]===pb[1]&&h[2]===pb[2]&&(h[3]||("http:"===h[1]?"80":"443"))===(pb[3]||("http:"===pb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=n.param(k.data,k.traditional)),rb(lb,k,b,v),2===t)return v;i=n.event&&k.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!ib.test(k.type),d=k.url,k.hasContent||(k.data&&(d=k.url+=(db.test(d)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=fb.test(d)?d.replace(fb,"$1_="+cb++):d+(db.test(d)?"&":"?")+"_="+cb++)),k.ifModified&&(n.lastModified[d]&&v.setRequestHeader("If-Modified-Since",n.lastModified[d]),n.etag[d]&&v.setRequestHeader("If-None-Match",n.etag[d])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+nb+"; q=0.01":""):k.accepts["*"]);for(j in k.headers)v.setRequestHeader(j,k.headers[j]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(j in{success:1,error:1,complete:1})v[j](k[j]);if(c=rb(mb,k,b,v)){v.readyState=1,i&&m.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,c.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,f,h){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),c=void 0,e=h||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,f&&(u=tb(k,v,f)),u=ub(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(n.lastModified[d]=w),w=v.getResponseHeader("etag"),w&&(n.etag[d]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,i&&m.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),i&&(m.trigger("ajaxComplete",[v,k]),--n.active||n.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return this.each(n.isFunction(a)?function(b){n(this).wrapInner(a.call(this,b))}:function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var vb=/%20/g,wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&").replace(vb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!T.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Bb=0,Cb={},Db={0:200,1223:204},Eb=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Cb)Cb[a]()}),k.cors=!!Eb&&"withCredentials"in Eb,k.ajax=Eb=!!Eb,n.ajaxTransport(function(a){var b;return k.cors||Eb&&!a.crossDomain?{send:function(c,d){var e,f=a.xhr(),g=++Bb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Cb[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Db[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Cb[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(h){if(b)throw h}},abort:function(){b&&b()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=n("<script>").prop({async:!0,charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&e("error"===a.type?404:200,a.type)}),l.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Fb=[],Gb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Fb.pop()||n.expando+"_"+cb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Gb.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Gb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Gb,"$1"+e):b.jsonp!==!1&&(b.url+=(db.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Fb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||l;var d=v.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=n.buildFragment([a],b,e),e&&e.length&&n(e).remove(),n.merge([],d.childNodes))};var Hb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Hb)return Hb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e,dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,f||[a.responseText,b,a])}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};var Ib=a.document.documentElement;function Jb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(typeof d.getBoundingClientRect!==U&&(e=d.getBoundingClientRect()),c=Jb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||Ib;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ib})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(b,c){var d="pageYOffset"===c;n.fn[b]=function(e){return J(this,function(b,e,f){var g=Jb(b);return void 0===f?g?g[c]:b[e]:void(g?g.scrollTo(d?a.pageXOffset:f,d?f:a.pageYOffset):b[e]=f)},b,e,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=ya(k.pixelPosition,function(a,c){return c?(c=xa(a,b),va.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return J(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Kb=a.jQuery,Lb=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Lb),b&&a.jQuery===n&&(a.jQuery=Kb),n},typeof b===U&&(a.jQuery=a.$=n),n});
\ No newline at end of file
diff --git a/js/search.js b/js/search.js
deleted file mode 100644
index 7cd8805..0000000
--- a/js/search.js
+++ /dev/null
@@ -1,797 +0,0 @@
-var SearchService = "";
-
-(function($) {
-  /**
-   * A super class of common logics for all search services
-   * @param options : (object)
-   */
-  SearchService = function(options) {
-    var self = this;
-    
-    self.config = $.extend({
-      per_page: 10,
-      selectors: {
-        body: "body",
-        form: ".u-search-form",
-        input: ".u-search-input",
-        container: "#u-search",
-        modal: "#u-search .modal",
-        modal_body: "#u-search .modal-body",
-        modal_footer: "#u-search .modal-footer",
-        modal_overlay: "#u-search .modal-overlay",
-        modal_results: "#u-search .modal-results",
-        modal_metadata: "#u-search .modal-metadata",
-        modal_error: "#u-search .modal-error",
-        modal_loading_bar: "#u-search .modal-loading-bar",
-        modal_ajax_content: "#u-search .modal-ajax-content",
-        modal_logo: '#u-search .modal-footer .logo',
-        btn_close: "#u-search .btn-close",
-        btn_next: "#u-search .btn-next",
-        btn_prev: "#u-search .btn-prev"
-      },
-      brands: {
-        'google': {logo: '/img/google.svg', url: 'https://cse.google.com'},
-        'algolia': {logo: '/img/algolia.svg', url: 'https://www.algolia.com'},
-        'hexo': {logo: '', url: ''},
-        'azure': {logo: '/img/azure.svg', url: 'https://azure.microsoft.com/en-us/services/search/'},
-        'baidu': {logo: '/img/baidu.svg', url: 'http://zn.baidu.com/cse/home/index'}
-      }
-    }, options);
-
-    self.dom = {};
-    self.percentLoaded = 0;
-    self.open = false;
-    self.queryText = "";
-    self.nav = {
-      next: -1,
-      prev: -1,
-      total: 0,
-      current: 1
-    };
-
-    self.parseSelectors = function() {
-      for (var key in self.config.selectors) {
-        self.dom[key] = $(self.config.selectors[key]);
-      }
-    };
-
-    self.beforeQuery = function() {
-      if (!self.open) {
-        self.dom.container.fadeIn();
-        self.dom.body.addClass('modal-active');
-      }
-      self.dom.input.each(function(index,elem) {
-        $(elem).val(self.queryText);
-      });
-      document.activeElement.blur();
-      self.dom.modal_error.hide();
-      self.dom.modal_ajax_content.removeClass('loaded');
-      self.startLoading();
-    };
-    
-    self.afterQuery = function() {
-      self.dom.modal_body.scrollTop(0);
-      self.dom.modal_ajax_content.addClass('loaded');
-      self.stopLoading();
-    };
-
-    /**
-     * Perform a complete serach operation including UI updates and query
-     * @param startIndex {int} start index or page number
-     */
-    self.search = function(startIndex, callback) {
-      self.beforeQuery();
-      if (self.search instanceof Function) {
-        self.query(self.queryText, startIndex, function() {
-          self.afterQuery();
-        });
-      }
-      else {
-        console.log("query() does not exist.");
-        self.onQueryError(self.queryText, '');
-        self.afterQuery();
-      }
-    };
-
-    /**
-     * Query error handler
-     * @param queryText: (string)
-     * @param status: (string)
-     */
-    self.onQueryError = function(queryText, status) {
-      var errMsg = "";
-      if (status === "success") errMsg = "No result found for \"" +queryText+ "\".";
-      else if (status === "timeout") errMsg = "Unfortunate timeout.";
-      else errMsg = "Mysterious failure.";
-      self.dom.modal_results.html("");
-      self.dom.modal_error.html(errMsg);
-      self.dom.modal_error.show();
-    };
-    
-    self.nextPage = function() {
-      if (self.nav.next !== -1) {
-        self.search(self.nav.next);
-      }
-    };
-    
-    self.prevPage = function() {
-      if (self.nav.prev !== -1) {
-        self.search(self.nav.prev);
-      }
-    };
-    
-    /**
-     * Generate html for one result
-     * @param url : (string) url
-     * @param title : (string) title
-     * @param digest : (string) digest
-     */
-    self.buildResult = function(url, title, digest) {
-      var html = "";
-      html = "<li>";
-      html +=   "<a class='result' href='" +url+ "'>";
-      html +=     "<span class='title'>" +title+ "</span>";
-      html +=     "<span class='digest'>" +digest+ "</span>";
-      html +=     "<span class='icon icon-chevron-thin-right'></span>";
-      html +=   "</a>";
-      html += "</li>";
-      return html;
-    };
-    
-    /**
-     * Close the modal, resume body scrolling
-     * no param
-     */
-    self.close = function() {
-      self.open = false;
-      self.dom.container.fadeOut();
-      self.dom.body.removeClass('modal-active');
-    };
-    
-    /**
-     * Searchform submit event handler
-     * @param queryText : (string) the query text
-     */
-    self.onSubmit = function(event) {
-      event.preventDefault();
-      self.queryText = $(this).children('.u-search-input').val();
-      self.search(1);
-    };
-    
-    /**
-     * Start loading bar animation
-     * no param
-     */
-    self.startLoading = function() {
-      self.dom.modal_loading_bar.show();
-      self.loadingTimer = setInterval(function() { 
-        self.percentLoaded = Math.min(self.percentLoaded+5,95);
-        self.dom.modal_loading_bar.css('width', self.percentLoaded+'%');
-      }, 100);
-    };
-    
-    /**
-     * Stop loading bar animation
-     * no param
-     */
-    self.stopLoading = function() {
-      clearInterval(self.loadingTimer);
-      self.dom.modal_loading_bar.css('width', '100%');
-      self.dom.modal_loading_bar.fadeOut();
-      setTimeout(function() {
-        self.percentLoaded = 0;
-        self.dom.modal_loading_bar.css('width', '0%');
-      }, 300);
-    };
-
-    /**
-     * Add service branding
-     * @param service {String} service name
-     */
-    self.addLogo = function(service) {
-      var html = "";
-      if (self.config.brands[service] && self.config.brands[service].logo) {
-        html += "<a href='" +self.config.brands[service].url+ "'>";
-        html +=    '<img src="' +self.config.brands[service].logo+ '" />';
-        html += "</a>";
-        self.dom.modal_logo.html(html);
-        self.dom.modal_logo.addClass(service);
-      }
-    };
-    
-    /**
-     * Load template and register event handlers
-     * no param
-     */
-    self.init = function() {
-      $('body').append(template);
-      self.parseSelectors();
-      self.dom.form.each(function(index,elem) {
-        $(elem).on('submit', self.onSubmit);
-      });
-      self.dom.modal_overlay.on('click', self.close);
-      self.dom.btn_close.on('click', self.close);
-      self.dom.btn_next.on('click', self.nextPage);
-      self.dom.btn_prev.on('click', self.prevPage);
-    };
-
-    self.init();
-  };
-
-  var template = '<div id="u-search"><div class="modal"> <header class="modal-header" class="clearfix"><form id="u-search-modal-form" class="u-search-form" name="uSearchModalForm"> <input type="text" id="u-search-modal-input" class="u-search-input" /> <button type="submit" id="u-search-modal-btn-submit" class="u-search-btn-submit"> <span class="icon icon-search"></span> </button></form> <a class="btn-close"> <span class="icon icon-close"></span> </a><div class="modal-loading"><div class="modal-loading-bar"></div></div> </header> <main class="modal-body"><ul class="modal-results modal-ajax-content"></ul> </main> <footer class="modal-footer clearfix"><div class="modal-metadata modal-ajax-content"> <strong class="range"></strong> of <strong class="total"></strong></div><div class="modal-error"></div> <div class="logo"></div> <a class="nav btn-next modal-ajax-content"> <span class="text">NEXT</span> <span class="icon icon-chevron-right"></span> </a> <a class="nav btn-prev modal-ajax-content"> <span class="icon icon-chevron-left"></span> <span class="text">PREV</span> </a> </footer></div><div class="modal-overlay"></div></div>';
-})(jQuery);
-
-var AlgoliaSearch;
-
-(function($) {
-  'use strict';
-
-  /**
-   * Search by Algolia Search
-   * @param options : (object)
-   */
-  AlgoliaSearch = function(options) {
-    SearchService.apply(this, arguments);
-    var self = this;
-    var endpoint = "https://" +self.config.appId+ "-dsn.algolia.net/1/indexes/" +self.config.indexName;
-    self.addLogo('algolia');
-    
-    /**
-     * Generate result list html
-     * @param data : (array) result items
-     */
-    self.buildResultList = function(data) {
-      var html = "";
-      $.each(data, function(index, row) {
-        var url = row.permalink || row.path || "";
-        if (!row.permalink && row.path) {
-          url = "/" + url;
-        }
-        var title = row.title;
-        var digest = row._highlightResult.excerptStrip.value || "";
-        html += self.buildResult(url, title, digest);
-      });
-      return html;
-    };
-    
-    /**
-     * Generate metadata after a successful query
-     * @param data : (object) the raw search response data
-     */
-    self.buildMetadata = function(data) {
-      self.nav.current = data.page * data.hitsPerPage + 1;
-      self.nav.currentCount = data.hits.length;
-      self.nav.total = parseInt(data.nbHits);
-      self.dom.modal_metadata.children('.total').html(self.nav.total);
-      self.dom.modal_metadata.children('.range').html(self.nav.current + "-" + (self.nav.current+self.nav.currentCount-1));
-      if (self.nav.total > 0) {
-        self.dom.modal_metadata.show();
-      }
-      else {
-        self.dom.modal_metadata.hide();
-      }
-
-      if (data.page < data.nbPages-1) {
-        self.nav.next = (data.page+1)+1;
-        self.dom.btn_next.show();
-      }
-      else {
-        self.nav.next = -1;
-        self.dom.btn_next.hide();
-      }
-      if (data.page > 0) {
-        self.nav.prev = (data.page+1)-1;
-        self.dom.btn_prev.show();
-      }
-      else {
-        self.nav.prev = -1;
-        self.dom.btn_prev.hide();
-      }
-    };
-    
-    /**
-     * Send a GET request
-     * @param queryText : (string) the query text
-     * @param page : (int) the current page (start from 1)
-     * @param callback : (function)
-     */
-    self.query = function(queryText, page, callback) {
-      $.get(endpoint, {
-        query: queryText,
-        page: page-1,
-        hitsPerPage: self.config.per_page,
-        "x-algolia-application-id": self.config.appId,
-        "x-algolia-api-key": self.config.apiKey
-      }, function(data, status) {
-        if (status === 'success' && data.hits && data.hits.length > 0) {
-          var results = self.buildResultList(data.hits); 
-          self.dom.modal_results.html(results);
-        }
-        else {
-          self.onQueryError(queryText, status);
-        }
-        self.buildMetadata(data);
-        if (callback) {
-          callback(data);
-        }
-      });
-    };
-    
-  };
-
-})(jQuery);
-
-var AzureSearch;
-
-(function($) {
-  'use strict';
-
-  /**
-   * Search by Azure Search API
-   * @param options : (object)
-   */
-  AzureSearch = function(options) {
-    SearchService.apply(this, arguments);
-    var self = this;
-    var endpoint = "https://" +self.config.serviceName+ ".search.windows.net/indexes/" +self.config.indexName+ "/docs?api-version=2015-02-28";
-    self.nav.current = 1;
-    self.addLogo('azure');
-    
-    /**
-     * Generate result list html
-     * @param data : (array) result items
-     */
-    self.buildResultList = function(data) {
-      var html = "";
-      $.each(data, function(index, row) {
-        var url = row.permalink || row.path || "";
-        if (!row.permalink && row.path) {
-          url = "/" + url;
-        }
-        var title = row.title;
-        var digest = row.excerptStrip || "";
-        html += self.buildResult(url, title, digest);
-      });
-      return html;
-    };
-    
-    /**
-     * Generate metadata after a successful query
-     * @param data : (object) the raw response data
-     * @param startIndex : (int) requested start index of current query
-     */
-    self.buildMetadata = function(data, startIndex) {
-      self.nav.current = startIndex;
-      self.nav.currentCount = data.value.length;
-      self.nav.total = parseInt(data['@odata.count']);
-      self.dom.modal_metadata.children('.total').html(self.nav.total);
-      self.dom.modal_metadata.children('.range').html(self.nav.current + "-" + (self.nav.current+self.nav.currentCount-1));
-      if (self.nav.total > 0) {
-        self.dom.modal_metadata.show();
-      }
-      else {
-        self.dom.modal_metadata.hide();
-      }
-
-      if (self.nav.current+self.nav.currentCount <= self.nav.total) {
-        self.nav.next = self.nav.current+self.nav.currentCount;
-        self.dom.btn_next.show();
-      }
-      else {
-        self.nav.next = -1;
-        self.dom.btn_next.hide();
-      }
-      if (self.nav.current > 1) {
-        self.nav.prev = self.nav.current-self.config.per_page;
-        self.dom.btn_prev.show();
-      }
-      else {
-        self.nav.prev = -1;
-        self.dom.btn_prev.hide();
-      }
-    };
-    
-    /**
-     * Send a GET request
-     * @param queryText : (string) the query text
-     * @param page : (int) the current page (start from 1)
-     * @param callback : (function)
-     */
-    self.query = function(queryText, startIndex, callback) {
-      $.ajax({
-        url: endpoint,
-        headers: {
-          "Accept": "application/json",
-          "api-key": self.config.queryKey
-        },
-        data: {
-          search: queryText,
-          $skip: startIndex-1,
-          $top: self.config.per_page,
-          $count: true
-        },
-        type: "GET",
-        success: function(data, status) {
-          if (status === 'success' && data.value && data.value.length > 0) {
-            var results = self.buildResultList(data.value);
-            self.dom.modal_results.html(results);
-          }
-          else {
-            self.onQueryError(queryText, status);
-          }
-          self.buildMetadata(data, startIndex);
-          if (callback) {
-            callback(data);
-          }
-        }
-      });
-    };
-
-  };
-
-})(jQuery);
-
-var BaiduSearch;
-
-(function($) {
-  'use strict';
-
-  /**
-   * TODO
-   * Search by Baidu Search API
-   * @param options : (object)
-   */
-  BaiduSearch = function(options) {
-    SearchService.apply(this, arguments);
-    var self = this;
-    var endpoint = "";
-    self.addLogo('baidu');
-
-    self.loadScript = function() {
-      self.dom.form.attr('disabled', true);
-      var script = "<script src='http://zhannei.baidu.com/api/customsearch/apiaccept?sid=" +self.config.apiId+ "&v=2.0&callback=customSearch.initBaidu' type='text/javascript' charset='utf-8'></script>";
-      self.dom.body.append(script);
-    };
-
-    self.initBaidu = function() {
-      console.log("init baidu search");
-      self.cse = new BCse.Search(self.config.apiId);
-      self.dom.form.attr('disabled', false);
-    };
-
-    /**
-     * Get search results
-     * @param queryText {String}
-     * @param page {Integer}
-     * @param callback {Function}
-     */
-    self.query = function(queryText, page, callback) {
-      self.cse.setPageNum(self.config.per_page);
-      self.cse.getResult(queryText, function(data) {
-        console.log(data);
-        if (callback instanceof Function) {
-          callback();
-        }
-      }, page);
-    };
-
-    self.loadScript();
-    
-  };
-
-})(jQuery);
-
-var GoogleCustomSearch = "";
-
-(function($) {
-  'use strict';
-  
-  /**
-   * Search by Google Custom Search Engine JSON API
-   * @param options : (object)
-   */
-  GoogleCustomSearch = function(options) {
-    SearchService.apply(this, arguments);
-    var self = this;
-    var endpoint = "https://www.googleapis.com/customsearch/v1";
-    self.addLogo('google');
-
-    /**
-     * Generate result list html
-     * @param data : (array) result items
-     */
-    self.buildResultList = function(data) {
-      var html = "";
-      $.each(data, function(index, row) {
-        var url = row.link;
-        var title = row.title;
-        var digest = (row.htmlSnippet || "").replace('<br>','');
-        html += self.buildResult(url, title, digest);
-      });
-      return html;
-    };
-    
-    /**
-     * Generate metadata after a successful query
-     * @param data : (object) the raw google custom search response data
-     */
-    self.buildMetadata = function(data) {
-      if (data.queries && data.queries.request && data.queries.request[0].totalResults !== '0') {
-        self.nav.current = data.queries.request[0].startIndex;
-        self.nav.currentCount = data.queries.request[0].count;
-        self.nav.total = parseInt(data.queries.request[0].totalResults);
-        self.dom.modal_metadata.children('.total').html(self.nav.total);
-        self.dom.modal_metadata.children('.range').html(self.nav.current + "-" + (self.nav.current+self.nav.currentCount-1));
-        self.dom.modal_metadata.show();
-      }
-      else {
-        self.dom.modal_metadata.hide();
-      }
-      if (data.queries && data.queries.nextPage) {
-        self.nav.next = data.queries.nextPage[0].startIndex;
-        self.dom.btn_next.show();
-      }
-      else {
-        self.nav.next = -1;
-        self.dom.btn_next.hide();
-      }
-      if (data.queries && data.queries.previousPage) {
-        self.nav.prev = data.queries.previousPage[0].startIndex;
-        self.dom.btn_prev.show();
-      }
-      else {
-        self.nav.prev = -1;
-        self.dom.btn_prev.hide();
-      }
-    };
-    
-    /**
-     * Send a GET request
-     * @param queryText : (string) the query text
-     * @param startIndex : (int) the index of first item (start from 1)
-     * @param callback : (function)
-     */
-    self.query = function(queryText, startIndex, callback) {
-      $.get(endpoint, {
-        key: self.config.apiKey,
-        cx: self.config.engineId,
-        q: queryText,
-        start: startIndex,
-        num: self.config.per_page
-      }, function(data, status) {
-        if (status === 'success' && data.items && data.items.length > 0) {
-          var results = self.buildResultList(data.items); 
-          self.dom.modal_results.html(results);       
-        }
-        else {
-          self.onQueryError(queryText, status);
-        }
-        self.buildMetadata(data);
-        if (callback) {
-          callback();
-        }
-      });
-    };
-    
-  };
-})(jQuery);
-
-var HexoSearch;
-
-(function($) {
-  'use strict';
-  
-  /**
-  * Search by Hexo generator json content
-  * @param options : (object)
-  */
-  HexoSearch = function(options) {
-    SearchService.apply(this, arguments);
-    var self = this;
-    var endpoint = "/content.json";
-    self.cache = "";
-    
-    /**
-     * Search queryText in title and content of a post
-     * Credit to: http://hahack.com/codes/local-search-engine-for-hexo/
-     * @param post : the post object
-     * @param queryText : the search query
-     */
-    self.contentSearch = function(post, queryText) {
-      var post_title = post.title.trim().toLowerCase(),
-          post_content = post.text.trim().toLowerCase(),
-          keywords = queryText.trim().toLowerCase().split(" "),
-          foundMatch = false,
-          index_title = -1,
-          index_content = -1,
-          first_occur = -1;
-      if (post_title !== '' && post_content !== '') {
-        $.each(keywords, function(index, word) {
-          index_title = post_title.indexOf(word);
-          index_content = post_content.indexOf(word);
-          if (index_title < 0 && index_content < 0) {
-            foundMatch = false;
-          }
-          else {
-            foundMatch = true;
-            if (index_content < 0) {
-              index_content = 0;
-            }
-            if (index === 0) {
-              first_occur = index_content;
-            }
-          }
-          if (foundMatch) {
-            post_content = post.text.trim();
-            var start = 0, end = 0;
-            if (first_occur >= 0) {
-              start = Math.max(first_occur-30, 0);
-              end = (start === 0) ? Math.min(200, post_content.length) : Math.min(first_occur+170, post_content.length);
-              var match_content = post_content.substring(start, end);
-              keywords.forEach(function(keyword) {
-                var regS = new RegExp(keyword, "gi");
-                match_content = match_content.replace(regS, "<b>"+keyword+"</b>");
-              });
-              post.digest = match_content;
-            }
-            else {
-              end = Math.min(200, post_content.length);
-              post.digest = post_content.trim().substring(0, end);
-            }
-          }
-        });
-      }
-      return foundMatch;
-    };
-    
-    /**
-     * Generate result list html
-     * @param data : (array) result items
-     */
-    self.buildResultList = function(data, queryText) {
-      var results = [],
-          html = "";
-      $.each(data, function(index, post) {
-        if (self.contentSearch(post, queryText))
-          html += self.buildResult(post.permalink, post.title, post.digest);
-      });
-      return html;
-    };
-    
-    /**
-     * Generate metadata after a successful query
-     * @param data : (object) the raw google custom search response data
-     */
-    self.buildMetadata = function(data) {
-      self.dom.modal_footer.hide();
-    };
-    
-    /**
-     * Send a GET request
-     * @param queryText : (string) the query text
-     * @param startIndex : (int) the index of first item (start from 1)
-     * @param callback : (function)
-     */
-    self.query = function(queryText, startIndex, callback) {
-      if (!self.cache) {
-        $.get(endpoint, {
-          key: self.config.apiKey,
-          cx: self.config.engineId,
-          q: queryText,
-          start: startIndex,
-          num: self.config.per_page
-        }, function(data, status) {
-          if (status !== 'success' || 
-              !data || 
-              (!data.posts && !data.pages) || 
-              (data.posts.length < 1 && data.pages.length < 1)
-            ) {
-            self.onQueryError(queryText, status);
-          }
-          else {
-            self.cache = data;
-            var results = ""; 
-            results += self.buildResultList(data.pages, queryText);
-            results += self.buildResultList(data.posts, queryText);
-            self.dom.modal_results.html(results);
-          }
-          self.buildMetadata(data);
-          if (callback) {
-            callback(data);
-          }
-        });
-      }
-      else {
-        var results = ""; 
-        results += self.buildResultList(self.cache.pages, queryText);
-        results += self.buildResultList(self.cache.posts, queryText);
-        self.dom.modal_results.html(results);
-        self.buildMetadata(self.cache);
-        if (callback) {
-          callback(self.cache);
-        }
-      }
-    };
-    
-  };
-
-})(jQuery);
-
-var BaiduSearch;
-
-(function($) {
-  'use strict';
-
-  /**
-   * TODO
-   * Search by Baidu Search API
-   * @param options : (object)
-   */
-  BaiduSearch = function(options) {
-    SearchService.apply(this, arguments);
-    var self = this;
-    var endpoint = "";
-    self.addLogo('baidu');
-
-    /**
-     * Generate result list html
-     * @param data : (array) result items
-     */
-    self.buildResultList = function(data, queryText) {
-      var results = [],
-          html = "";
-      $.each(data, function(index, post) {
-        if (self.contentSearch(post, queryText))
-          html += self.buildResult(post.linkUrl, post.title, post.abstract);
-      });
-      return html;
-    };
-    
-    /**
-     * Generate metadata after a successful query
-     * @param data : (object) the raw google custom search response data
-     */
-    self.buildMetadata = function(data) {
-
-    };
-
-    self.loadScript = function() {
-      self.dom.input.each(function(index,elem) {
-        $(elem).attr('disabled', true);
-      });
-      var script = "<script src='http://zhannei.baidu.com/api/customsearch/apiaccept?sid=" +self.config.apiId+ "&v=2.0&callback=customSearch.initBaidu' type='text/javascript' charset='utf-8'></script>";
-      self.dom.body.append(script);
-    };
-
-    self.initBaidu = function() {
-      self.cse = new BCse.Search(self.config.apiId);
-      self.dom.input.each(function(index,elem) {
-        $(elem).attr('disabled', false);
-      });
-    };
-
-    /**
-     * Get search results
-     * @param queryText {String}
-     * @param page {Integer}
-     * @param callback {Function}
-     */
-    self.query = function(queryText, page, callback) {
-      self.cse.setPageNum(self.config.per_page);
-      self.cse.getResult(queryText, function(data) {
-        console.log(data);
-        self.buildResultList(data, queryText);
-        self.cse.getSearchInfo(queryText, function(data) {
-          console.log(data);
-        });
-        if (callback instanceof Function) {
-          callback();
-        }
-      }, page);
-    };
-
-    self.loadScript();
-    
-  };
-
-})(jQuery);
\ No newline at end of file
diff --git a/page/2/index.html b/page/2/index.html
deleted file mode 100644
index 51ecc43..0000000
--- a/page/2/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/2/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/15/Snappy/">
-		<h3 class="post-title">Snappy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-15T09:00:01.000Z" itemprop="datePublished">
-	      615.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/14/TimingWheel/">
-		<h3 class="post-title">Timing Wheel</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-14T01:20:25.000Z" itemprop="datePublished">
-	      614.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/13/Ligatures/">
-		<h3 class="post-title">Ligatures</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-13T05:20:38.000Z" itemprop="datePublished">
-	      613.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/12/Calculate24/">
-		<h3 class="post-title">Calculate 24</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-12T06:53:49.000Z" itemprop="datePublished">
-	      612.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/11/ChatChatChat/">
-		<h3 class="post-title">Chat Chat Chat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-11T07:09:34.000Z" itemprop="datePublished">
-	      611.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/06/bitcoin/">
-		<h3 class="post-title">bitcoin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-06T14:19:02.000Z" itemprop="datePublished">
-	      66.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/05/MagicNumber/">
-		<h3 class="post-title">Magic Number</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-05T08:27:07.000Z" itemprop="datePublished">
-	      65.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/03/Raft/">
-		<h3 class="post-title">Raft</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-03T12:59:23.000Z" itemprop="datePublished">
-	      63.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/02/ReplicatedServiceClient/">
-		<h3 class="post-title">Replicated Service Client</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-02T07:01:00.000Z" itemprop="datePublished">
-	      62.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/06/01/Semaphore/">
-		<h3 class="post-title">Semaphore</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-06-01T13:07:44.000Z" itemprop="datePublished">
-	      61.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/">Prev</a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><a class="page-number" href="/page/4/">4</a><span class="space">&hellip;</span><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/3/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/page/3/index.html b/page/3/index.html
deleted file mode 100644
index 2b3387f..0000000
--- a/page/3/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/3/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/31/MemoryMappedFile/">
-		<h3 class="post-title">Memory Mapped File</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-31T11:05:38.000Z" itemprop="datePublished">
-	      531.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/29/ProtocolMultiplexer/">
-		<h3 class="post-title">Protocol Multiplexer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-29T11:50:23.000Z" itemprop="datePublished">
-	      529.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/28/Shredder-Gluer/">
-		<h3 class="post-title">Shredder &amp; Gluer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-28T03:38:22.000Z" itemprop="datePublished">
-	      528.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/27/TUNTAP/">
-		<h3 class="post-title">TUN/TAP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-27T06:05:03.000Z" itemprop="datePublished">
-	      527.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/26/TryLock/">
-		<h3 class="post-title">Try Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-26T14:05:27.000Z" itemprop="datePublished">
-	      526.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/25/ConcurrentPrimeSieve/">
-		<h3 class="post-title">Concurrent Prime Sieve</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-25T06:36:04.000Z" itemprop="datePublished">
-	      525.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/SingleFlight/">
-		<h3 class="post-title">Single Flight</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-24T05:46:36.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/24/LRU/">
-		<h3 class="post-title">LRU</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T16:23:40.000Z" itemprop="datePublished">
-	      524.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/23/Heartbeat/">
-		<h3 class="post-title">Heartbeat</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-23T09:52:18.000Z" itemprop="datePublished">
-	      523.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/BitwiseOperation/">
-		<h3 class="post-title">Bitwise Operation</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T11:28:38.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/page/2/">Prev</a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/page/4/">4</a><a class="page-number" href="/page/5/">5</a><span class="space">&hellip;</span><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/4/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/page/4/index.html b/page/4/index.html
deleted file mode 100644
index f1ad989..0000000
--- a/page/4/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/4/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/22/GUID/">
-		<h3 class="post-title">GUID</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-22T03:49:08.000Z" itemprop="datePublished">
-	      522.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/21/mpg123/">
-		<h3 class="post-title">mpg123</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-21T11:12:06.000Z" itemprop="datePublished">
-	      521.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/20/Future/">
-		<h3 class="post-title">Future</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-20T06:04:59.000Z" itemprop="datePublished">
-	      520.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/19/ADB/">
-		<h3 class="post-title">ADB</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-19T07:38:54.000Z" itemprop="datePublished">
-	      519.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/15/ConnectionLimiter/">
-		<h3 class="post-title">Connection Limiter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-15T02:18:24.000Z" itemprop="datePublished">
-	      515.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/14/TerminalUI/">
-		<h3 class="post-title">Terminal UI</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-14T14:49:04.000Z" itemprop="datePublished">
-	      514.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/13/JobDispatcher/">
-		<h3 class="post-title">Job Dispatcher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-13T13:34:24.000Z" itemprop="datePublished">
-	      513.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/ReverseProxy/">
-		<h3 class="post-title">Reverse Proxy</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T13:30:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/12/AdvisoryLock/">
-		<h3 class="post-title">Advisory Lock</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-12T05:26:04.000Z" itemprop="datePublished">
-	      512.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/TokenBucket/">
-		<h3 class="post-title">Token Bucket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T14:05:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/page/3/">Prev</a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/page/5/">5</a><a class="page-number" href="/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/5/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/page/5/index.html b/page/5/index.html
deleted file mode 100644
index 12a12b2..0000000
--- a/page/5/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/5/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/11/StreamCipher/">
-		<h3 class="post-title">Stream Cipher</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-11T05:10:04.000Z" itemprop="datePublished">
-	      511.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/10/ConnectionPool/">
-		<h3 class="post-title">Connection Pool</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-10T03:40:24.000Z" itemprop="datePublished">
-	      510.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/MorseCode/">
-		<h3 class="post-title">Morse Code</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T09:07:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/09/CircuitBreaker/">
-		<h3 class="post-title">Circuit Breaker</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-09T01:17:24.000Z" itemprop="datePublished">
-	      59.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/ColorfulPrinting/">
-		<h3 class="post-title">Colorful Printing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T11:48:24.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/08/SmoothWeightedRoundRobin/">
-		<h3 class="post-title">Weighted Round Robin</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-08T02:29:04.000Z" itemprop="datePublished">
-	      58.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/07/MagnetLink/">
-		<h3 class="post-title">Magnet Link</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-07T07:15:24.000Z" itemprop="datePublished">
-	      57.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/06/PubSub/">
-		<h3 class="post-title">PubSub</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-06T11:08:04.000Z" itemprop="datePublished">
-	      56.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/WebSocket/">
-		<h3 class="post-title">WebSocket</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:52:04.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/dep/">
-		<h3 class="post-title">dep</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:47:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/page/4/">Prev</a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/3/">3</a><a class="page-number" href="/page/4/">4</a><span class="page-number current">5</span><a class="page-number" href="/page/6/">6</a><a class="page-number" href="/page/7/">7</a><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/6/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/page/6/index.html b/page/6/index.html
deleted file mode 100644
index 6108a02..0000000
--- a/page/6/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/6/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/05/Crawler/">
-		<h3 class="post-title">Crawler</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-05T02:05:24.000Z" itemprop="datePublished">
-	      55.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/04/Docker/">
-		<h3 class="post-title">Docker &amp; Golang</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-04T09:01:24.000Z" itemprop="datePublished">
-	      54.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/Screenshot/">
-		<h3 class="post-title">Screenshot</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T12:29:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/LoadBalancing/">
-		<h3 class="post-title">Load Balancing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T10:12:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/DecodingDubboProtocol/">
-		<h3 class="post-title">Dubbo Protocol</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T07:58:24.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/02/TLS/">
-		<h3 class="post-title">TLS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-02T04:40:04.000Z" itemprop="datePublished">
-	      52.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/iobridge/">
-		<h3 class="post-title">iobridge</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T13:13:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/etcd/">
-		<h3 class="post-title">etcd</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T04:28:24.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/05/01/Port_0/">
-		<h3 class="post-title">port 0, WTF?</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-05-01T03:11:11.000Z" itemprop="datePublished">
-	      51.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/ConsistentHashing/">
-		<h3 class="post-title">Connection Hashing</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T10:59:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/page/5/">Prev</a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/4/">4</a><a class="page-number" href="/page/5/">5</a><span class="page-number current">6</span><a class="page-number" href="/page/7/">7</a><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/7/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/page/7/index.html b/page/7/index.html
deleted file mode 100644
index 52cdd92..0000000
--- a/page/7/index.html
+++ /dev/null
@@ -1,352 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/7/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/30/Crontab/">
-		<h3 class="post-title">crontab</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-30T05:58:24.000Z" itemprop="datePublished">
-	      430.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/TCP_IP/">
-		<h3 class="post-title">TCP/IP</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-29T11:56:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/29/BloomFilter/">
-		<h3 class="post-title">Bloom Filter</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-28T16:00:04.000Z" itemprop="datePublished">
-	      429.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/EventTimer/">
-		<h3 class="post-title">Event Timer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T06:47:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/27/MerkleTree/">
-		<h3 class="post-title">Merkle Tree</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-27T04:18:24.000Z" itemprop="datePublished">
-	      427.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/FactoryPattern/">
-		<h3 class="post-title">Factory Pattern</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T15:27:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/LeakyBuffer/">
-		<h3 class="post-title">Leaky Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T06:21:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/26/EventProcessEngine/">
-		<h3 class="post-title">Event Process Engine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-26T01:43:24.000Z" itemprop="datePublished">
-	      426.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Fanin/">
-		<h3 class="post-title">Fan-in</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T12:35:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/gRPC/">
-		<h3 class="post-title">gRPC</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:27:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/page/6/">Prev</a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/5/">5</a><a class="page-number" href="/page/6/">6</a><span class="page-number current">7</span><a class="page-number" href="/page/8/">8</a><a class="extend next" rel="next" href="/page/8/">Next</a>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/page/8/index.html b/page/8/index.html
deleted file mode 100644
index c638e12..0000000
--- a/page/8/index.html
+++ /dev/null
@@ -1,340 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-  <meta charset="utf-8">
-  
-  <title>Whyyy</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-  <meta name="description" content="Pieces of Valuable Programming Knowledges">
-<meta name="keywords" content="programming,hack,golang">
-<meta property="og:type" content="website">
-<meta property="og:title" content="Whyyy">
-<meta property="og:url" content="https://oceanoverflow.github.io/page/8/index.html">
-<meta property="og:site_name" content="Whyyy">
-<meta property="og:description" content="Pieces of Valuable Programming Knowledges">
-<meta property="og:locale" content="default">
-<meta name="twitter:card" content="summary">
-<meta name="twitter:title" content="Whyyy">
-<meta name="twitter:description" content="Pieces of Valuable Programming Knowledges">
-  
-  
-    <link rel="icon" href="/favicon.png">
-  
-  
-	<!-- If needed, replace your own web font service -->
-  <link href="https://fonts.googleapis.com/css?family=Lato:400,400i,700" rel="stylesheet">
-
-  <link rel="stylesheet" href="/icomoon/style.css">
-  <link rel="stylesheet" href="/style.css">
-
-</head>
-
-<body>
-  <div class="site-wrapper">
-    <div id="loading-bar-wrapper">
-  <div id="loading-bar"></div>
-</div>
-<script>document.getElementById("loading-bar").style.width="20%";</script>
-
-
-<header id="header" class="site-header clearfix">
-
-  <a class="logo square clearfix" href="/">
-    <!-- 
-      Replace with your own size name, for example:
-      <span class="b">A</span>
-      <span class="w">B</span>
-      <span class="b">C</span>
-     -->
-    
-      <span class="b">
-        W
-      </span>
-    
-      <span class="b">
-        h
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-      <span class="w">
-        y
-      </span>
-    
-      <span class="b">
-        y
-      </span>
-    
-  </a>
-  <a class="me square site-nav-switch clearfix">
-    <span class="b">
-    	<span class="icon icon-menu"></span>
-    </span>
-  </a>
-
-</header>
-
-    <script>document.getElementById("loading-bar").style.width="40%";</script>
-    <main id="main" class="clearfix">
-      <div class="page-header">
-	
-
-</div>
-
-<ul class="post-list clearfix">
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/Protobuf/">
-		<h3 class="post-title">Protocol Buffer</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T08:03:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/25/FSM/">
-		<h3 class="post-title">Finite State Machine</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-25T01:58:24.000Z" itemprop="datePublished">
-	      425.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/24/PKCS7_Padding/">
-		<h3 class="post-title">PKCS7 Padding</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-24T08:26:24.000Z" itemprop="datePublished">
-	      424.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/23/RSS/">
-		<h3 class="post-title">RSS</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-23T13:50:37.000Z" itemprop="datePublished">
-	      423.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/04/22/heap/">
-		<h3 class="post-title">heap</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-04-22T09:44:48.000Z" itemprop="datePublished">
-	      422.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2018/02/05/CryptoBasic/">
-		<h3 class="post-title">Cryptography Basics</h3>
-	  <div class="post-meta">
-	    <time datetime="2018-02-05T14:39:55.000Z" itemprop="datePublished">
-	      25.18
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/12/07/openssl/">
-		<h3 class="post-title">openssl</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-12-07T05:17:05.000Z" itemprop="datePublished">
-	      127.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/02/LinuxManiac/">
-		<h3 class="post-title">Linux Maniac</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-02T13:24:46.000Z" itemprop="datePublished">
-	      92.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-    <li class="post-item grid-item">
-	<a class="post-link" href="/2017/09/01/TODO/">
-		<h3 class="post-title">TODO</h3>
-	  <div class="post-meta">
-	    <time datetime="2017-09-01T13:20:48.000Z" itemprop="datePublished">
-	      91.17
-	    </time>
-	  </div>
-  </a>
-</li>
-
-  
-</ul>
-
-
-  <nav id="page-nav">
-    <a class="extend prev" rel="prev" href="/page/7/">Prev</a><a class="page-number" href="/">1</a><span class="space">&hellip;</span><a class="page-number" href="/page/6/">6</a><a class="page-number" href="/page/7/">7</a><span class="page-number current">8</span>
-  </nav>
-
-
-
-
-      <script>document.getElementById("loading-bar").style.width="60%";</script>
-    </main>
-    
-<footer id="footer" class="clearfix">
-	
-  <div>&copy; <a href="https://oceanoverflow.github.io">Whyyy</a> Theme by <a href="http://artifact.me/" target="_blank">Art Chen</a>.</div>
-  <div>Powered by <a href="https://hexo.io/" rel="external">Hexo</a>.</div>
-</footer>
-
-
-    <script>document.getElementById("loading-bar").style.width="80%";</script>
-    <div class="overlay"></div>
-  </div>
-  <div class="site-sidebar">
-
-	
-	
-	<div class="sidebar-switch clearfix "
-		style="display: none">
-		<a class="dark-btn active" data-toggle="toc">
-	    <span class="icon icon-list"></span>
-	    <span class="text">Index</span>
-	  </a>
-	  <a class="dark-btn" data-toggle="bio">
-	    <span class="icon icon-person"></span>
-	    <span class="text">Bio</span>
-	  </a>
-	</div>
-
-	<div class="site-toc "
-		style="display: none">
-		
-	    <div class="no-index">No Index</div>
-	  
-  </div>
-  
-	<div class="site-bio show"
-		style="display: block">
-		
-	  <!-- About Me -->
-	  <div class="about-me clearfix">
-	    <div class="avatar">
-	      <img src="/img/avatar.png" />
-	    </div>
-	    <div class="info">
-	      <a class="name dark-btn" href="/about">
-	        Yangyi, Yi
-	      </a>
-	    </div>
-	    <div class="info">
-	      <span class="item desc">
-	        Pieces of Valuable Programming Knowledges
-	      </span>
-	    </div>
-	  </div>
-	
-	  <!-- Social Icons -->
-	  <div class="social clearfix">
-	    
-	      
-	        <a href="/atom.xml" class="feed"
-	          target="_blank" rel="external">
-	          <span class="icon icon-feed"></span>
-	        </a>
-	      
-	        <a href="https://github.com/oceanoverflow" class="github"
-	          target="_blank" rel="external">
-	          <span class="icon icon-github"></span>
-	        </a>
-	      
-	    
-	  </div>
-	
-	  <!-- Home & Bottom -->
-	  <div class="shortcuts clearfix">
-	    <div class="bk">
-	      <a href="#header" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-up"></span>
-	        <span class="text">Back to Top</span>
-	      </a>
-	    </div>
-	    <div class="bk">
-	      <a href="#footer" class="dark-btn window-nav">
-	        <span class="icon icon-chevron-thin-down"></span>
-	        <span class="text">Go to Bottom</span>
-	      </a>
-	    </div>
-	  </div>
-
-	</div>
-
-</div>
-
-  <!-- Universal Search -->
-
-<script type="text/javascript">
-	var GOOGLE_CUSTOM_SEARCH_API_KEY = "";
-	var GOOGLE_CUSTOM_SEARCH_ENGINE_ID = "";
-	var ALGOLIA_API_KEY = "";
-	var ALGOLIA_APP_ID = "";
-	var ALGOLIA_INDEX_NAME = "";
-  var AZURE_SERVICE_NAME = "";
-  var AZURE_INDEX_NAME = "";
-  var AZURE_QUERY_KEY = "";
-  var BAIDU_API_ID = "";
-  var SEARCH_SERVICE = "hexo";
-</script>
-
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
-<script>window.jQuery || document.write('<script src="/js/jquery.js"><\/script>')</script>
-
-<script src="/js/search.js"></script>
-<script src="/js/app.js"></script>
-
-<!-- Disqus -->
-
-
-
-<!-- Swiftype -->
-<!-- Please replace with your own swiftype settings -->
-<!--
-<script type="text/javascript">
-  /* Swiftype */
-  (function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
-  (w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
-  e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
-  })(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');
-
-  _st('install','FHMeAyBdVccJECstf-XJ','2.0.0');
-</script>
--->
-
-  <script>document.getElementById("loading-bar").style.width="100%";</script>
-</body>
-</html>
diff --git a/style.css b/style.css
deleted file mode 100644
index 4086d7f..0000000
--- a/style.css
+++ /dev/null
@@ -1 +0,0 @@
-@charset "utf-8";/*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{-ms-box-sizing:border-box;box-sizing:border-box;outline:none;margin:0;padding:0}html{height:100%;max-height:100%;font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{height:100%;max-height:100%;font-family:"Lato",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3",Microsoft JhengHei,WenQuanYi Micro Hei,"Microsoft YaHei",sans-serif;font-size:1.8rem;line-height:1.5em;color:#414141;-webkit-font-feature-settings:'kern' 1;-moz-font-feature-settings:'kern' 1;-o-font-feature-settings:'kern' 1;text-rendering:geometricPrecision}::-moz-selection{background:#D6EDFF}::selection{background:#D6EDFF}h1,h2,h3,h4,h5,h6{-webkit-font-feature-settings:'dlig' 1,'liga' 1,'lnum' 1,'kern' 1;-moz-font-feature-settings:'dlig' 1,'liga' 1,'lnum' 1,'kern' 1;-o-font-feature-settings:'dlig' 1,'liga' 1,'lnum' 1,'kern' 1;text-rendering:geometricPrecision;margin:0 0 .4em 0}h1{font-size:1.8em}h2{font-size:1.6em}h3{font-size:1.4em}h4{font-size:1.2em}h5{font-size:1em}h6{font-size:1em}a{color:#414141;text-decoration:none;transition:all .24s ease}a:hover{text-decoration:none}pre{tab-size:2;-moz-tab-size:2;-o-tab-size:2;-webkit-tab-size:2}::-webkit-input-placeholder{color:#b5b5b5;font-weight:300}:-moz-placeholder{color:#b5b5b5;font-weight:300}::-moz-placeholder{color:#b5b5b5;font-weight:300}:-ms-input-placeholder{color:#b5b5b5;font-weight:300}.clearfix{zoom:1}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.hidden{text-indent:-9999px;visibility:hidden;display:none}.inner{position:relative;width:80%;max-width:710px;margin:0 auto}.vertical{display:table-cell;vertical-align:middle}.right{float:right}.left{float:left}body.bio-open .site-sidebar{transform:translate3d(0, 0, 0)}body.bio-open .site-wrapper{transform:translate3d(-280px, 0, 0)}body.bio-open .site-wrapper .overlay{opacity:1;visibility:visible}.site-wrapper{position:relative;min-height:100%;overflow:hidden;transition:all .24s ease;z-index:10}.site-wrapper .overlay{position:absolute;top:0;left:0;width:100%;height:100%;content:"";opacity:0;background-color:rgba(255,255,255,0.5);transition:all .24s ease;visibility:hidden;z-index:9999}.dark-btn{display:inline-block;background:rgba(0,0,0,0.3);border:1px solid black;padding:0 15px;font-size:13px;font-family:"Lato",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3",Microsoft JhengHei,WenQuanYi Micro Hei,"Microsoft YaHei",sans-serif;text-align:center;color:#c2c2c2}.dark-btn:hover{color:#f5f5f5;background-color:#009688}.dark-btn .icon{margin-right:5px;font-size:16px;vertical-align:middle;line-height:44px}.dark-btn .text{vertical-align:middle;line-height:44px}#loading-bar-wrapper{position:fixed;width:100%;top:0;left:0;overflow:visible;z-index:999}#loading-bar{position:relative;width:0;height:2px;background-color:rgba(255,156,10,0.8);transition:all .5s ease}.tomorrow-comment,pre .comment,pre .title{color:#8e908c}.tomorrow-red,pre .variable,pre .attribute,pre .tag,pre .regexp,pre .ruby .constant,pre .xml .tag .title,pre .xml .pi,pre .xml .doctype,pre .html .doctype,pre .css .id,pre .css .class,pre .css .pseudo{color:#c82829}.tomorrow-orange,pre .number,pre .preprocessor,pre .built_in,pre .literal,pre .params,pre .constant{color:#f5871f}.tomorrow-yellow,pre .class,pre .ruby .class .title,pre .css .rules .attribute{color:#eab700}.tomorrow-green,pre .string,pre .value,pre .inheritance,pre .header,pre .ruby .symbol,pre .xml .cdata{color:#718c00}.tomorrow-aqua,pre .css .hexcolor{color:#3e999f}.tomorrow-blue,pre .function,pre .python .decorator,pre .python .title,pre .ruby .function .title,pre .ruby .title .keyword,pre .perl .sub,pre .javascript .title,pre .coffeescript .title{color:#4271ae}.tomorrow-purple,pre .keyword,pre .javascript .function{color:#8959a8}pre code{display:block;background:white;color:#4d4d4c;line-height:1.5;border:1px solid #ccc;padding:10px}.site-header{position:relative;width:100%;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;padding:20px}.site-header .square{position:relative;display:block;font-weight:normal;text-transform:uppercase;cursor:pointer;overflow:hidden}.site-header .square.logo{float:left}.site-header .square.me{position:fixed;top:20px;right:20px;visibility:visible;opacity:1;transition:all .24s;z-index:65535}.site-header .square.me.active{opacity:0;visibility:hidden}.site-header .square span{display:block;float:left;width:30px;height:30px;line-height:30px;text-align:center;transition:all .24s}.site-header .square span.b{background:#414141;color:white}.site-header .square span.b:hover{background:black}.site-header .square span.w{background:transparent;color:#414141}.site-header .square span.w:hover{background:white}#main{position:relative;width:100%;padding:20px 0}#main .page-header{text-align:center;margin-bottom:20px;color:#8e8e8e;font-size:15px}.post-list{position:relative;list-style:none;margin:0 auto;width:1280px;opacity:0;transition:opacity .4s}@media (max-width:1300px){.post-list{width:960px}}@media (max-width:960px){.post-list{width:640px}}@media (max-width:640px){.post-list{width:100%;padding:0 20px}}.post-list.show{opacity:1}.post-list>li{position:relative;float:left;width:300px;height:300px;margin:0 10px 20px 10px}@media (max-width:640px){.post-list>li{width:100%;margin:0 0 20px 0}}.post-list>li .post-link{position:relative;display:block;width:100%;height:100%;border:3px solid #414141;padding:20px}.post-list>li .post-link:hover{border-color:#ff9800}.post-list>li .post-link:hover .post-title{color:#ff9800}.post-list>li .post-link:hover .post-meta{background:#ff9800}.post-list>li .post-title{position:absolute;bottom:15px;right:20px;padding-left:50px;text-align:right;font-size:20px;font-weight:500;transition:all .24s}.post-list>li .post-meta{position:absolute;top:0;left:0;background:#414141;padding:2px 14px 2px 10px;font-family:"Lato",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3",Microsoft JhengHei,WenQuanYi Micro Hei,"Microsoft YaHei",sans-serif;font-size:14px;font-weight:700;color:white;transition:all .24s}.article{position:relative;width:100%;max-width:700px;margin:0 auto;margin-bottom:20px}@media (max-width:768px){.article{padding:20px}}.article .article-header{padding:20px 0 40px 0}@media (max-width:768px){.article .article-header{padding:0 0 40px 0}}.article .article-header h1{font-size:2em;line-height:1.2;margin-bottom:0}@media (max-width:768px){.article .article-header h1{font-size:1.5em}}.article .article-meta{font-size:14px;color:#9b9b9b;padding-left:1px}.article-entry,.post-excerpt{position:relative;font-family:"Lato",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3",Microsoft JhengHei,WenQuanYi Micro Hei,"Microsoft YaHei",sans-serif;font-size:16px;color:#393a3a;padding-bottom:30px}.article-entry a,.post-excerpt a{color:#f59200}.article-entry a:hover,.post-excerpt a:hover{color:#f08f00;background:rgba(255,152,0,0.1)}.article-entry a:active,.post-excerpt a:active{background:rgba(255,152,0,0.2);color:#ffffff}.article-entry h1,.post-excerpt h1,.article-entry h2,.post-excerpt h2,.article-entry h3,.post-excerpt h3,.article-entry h4,.post-excerpt h4,.article-entry h5,.post-excerpt h5,.article-entry h6,.post-excerpt h6{position:relative;font-family:"Lato",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3",Microsoft JhengHei,WenQuanYi Micro Hei,"Microsoft YaHei",sans-serif;font-weight:bold;margin:40px auto 30px auto}@media (max-width:768px){.article-entry h1,.post-excerpt h1,.article-entry h2,.post-excerpt h2,.article-entry h3,.post-excerpt h3,.article-entry h4,.post-excerpt h4,.article-entry h5,.post-excerpt h5,.article-entry h6,.post-excerpt h6{left:15px}}.article-entry h1::before,.post-excerpt h1::before,.article-entry h2::before,.post-excerpt h2::before,.article-entry h3::before,.post-excerpt h3::before,.article-entry h4::before,.post-excerpt h4::before,.article-entry h5::before,.post-excerpt h5::before,.article-entry h6::before,.post-excerpt h6::before{position:absolute;left:-20px;top:0;content:"#";color:#4caf50;font-weight:normal}.article-entry p,.post-excerpt p{margin-bottom:20px;line-height:1.75em}.article-entry figure,.post-excerpt figure{width:100%;font-size:13px;margin:20px 0;padding:10px 15px;background:#F9F9F9;overflow:auto}.article-entry figure td.gutter,.post-excerpt figure td.gutter{padding-right:10px;color:#969696;font-size:12px;border-right:1px solid #ececec}.article-entry figure td.code,.post-excerpt figure td.code{padding-left:10px}.article-entry ul,.post-excerpt ul,.article-entry ol,.post-excerpt ol{margin:20px 0 20px 0;padding-left:30px;list-style:circle}.article-entry img,.post-excerpt img{display:block;border:none;max-width:100%;height:auto}.article-entry blockquote,.post-excerpt blockquote{position:relative;width:100%;margin:20px 0;padding:0 20px;border-left:4px solid #4caf50}.article-entry pre,.post-excerpt pre{white-space:pre}.article-entry pre code,.post-excerpt pre code{color:#414141;padding:0 0 0 30px;margin:0;font-size:1em;background:transparent;border:0;white-space:inherit}.article-entry pre figure,.post-excerpt pre figure{margin:0}.article-entry code,.post-excerpt code{color:#008c7f;padding:3px 5px;margin:0 2px;border-radius:2px;white-space:nowrap;font-size:.8em;background:#F9F9F9}@media (max-width:768px){.article-entry,.post-excerpt{font-size:16px}.article-entry h1,.post-excerpt h1,.article-entry h2,.post-excerpt h2,.article-entry h3,.post-excerpt h3{margin:30px 0}.article-entry h4,.post-excerpt h4,.article-entry h5,.post-excerpt h5,.article-entry h6,.post-excerpt h6{margin:20px 0}.article-entry h1,.post-excerpt h1{font-size:1.5em}.article-entry h2,.post-excerpt h2{font-size:1.4em}.article-entry h3,.post-excerpt h3{font-size:1.3em}.article-entry h4,.post-excerpt h4{font-size:1.2em}.article-entry h5,.post-excerpt h5{font-size:1.1em}.article-entry h6,.post-excerpt h6{font-size:1em}.article-entry figure,.post-excerpt figure{font-size:13px;line-height:1.6em}}.article-tags{margin-bottom:30px}.article-tags .tag-link{position:relative;padding:4px 10px 4px 20px;margin-right:5px;font-size:14px;background:#F9F9F9;border-radius:2px}.article-tags .tag-link:hover{background:#414141;color:white}.article-tags .tag-link::before{position:absolute;top:0;left:7px;content:"#"}#comments{position:relative;padding:30px 0}.site-sidebar{position:fixed;top:0;right:0;width:280px;height:100%;padding:20px;background-image:url(/img/sidebar-bg.png);background-repeat:repeat;background-size:102px 102px;text-align:center;overflow:hidden;transform:translate3d(280px, 0, 0);transition:all .24s ease;z-index:1}.site-sidebar .sidebar-switch{width:200px;margin:0 auto 20px auto;opacity:0;visibility:hidden;transition:all .24s ease}.site-sidebar .sidebar-switch.show{opacity:1;visibility:visible}.site-sidebar .sidebar-switch .dark-btn{display:block;float:left;width:100px;margin-left:-1px;cursor:pointer}.site-sidebar .sidebar-switch .dark-btn.active{color:#f5f5f5;background-color:#009688}.site-sidebar .sidebar-switch .dark-btn .icon{line-height:30px}.site-sidebar .sidebar-switch .dark-btn .text{line-height:30px}.site-bio{position:relative;opacity:0;transform:translate3d(0, -20px, 0);transition:all .24s ease}.site-bio.show{opacity:1;transform:translate3d(0, 0, 0)}.site-bio .window-nav{width:125px;padding:0 0 0 15px;text-align:left}.site-bio .shortcuts{padding:0 5px}.site-bio .shortcuts .bk{margin-bottom:5px}.site-bio .about-me{padding:12px 5px 15px 5px;background:rgba(0,0,0,0.1);border:1px solid #262626;transition:background .24s,border-color .24s}.site-bio .about-me:hover{background:rgba(0,0,0,0.2);border-color:#1a1a1a}.site-bio .about-me .avatar{display:block;width:96px;height:96px;margin:4px auto;background:rgba(0,0,0,0.3);border-radius:50%;border:1px solid black;padding:3px;overflow:hidden}.site-bio .about-me .avatar img{display:block;width:100%;height:100%;border-radius:50%}.site-bio .about-me .dark-btn{padding:5px 15px}.site-bio .about-me .dark-btn:hover{background-color:#009688}.site-bio .about-me .dark-btn .icon{margin-right:0}.site-bio .about-me .info{color:#a9a9a9;margin-top:10px;line-height:140%;padding:0 15px;font-size:13px}.site-bio .social{position:relative;margin:15px 0;padding:0}.site-bio .social a{display:inline-block;color:#ffffff;font-size:14px;text-transform:uppercase;text-align:center;line-height:46px;vertical-align:middle;width:46px;height:46px;background-color:rgba(0,0,0,0.3);border:1px solid black;margin:5px 2px}.site-bio .social a.feed:hover{background-color:#ff9800}.site-bio .social a.github:hover{background-color:#467cc2}.site-bio .social a.twitter:hover{background-color:#55acee}.site-bio .social a.facebook:hover{background-color:#3765a3}.site-bio .social a.google:hover{background-color:#db4437}.site-bio .social a.dribbble:hover{background-color:#ed699c}.site-bio .social a.pinterest:hover{background-color:#bc1725}.site-bio .social a.weibo:hover{background-color:#f8712a}.site-bio .social a.tumblr:hover{background-color:#35465c}.site-bio .social a.instagram:hover{background-color:#3f729b}.site-bio .social a.linkedin:hover{background-color:#0077B5}.site-bio .social a.behance:hover{background-color:#1769FF}.site-bio .social a:hover{background:#009688}.site-bio .social a:hover .icon{color:rgba(245,245,245,0.7)}.site-bio .social a .avatar,.site-bio .social a .icon{transition:all .24s}.site-bio .social a .avatar{display:block;width:30px;height:30px;margin:7px;border-radius:50%}.site-bio .social a .icon{font-size:18px;color:#a9a9a9;line-height:46px}.site-toc{position:relative;padding:12px 10px 15px 10px;background:rgba(0,0,0,0.1);border:1px solid #262626;max-height:450px;overflow:auto;opacity:0;transform:translate3d(0, -20px, 0);transition:all .24s ease}.site-toc.show{transform:translate3d(0, 0, 0);opacity:1}.site-toc>ol{text-align:left;list-style:none}.site-toc>ol li a{color:#e6e6e6;font-size:15px}.site-toc>ol li a:hover{color:#009688}.site-toc>ol li ol{list-style:none;padding-left:15px}#u-search{display:none;position:fixed;top:0;left:0;width:100%;height:100%;padding:60px 20px;z-index:999999}@media (max-width:680px){#u-search{padding:0}}#u-search .modal{position:fixed;height:80%;width:100%;max-width:640px;left:50%;top:0;margin:64px 0 0 -320px;background:#fff;box-shadow:0 7px 8px -4px rgba(0,0,0,0.2),0 13px 19px 2px rgba(0,0,0,0.14),0 5px 24px 4px rgba(0,0,0,0.12);z-index:3}@media (max-width:680px){#u-search .modal{box-shadow:none;max-width:none;top:0;left:0;margin:0;height:100%}}#u-search .modal .modal-ajax-content{opacity:0;visibility:hidden;transition:all .36s}#u-search .modal .modal-ajax-content.loaded{opacity:1;visibility:visible}#u-search .modal .modal-header{position:relative;width:100%;height:50px;background-color:#33475A;z-index:3}#u-search .modal .modal-header .btn-close{display:block;position:absolute;width:50px;height:50px;top:0;right:0;color:white;cursor:pointer;text-align:center;line-height:50px;vertical-align:middle;font-size:18px;transition:all .24s;z-index:2}#u-search .modal .modal-header .btn-close:hover{transform:rotate(90deg)}#u-search .modal .modal-header .modal-loading{position:absolute;bottom:-2px;left:0;width:100%;height:2px;background:transparent;z-index:1}#u-search .modal .modal-header .modal-loading .modal-loading-bar{display:block;position:relative;width:0;height:100%;background:#ffb74d;transition:width .24s}#u-search .modal .modal-header #u-search-modal-form{position:relative;width:100%;height:100%;z-index:2}#u-search .modal .modal-header #u-search-modal-form #u-search-modal-input{width:100%;padding:0 50px 0 40px;font-size:15px;line-height:50px;vertical-align:middle;color:#fff;border:none;background:transparent;transition:background-color .24s;font-weight:thin;-webkit-appearance:none;-moz-appearance:none;appearance:none;box-shadow:none}#u-search .modal .modal-header #u-search-modal-form #u-search-modal-input:focus{background-color:#3c546a}#u-search .modal .modal-header #u-search-modal-btn-submit{position:absolute;top:0;left:0;padding-left:5px;padding-top:2px;background:transparent;border:none;width:40px;height:50px;vertical-align:middle;font-size:20px;color:white;z-index:2}#u-search .modal .modal-footer{position:absolute;bottom:0;left:0;width:100%;height:50px;padding:0 15px;background:#fff;border-top:1px solid #dadada}#u-search .modal .modal-footer .logo{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;z-index:0}#u-search .modal .modal-footer .logo a{display:inline-block}#u-search .modal .modal-footer .logo.google img{height:24px;margin-top:13px}#u-search .modal .modal-footer .logo.baidu img{height:22px;margin-top:14px}#u-search .modal .modal-footer .logo img{position:relative;display:inline-block;width:auto;height:18px;margin-top:16px}#u-search .modal .modal-footer .modal-error{position:relative;float:left;vertical-align:middle;line-height:50px;font-size:13px;z-index:1}#u-search .modal .modal-footer .modal-metadata{position:relative;float:left;vertical-align:middle;line-height:50px;font-size:13px;z-index:1}#u-search .modal .modal-footer .nav{position:relative;display:block;float:right;vertical-align:middle;font-size:13px;font-weight:500;line-height:50px;color:#828282;cursor:pointer;z-index:1}#u-search .modal .modal-footer .nav:hover{color:#414141}#u-search .modal .modal-footer .nav.btn-next{margin-left:10px}#u-search .modal .modal-footer .nav .icon{font-size:12px}#u-search .modal .modal-body{position:absolute;padding:64px 40px 80px 40px;width:100%;height:100%;top:0;left:0;overflow-y:scroll;-webkit-overflow-scrolling:touch}@media (max-width:680px){#u-search .modal .modal-body{padding:60px 20px 80px 20px}}#u-search .modal .modal-body .modal-results{list-style:none}#u-search .modal .modal-body .modal-results li{border-bottom:1px solid #e6e8ea}#u-search .modal .modal-body .modal-results li:last-child{border-bottom:none}#u-search .modal .modal-body .modal-results .result{position:relative;display:block;padding:15px 30px 15px 0;text-decoration:none}#u-search .modal .modal-body .modal-results .result:hover .digest,#u-search .modal .modal-body .modal-results .result:hover .icon{color:#414141}#u-search .modal .modal-body .modal-results .result .title{display:inline-block;max-width:100%;color:#2196f3;font-size:15px;font-weight:bold;background:#f1f8fe;padding:1px;border-bottom:1px solid #e6e8ea;margin-bottom:2px;line-height:110%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#u-search .modal .modal-body .modal-results .result .digest{display:block;font-size:13px;line-height:140%;color:#8e8e8e;transition:color .24s}#u-search .modal .modal-body .modal-results .result .digest em{font-weight:bold}#u-search .modal .modal-body .modal-results .result .icon{position:absolute;top:50%;right:0;margin-top:-4px;font-size:11px;color:#828282}#u-search .modal-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:1}#footer{position:relative;padding:20px 20px 40px 20px;font-size:14px;overflow:hidden;text-align:center;opacity:0;transform:translate3d(0, -20px, 0);transition:all .4s;z-index:3}#footer.show{transform:translate3d(0, 0, 0);opacity:1}#footer a{color:#828282}#footer a:hover{background:rgba(255,152,0,0.2);color:#ff9800}.search{position:relative;width:100%;max-width:700px;margin:0 auto 20px auto;z-index:2}.search #searchform{position:relative;display:block;width:100%}.search #searchform #u-search-btn-submit{display:block;position:absolute;top:0;right:0;width:36px;height:36px;background:transparent;color:white;border:0;text-align:center;font-size:18px}.search #searchform #u-search-btn-submit span{line-height:36px}.search #searchinput{width:100%;padding:0 10px;line-height:36px;height:36px;font-size:14px;font-family:"Lato",Helvetica,Arial,"Hiragino Sans GB","Hiragino Sans GB W3",Microsoft JhengHei,WenQuanYi Micro Hei,"Microsoft YaHei",sans-serif;border:none;border-radius:0 !important;background:#414141;color:white;box-sizing:border-box;transition:all .24s ease}.search #searchinput:focus{background:black}#page-nav{position:relative;width:100%;max-width:700px;margin:20px auto 0 auto;transition:all .4s;transform:translate3d(0, -20px, 0);opacity:0;text-align:center}#page-nav.show{opacity:1;transform:translate3d(0, 0, 0)}#page-nav span,#page-nav a{display:inline-block;padding:0 10px;margin:5px 0;height:30px;min-width:30px;line-height:30px;font-size:14px;text-transform:uppercase;vertical-align:middle;text-align:center;transition:all .24s;border-bottom:1px solid transparent}#page-nav span.current{background:#ececec;border-bottom:1px solid #c6c6c6;color:#414141}#page-nav span.space{background:white;color:#414141}#page-nav a{background:white;color:#414141}#page-nav a:hover{background:#f1f1f1;color:black}
\ No newline at end of file
