This commit is contained in:
chai2010
2015-12-14 12:08:47 +08:00
parent 3b8de6c274
commit 0a24303905
132 changed files with 1069 additions and 159 deletions

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11.1" data-chapter-title="go test" data-filepath="ch11/ch11-01.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11.1" data-chapter-title="go test" data-filepath="ch11/ch11-01.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">

View File

@@ -1,3 +1,51 @@
### 11.2.1. 隨機測試
TODO
錶格驅動的測試便於構造基於精心挑選的測試數據的測試用例. 另一種測試思路是隨機測試, 也就是通過構造更廣汎的隨機輸入來測試探索函數的行爲.
那麼對於一箇隨機的輸入, 我們如何能知道希望的輸齣結果呢? 這裡有兩種策略. 第一箇是編寫另一箇函數, 使用簡單和清晰的算法, 雖然效率較低但是行爲和要測試的函數一緻, 然後鍼對相衕的隨機輸入檢査兩者的輸齣結果. 第二種是生成的隨機輸入的數據遵循特定的模式, 這樣我們就可以知道期望的輸齣的模式.
下麫的例子使用的是第二種方法: randomPalindrome 函數用於隨機生成迴文字符串.
```Go
import "math/rand"
// randomPalindrome returns a palindrome whose length and contents
// are derived from the pseudo-random number generator rng.
func randomPalindrome(rng *rand.Rand) string {
n := rng.Intn(25) // random length up to 24
runes := make([]rune, n)
for i := 0; i < (n+1)/2; i++ {
r := rune(rng.Intn(0x1000)) // random rune up to '\u0999'
runes[i] = r
runes[n-1-i] = r
}
return string(runes)
}
func TestRandomPalindromes(t *testing.T) {
// Initialize a pseudo-random number generator.
seed := time.Now().UTC().UnixNano()
t.Logf("Random seed: %d", seed)
rng := rand.New(rand.NewSource(seed))
for i := 0; i < 1000; i++ {
p := randomPalindrome(rng)
if !IsPalindrome(p) {
t.Errorf("IsPalindrome(%q) = false", p)
}
}
}
```
雖然隨機測試有不確定因素, 但是它也是至關重要的, 我們可以從失敗測試的日誌穫取足夠的信息. 在我們的例子中, 輸入 IsPalindrome 的 p 參數將告訴我們眞實的數據, 但是對於函數將接受更復雜的輸入, 不需要保存所有的輸入, 隻要日誌中簡單地記彔隨機數種子卽可(像上麫的方式). 有了這些隨機數初始化種子, 我們可以很容易脩改測試代碼以重現失敗的隨機測試.
通過使用噹前時間作爲隨機種子, 在整箇過程中的每次運行測試命令時都將探索新的隨機數據. 如果你使用的是定期運行的自動化測試集成繫統, 隨機測試將特別有價值.
**練習 11.3:** TestRandomPalindromes 隻測試了迴文字符串. 編寫新的隨機測試生成器, 用於測試隨機生成的非迴文字符串.
**練習 11.4:** 脩改 randomPalindrome 函數, 以探索 IsPalindrome 對標點和空格的處理.

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11.2" data-chapter-title="測試函數" data-filepath="ch11/ch11-02.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11.2" data-chapter-title="測試函數" data-filepath="ch11/ch11-02.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">
@@ -2060,9 +2060,207 @@
<section class="normal" id="section-">
<h2 id="112-&#x6E2C;&#x8A66;&#x51FD;&#x6578;">11.2. &#x6E2C;&#x8A66;&#x51FD;&#x6578;</h2>
<p>TODO</p>
<p>&#x6BCF;&#x7B87;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x5FC5;&#x9808;&#x5C0E;&#x5165; testing &#x5305;. &#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x6709;&#x5982;&#x4E0B;&#x7684;&#x7C3D;&#x540D;:</p>
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> TestName(t *testing.T) {
<span class="hljs-comment">// ...</span>
}
</code></pre>
<p>&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x7684;&#x540D;&#x5B57;&#x5FC5;&#x9808;&#x4EE5;Test&#x958B;&#x982D;, &#x53EF;&#x9078;&#x7684;&#x5F8C;&#x7DB4;&#x540D;&#x5FC5;&#x9808;&#x4EE5;&#x5927;&#x5BEB;&#x5B57;&#x6BCD;&#x958B;&#x982D;:</p>
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> TestSin(t *testing.T) { <span class="hljs-comment">/* ... */</span> }
<span class="hljs-keyword">func</span> TestCos(t *testing.T) { <span class="hljs-comment">/* ... */</span> }
<span class="hljs-keyword">func</span> TestLog(t *testing.T) { <span class="hljs-comment">/* ... */</span> }
</code></pre>
<p>&#x5176;&#x4E2D; t &#x53C3;&#x6578;&#x7528;&#x65BC;&#x5831;&#x544A;&#x6E2C;&#x8A66;&#x5931;&#x6557;&#x548C;&#x9644;&#x4EF6;&#x7684;&#x65E5;&#x8A8C;&#x4FE1;&#x606F;. &#x8B93;&#x6211;&#x5011;&#x9802;&#x4E00;&#x7B87;&#x4E00;&#x7B87;&#x5BE6;&#x4F8B;&#x5305; gopl.io/ch11/word1, &#x96BB;&#x6709;&#x4E00;&#x7B87;&#x51FD;&#x6578; IsPalindrome &#x7528;&#x65BC;&#x6AA2;&#x67FB;&#x4E00;&#x7B87;&#x5B57;&#x7B26;&#x4E32;&#x662F;&#x5426;&#x5F9E;&#x524D;&#x56AE;&#x5F8C;&#x548C;&#x5F9E;&#x5F8C;&#x56AE;&#x524D;&#x8B80;&#x90FD;&#x4E00;&#x6A23;. (&#x9019;&#x7B87;&#x5BE6;&#x73FE;&#x5C0D;&#x65BC;&#x4E00;&#x7B87;&#x5B57;&#x7B26;&#x4E32;&#x662F;&#x5426;&#x662F;&#x8FF4;&#x6587;&#x5B57;&#x7B26;&#x4E32;&#x524D;&#x5F8C;&#x91CD;&#x5FA9;&#x6E2C;&#x8A66;&#x4E86;&#x5169;&#x6B21;; &#x6211;&#x5011;&#x7A0D;&#x5F8C;&#x6703;&#x518D;&#x8A0E;&#x8AD6;&#x9019;&#x7B87;&#x554F;&#x984C;.)</p>
<pre><code class="lang-Go">gopl.io/ch11/word1
<span class="hljs-comment">// Package word provides utilities for word games.</span>
<span class="hljs-keyword">package</span> word
<span class="hljs-comment">// IsPalindrome reports whether s reads the same forward and backward.</span>
<span class="hljs-comment">// (Our first attempt.)</span>
<span class="hljs-keyword">func</span> IsPalindrome(s <span class="hljs-typename">string</span>) <span class="hljs-typename">bool</span> {
<span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> s {
<span class="hljs-keyword">if</span> s[i] != s[<span class="hljs-built_in">len</span>(s)-<span class="hljs-number">1</span>-i] {
<span class="hljs-keyword">return</span> <span class="hljs-constant">false</span>
}
}
<span class="hljs-keyword">return</span> <span class="hljs-constant">true</span>
}
</code></pre>
<p>&#x5728;&#x76F8;&#x8855;&#x7684;&#x76EE;&#x5F54;&#x4E0B;, word_test.go &#x6587;&#x4EF6;&#x5305;&#x542B;&#x4E86; TestPalindrome &#x548C; TestNonPalindrome &#x5169;&#x7B87;&#x6E2C;&#x8A66;&#x51FD;&#x6578;. &#x6BCF;&#x4E00;&#x7B87;&#x90FD;&#x662F;&#x6E2C;&#x8A66; IsPalindrome &#x662F;&#x5426;&#x7D66;&#x9F63;&#x6B63;&#x78BA;&#x7684;&#x7D50;&#x679C;, &#x4F75;&#x4F7F;&#x7528; t.Error &#x5831;&#x544A;&#x5931;&#x6557;:</p>
<pre><code class="lang-Go"><span class="hljs-keyword">package</span> word
<span class="hljs-keyword">import</span> <span class="hljs-string">&quot;testing&quot;</span>
<span class="hljs-keyword">func</span> TestPalindrome(t *testing.T) {
<span class="hljs-keyword">if</span> !IsPalindrome(<span class="hljs-string">&quot;detartrated&quot;</span>) {
t.Error(<span class="hljs-string">`IsPalindrome(&quot;detartrated&quot;) = false`</span>)
}
<span class="hljs-keyword">if</span> !IsPalindrome(<span class="hljs-string">&quot;kayak&quot;</span>) {
t.Error(<span class="hljs-string">`IsPalindrome(&quot;kayak&quot;) = false`</span>)
}
}
<span class="hljs-keyword">func</span> TestNonPalindrome(t *testing.T) {
<span class="hljs-keyword">if</span> IsPalindrome(<span class="hljs-string">&quot;palindrome&quot;</span>) {
t.Error(<span class="hljs-string">`IsPalindrome(&quot;palindrome&quot;) = true`</span>)
}
}
</code></pre>
<p><code>go test</code> (&#x6216; <code>go build</code>) &#x547D;&#x4EE4; &#x5982;&#x679C;&#x6C92;&#x6709;&#x53C3;&#x6578;&#x6307;&#x5B9A;&#x5305;&#x90A3;&#x9EBC;&#x5C07;&#x9ED8;&#x8A8D;&#x5BC0;&#x7528;&#x5679;&#x524D;&#x76EE;&#x5F54;&#x5C0D;&#x61C9;&#x7684;&#x5305;. &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x7528;&#x4E0B;&#x9EAB;&#x7684;&#x547D;&#x4EE4;&#x69CB;&#x5EFA;&#x548C;&#x904B;&#x884C;&#x6E2C;&#x8A66;.</p>
<pre><code>$ cd $GOPATH/src/gopl.io/ch11/word1
$ go test
ok gopl.io/ch11/word1 0.008s
</code></pre><p>&#x9084;&#x6BD4;&#x8F03;&#x6EFF;&#x610F;, &#x6211;&#x5011;&#x904B;&#x884C;&#x4E86;&#x9019;&#x7B87;&#x7A0B;&#x5E8F;, &#x4E0D;&#x904E;&#x6C92;&#x6709;&#x63D0;&#x524D;&#x9000;&#x9F63;&#x662F;&#x56E0;&#x7232;&#x9084;&#x6C92;&#x6709;&#x9047;&#x5230;BUG&#x5831;&#x544A;. &#x4E00;&#x7B87;&#x6CD5;&#x570B;&#x540D;&#x7232; Noelle Eve Elleon &#x7684;&#x7528;&#x6236;&#x62B1;&#x6028; IsPalindrome &#x51FD;&#x6578;&#x4E0D;&#x80FD;&#x8B58;&#x5225; &#x2018;&#x2018;&#xE9;t&#xE9;.&#x2019;&#x2019;. &#x53E6;&#x5916;&#x4E00;&#x7B87;&#x4F86;&#x81EA;&#x7F8E;&#x570B;&#x4E2D;&#x90E8;&#x7528;&#x6236;&#x7684;&#x62B1;&#x6028;&#x662F;&#x4E0D;&#x80FD;&#x8B58;&#x5225; &#x2018;&#x2018;A man, a plan, a canal: Panama.&#x2019;&#x2019;. &#x57F7;&#x884C;&#x7279;&#x6B8A;&#x548C;&#x5C0F;&#x7684;BUG&#x5831;&#x544A;&#x7232;&#x6211;&#x5011;&#x63D0;&#x4F9B;&#x4E86;&#x65B0;&#x7684;&#x66F4;&#x81EA;&#x7136;&#x7684;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;.</p>
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> TestFrenchPalindrome(t *testing.T) {
<span class="hljs-keyword">if</span> !IsPalindrome(<span class="hljs-string">&quot;&#xE9;t&#xE9;&quot;</span>) {
t.Error(<span class="hljs-string">`IsPalindrome(&quot;&#xE9;t&#xE9;&quot;) = false`</span>)
}
}
<span class="hljs-keyword">func</span> TestCanalPalindrome(t *testing.T) {
input := <span class="hljs-string">&quot;A man, a plan, a canal: Panama&quot;</span>
<span class="hljs-keyword">if</span> !IsPalindrome(input) {
t.Errorf(<span class="hljs-string">`IsPalindrome(%q) = false`</span>, input)
}
}
</code></pre>
<p>&#x7232;&#x4E86;&#x907F;&#x514D;&#x5169;&#x6B21;&#x8F38;&#x5165;&#x8F03;&#x9577;&#x7684;&#x5B57;&#x7B26;&#x4E32;, &#x6211;&#x5011;&#x4F7F;&#x7528;&#x4E86;&#x63D0;&#x4F9B;&#x4E86;&#x6709;&#x985E;&#x4F3C; Printf &#x683C;&#x5F0F;&#x5316;&#x529F;&#x80FD;&#x7684; Errorf &#x51FD;&#x6578;&#x4F86;&#x5F59;&#x5831;&#x932F;&#x8AA4;&#x7D50;&#x679C;.</p>
<p>&#x5679;&#x6DFB;&#x52A0;&#x4E86;&#x9019;&#x5169;&#x7B87;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;&#x4E4B;&#x5F8C;, <code>go test</code> &#x8FD4;&#x8FF4;&#x4E86;&#x6E2C;&#x8A66;&#x5931;&#x6557;&#x7684;&#x4FE1;&#x606F;.</p>
<pre><code>$ go test
--- FAIL: TestFrenchPalindrome (0.00s)
word_test.go:28: IsPalindrome(&quot;&#xE9;t&#xE9;&quot;) = false
--- FAIL: TestCanalPalindrome (0.00s)
word_test.go:35: IsPalindrome(&quot;A man, a plan, a canal: Panama&quot;) = false
FAIL
FAIL gopl.io/ch11/word1 0.014s
</code></pre><p>&#x5148;&#x7DE8;&#x5BEB;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;&#x4F75;&#x89C0;&#x5BDF;&#x5230;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;&#x89F8;&#x767C;&#x4E86;&#x548C;&#x7528;&#x6236;&#x5831;&#x544A;&#x7684;&#x932F;&#x8AA4;&#x76F8;&#x8855;&#x7684;&#x63CF;&#x8FF0;&#x662F;&#x4E00;&#x7B87;&#x597D;&#x7684;&#x6E2C;&#x8A66;&#x7FD2;&#x6163;. &#x96BB;&#x6709;&#x9019;&#x6A23;, &#x6211;&#x5011;&#x7E94;&#x80FD;&#x5B9A;&#x4F4D;&#x6211;&#x5011;&#x8981;&#x771E;&#x6B63;&#x89E3;&#x6C7A;&#x7684;&#x554F;&#x984C;.</p>
<p>&#x5148;&#x5BEB;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;&#x7684;&#x53E6;&#x597D;&#x8655;&#x662F;, &#x904B;&#x884C;&#x6E2C;&#x8A66;&#x901A;&#x5E38;&#x6703;&#x6BD4;&#x624B;&#x5DE5;&#x63CF;&#x8FF0;&#x5831;&#x544A;&#x7684;&#x8655;&#x7406;&#x66F4;&#x5FEB;, &#x9019;&#x8B93;&#x6211;&#x5011;&#x53EF;&#x4EE5;&#x9032;&#x884C;&#x5FEB;&#x901F;&#x5730;&#x8FED;&#x4EE3;. &#x5982;&#x679C;&#x6E2C;&#x8A66;&#x96C6;&#x6709;&#x5F88;&#x591A;&#x904B;&#x884C;&#x7DE9;&#x6162;&#x7684;&#x6E2C;&#x8A66;, &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x901A;&#x904E;&#x96BB;&#x9078;&#x64C7;&#x904B;&#x884C;&#x67D0;&#x4E9B;&#x7279;&#x5B9A;&#x7684;&#x6E2C;&#x8A66;&#x4F86;&#x52A0;&#x5FEB;&#x6E2C;&#x8A66;&#x901F;&#x5EA6;.</p>
<p>&#x53C3;&#x6578; <code>-v</code> &#x7528;&#x65BC;&#x6253;&#x5370;&#x6BCF;&#x7B87;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x7684;&#x540D;&#x5B57;&#x548C;&#x904B;&#x884C;&#x6642;&#x9593;:</p>
<pre><code>$ go test -v
=== RUN TestPalindrome
--- PASS: TestPalindrome (0.00s)
=== RUN TestNonPalindrome
--- PASS: TestNonPalindrome (0.00s)
=== RUN TestFrenchPalindrome
--- FAIL: TestFrenchPalindrome (0.00s)
word_test.go:28: IsPalindrome(&quot;&#xE9;t&#xE9;&quot;) = false
=== RUN TestCanalPalindrome
--- FAIL: TestCanalPalindrome (0.00s)
word_test.go:35: IsPalindrome(&quot;A man, a plan, a canal: Panama&quot;) = false
FAIL
exit status 1
FAIL gopl.io/ch11/word1 0.017s
</code></pre><p>&#x53C3;&#x6578; <code>-run</code> &#x662F;&#x4E00;&#x7B87;&#x6B63;&#x5247;&#x9336;&#x9054;&#x5F0F;, &#x96BB;&#x6709;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x540D;&#x88AB;&#x5B83;&#x6B63;&#x78BA;&#x5339;&#x914D;&#x7684;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x7E94;&#x6703;&#x88AB; <code>go test</code> &#x904B;&#x884C;:</p>
<pre><code>$ go test -v -run=&quot;French|Canal&quot;
=== RUN TestFrenchPalindrome
--- FAIL: TestFrenchPalindrome (0.00s)
word_test.go:28: IsPalindrome(&quot;&#xE9;t&#xE9;&quot;) = false
=== RUN TestCanalPalindrome
--- FAIL: TestCanalPalindrome (0.00s)
word_test.go:35: IsPalindrome(&quot;A man, a plan, a canal: Panama&quot;) = false
FAIL
exit status 1
FAIL gopl.io/ch11/word1 0.014s
</code></pre><p>&#x5679;&#x7136;, &#x4E00;&#x65E6;&#x6211;&#x5011;&#x5DF2;&#x7D93;&#x8129;&#x5FA9;&#x4E86;&#x5931;&#x6557;&#x7684;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;, &#x5728;&#x6211;&#x5011;&#x63D0;&#x4EA4;&#x4EE3;&#x78BC;&#x66F4;&#x65B0;&#x4E4B;&#x524D;, &#x6211;&#x5011;&#x61C9;&#x8A72;&#x4EE5;&#x4E0D;&#x5E36;&#x53C3;&#x6578;&#x7684; <code>go test</code> &#x547D;&#x4EE4;&#x904B;&#x884C;&#x5168;&#x90E8;&#x7684;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;, &#x4EE5;&#x78BA;&#x4FDD;&#x66F4;&#x65B0;&#x6C92;&#x6709;&#x5F15;&#x5165;&#x65B0;&#x7684;&#x554F;&#x984C;.</p>
<p>&#x6211;&#x5011;&#x73FE;&#x5728;&#x7684;&#x4EFB;&#x52D9;&#x5C31;&#x662F;&#x8129;&#x5FA9;&#x9019;&#x4E9B;&#x932F;&#x8AA4;. &#x7C21;&#x8981;&#x5206;&#x6790;&#x5F8C;&#x767C;&#x73FE;&#x7B2C;&#x4E00;&#x7B87;BUG&#x7684;&#x539F;&#x56E0;&#x662F;&#x6211;&#x5011;&#x5BC0;&#x7528;&#x4E86; byte &#x800C;&#x4E0D;&#x662F; rune &#x5E8F;&#x5217;, &#x6240;&#x4EE5;&#x50CF; &quot;&#xE9;t&#xE9;&quot; &#x4E2D;&#x7684; &#xE9; &#x7B49;&#x975E; ASCII &#x5B57;&#x7B26;&#x4E0D;&#x80FD;&#x6B63;&#x78BA;&#x8655;&#x7406;. &#x7B2C;&#x4E8C;&#x7B87;BUG&#x662F;&#x56E0;&#x7232;&#x6C92;&#x6709;&#x5FFD;&#x7565;&#x7A7A;&#x683C;&#x548C;&#x5B57;&#x6BCD;&#x7684;&#x5927;&#x5C0F;&#x5BEB;&#x5C0E;&#x7DFB;&#x7684;.</p>
<p>&#x937C;&#x5C0D;&#x4E0A;&#x8FF0;&#x5169;&#x7B87;BUG, &#x6211;&#x5011;&#x4ED4;&#x7D30;&#x91CD;&#x5BEB;&#x4E86;&#x51FD;&#x6578;:</p>
<pre><code class="lang-Go">gopl.io/ch11/word2
<span class="hljs-comment">// Package word provides utilities for word games.</span>
<span class="hljs-keyword">package</span> word
<span class="hljs-keyword">import</span> <span class="hljs-string">&quot;unicode&quot;</span>
<span class="hljs-comment">// IsPalindrome reports whether s reads the same forward and backward.</span>
<span class="hljs-comment">// Letter case is ignored, as are non-letters.</span>
<span class="hljs-keyword">func</span> IsPalindrome(s <span class="hljs-typename">string</span>) <span class="hljs-typename">bool</span> {
<span class="hljs-keyword">var</span> letters []<span class="hljs-typename">rune</span>
<span class="hljs-keyword">for</span> _, r := <span class="hljs-keyword">range</span> s {
<span class="hljs-keyword">if</span> unicode.IsLetter(r) {
letters = <span class="hljs-built_in">append</span>(letters, unicode.ToLower(r))
}
}
<span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> letters {
<span class="hljs-keyword">if</span> letters[i] != letters[<span class="hljs-built_in">len</span>(letters)-<span class="hljs-number">1</span>-i] {
<span class="hljs-keyword">return</span> <span class="hljs-constant">false</span>
}
}
<span class="hljs-keyword">return</span> <span class="hljs-constant">true</span>
}
</code></pre>
<p>&#x8855;&#x6642;&#x6211;&#x5011;&#x4E5F;&#x5C07;&#x4E4B;&#x524D;&#x7684;&#x6240;&#x6709;&#x6E2C;&#x8A66;&#x6578;&#x64DA;&#x95A4;&#x4F75;&#x5230;&#x4E86;&#x4E00;&#x7B87;&#x6E2C;&#x8A66;&#x4E2D;&#x7684;&#x9336;&#x683C;&#x4E2D;.</p>
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> TestIsPalindrome(t *testing.T) {
<span class="hljs-keyword">var</span> tests = []<span class="hljs-keyword">struct</span> {
input <span class="hljs-typename">string</span>
want <span class="hljs-typename">bool</span>
}{
{<span class="hljs-string">&quot;&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;aa&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;ab&quot;</span>, <span class="hljs-constant">false</span>},
{<span class="hljs-string">&quot;kayak&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;detartrated&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;A man, a plan, a canal: Panama&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;Evil I did dwell; lewd did I live.&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;Able was I ere I saw Elba&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;&#xE9;t&#xE9;&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;Et se resservir, ivresse reste.&quot;</span>, <span class="hljs-constant">true</span>},
{<span class="hljs-string">&quot;palindrome&quot;</span>, <span class="hljs-constant">false</span>}, <span class="hljs-comment">// non-palindrome</span>
{<span class="hljs-string">&quot;desserts&quot;</span>, <span class="hljs-constant">false</span>}, <span class="hljs-comment">// semi-palindrome</span>
}
<span class="hljs-keyword">for</span> _, test := <span class="hljs-keyword">range</span> tests {
<span class="hljs-keyword">if</span> got := IsPalindrome(test.input); got != test.want {
t.Errorf(<span class="hljs-string">&quot;IsPalindrome(%q) = %v&quot;</span>, test.input, got)
}
}
}
</code></pre>
<p>&#x6211;&#x5011;&#x7684;&#x65B0;&#x6E2C;&#x8A66;&#x963F;&#x90FD;&#x901A;&#x904E;&#x4E86;:</p>
<pre><code>$ go test gopl.io/ch11/word2
ok gopl.io/ch11/word2 0.015s
</code></pre><p>&#x9019;&#x7A2E;&#x9336;&#x683C;&#x9A45;&#x52D5;&#x7684;&#x6E2C;&#x8A66;&#x5728;Go&#x4E2D;&#x5F88;&#x5E38;&#x898B;&#x7684;. &#x6211;&#x5011;&#x5F88;&#x5BB9;&#x6613;&#x60F3;&#x9336;&#x683C;&#x6DFB;&#x52A0;&#x65B0;&#x7684;&#x6E2C;&#x8A66;&#x6578;&#x64DA;, &#x4F75;&#x4E14;&#x5F8C;&#x9EAB;&#x7684;&#x6E2C;&#x8A66;&#x908F;&#x8F2F;&#x4E5F;&#x6C92;&#x6709;&#x5197;&#x9918;, &#x9019;&#x6A23;&#x6211;&#x5011;&#x53EF;&#x4EE5;&#x66F4;&#x597D;&#x5730;&#x5B8C;&#x5584;&#x932F;&#x8AA4;&#x4FE1;&#x606F;.</p>
<p>&#x5931;&#x6557;&#x7684;&#x6E2C;&#x8A66;&#x7684;&#x8F38;&#x9F63;&#x4F75;&#x4E0D;&#x5305;&#x62EC;&#x8ABF;&#x7528; t.Errorf &#x6642;&#x523B;&#x7684;&#x5806;&#x68E7;&#x8ABF;&#x7528;&#x4FE1;&#x606F;. &#x4E0D;&#x50CF;&#x5176;&#x4ED6;&#x8A9E;&#x8A00;&#x6216;&#x6E2C;&#x8A66;&#x6846;&#x67B6;&#x7684; assert &#x65B7;&#x8A00;, t.Errorf &#x8ABF;&#x7528;&#x4E5F;&#x6C92;&#x6709;&#x5F15;&#x8D77; panic &#x6216;&#x505C;&#x6B62;&#x6E2C;&#x8A66;&#x7684;&#x57F7;&#x884C;. &#x537D;&#x4F7F;&#x9336;&#x683C;&#x4E2D;&#x524D;&#x9EAB;&#x7684;&#x6578;&#x64DA;&#x5C0E;&#x7DFB;&#x4E86;&#x6E2C;&#x8A66;&#x7684;&#x5931;&#x6557;, &#x9336;&#x683C;&#x5F8C;&#x9EAB;&#x7684;&#x6E2C;&#x8A66;&#x6578;&#x64DA;&#x4F9D;&#x7136;&#x6703;&#x904B;&#x884C;&#x6E2C;&#x8A66;, &#x56E0;&#x6B64;&#x5728;&#x4E00;&#x7B87;&#x6E2C;&#x8A66;&#x4E2D;&#x6211;&#x5011;&#x53EF;&#x80FD;&#x4E86;&#x89E3;&#x591A;&#x7B87;&#x5931;&#x6557;&#x7684;&#x4FE1;&#x606F;.</p>
<p>&#x5982;&#x679C;&#x6211;&#x5011;&#x771E;&#x7684;&#x9700;&#x8981;&#x505C;&#x6B62;&#x6E2C;&#x8A66;, &#x6216;&#x8A31;&#x662F;&#x56E0;&#x7232;&#x521D;&#x59CB;&#x5316;&#x5931;&#x6557;&#x6216;&#x53EF;&#x80FD;&#x662F;&#x65E9;&#x5148;&#x7684;&#x932F;&#x8AA4;&#x5C0E;&#x7DFB;&#x4E86;&#x5F8C;&#x7E8C;&#x932F;&#x8AA4;&#x7B49;&#x539F;&#x56E0;, &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x4F7F;&#x7528; t.Fatal &#x6216; t.Fatalf &#x505C;&#x6B62;&#x6E2C;&#x8A66;. &#x5B83;&#x5011;&#x5FC5;&#x9808;&#x5728;&#x548C;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x8855;&#x4E00;&#x7B87; goroutine &#x5167;&#x8ABF;&#x7528;.</p>
<p>&#x6E2C;&#x8A66;&#x5931;&#x6557;&#x7684;&#x4FE1;&#x606F;&#x4E00;&#x822C;&#x7684;&#x5F62;&#x5F0F;&#x662F; &quot;f(x) = y, want z&quot;, f(x) &#x89E3;&#x91CB;&#x4E86;&#x5931;&#x6557;&#x7684;&#x64CD;&#x4F5C;&#x548C;&#x5C0D;&#x61C9;&#x7684;&#x8F38;&#x9F63;, y &#x662F;&#x5BE6;&#x969B;&#x7684;&#x904B;&#x884C;&#x7D50;&#x679C;, z &#x662F;&#x671F;&#x671B;&#x7684;&#x6B63;&#x78BA;&#x7684;&#x7D50;&#x679C;. &#x5C31;&#x50CF;&#x524D;&#x9EAB;&#x6AA2;&#x67FB;&#x8FF4;&#x6587;&#x5B57;&#x7B26;&#x4E32;&#x7684;&#x4F8B;&#x5B50;, &#x5BE6;&#x969B;&#x7684;&#x51FD;&#x6578;&#x7528;&#x65BC; f(x) &#x90E8;&#x5206;. &#x5982;&#x679C;&#x986F;&#x793A; x &#x662F;&#x9336;&#x683C;&#x9A45;&#x52D5;&#x578B;&#x6E2C;&#x8A66;&#x4E2D;&#x6BD4;&#x8F03;&#x91CD;&#x8981;&#x7684;&#x90E8;&#x5206;, &#x56E0;&#x7232;&#x8855;&#x4E00;&#x7B87;&#x65B7;&#x8A00;&#x53EF;&#x80FD;&#x5C0D;&#x61C9;&#x4E0D;&#x8855;&#x7684;&#x9336;&#x683C;&#x9805;&#x57F7;&#x884C;&#x591A;&#x6B21;. &#x8981;&#x907F;&#x514D;&#x7121;&#x7528;&#x548C;&#x5197;&#x9918;&#x7684;&#x4FE1;&#x606F;. &#x5728;&#x6E2C;&#x8A66;&#x985E;&#x4F3C; IsPalindrome &#x8FD4;&#x8FF4;&#x4F48;&#x723E;&#x985E;&#x578B;&#x7684;&#x51FD;&#x6578;&#x6642;, &#x53EF;&#x4EE5;&#x5FFD;&#x7565;&#x4F75;&#x6C92;&#x6709;&#x984D;&#x5916;&#x4FE1;&#x606F;&#x7684; z &#x90E8;&#x5206;. &#x5982;&#x679C; x, y &#x6216; z &#x662F; y &#x7684;&#x9577;&#x5EA6;, &#x8F38;&#x9F63;&#x4E00;&#x7B87;&#x76F8;&#x95DC;&#x90E8;&#x5206;&#x7684;&#x7C21;&#x660E;&#x7E3D;&#x7D50;&#x537D;&#x53EF;. &#x6E2C;&#x8A66;&#x7684;&#x4F5C;&#x8005;&#x61C9;&#x8A72;&#x8981;&#x52AA;&#x529B;&#x5E6B;&#x52A9;&#x7A0B;&#x5E8F;&#x54E1;&#x8A3A;&#x65B7;&#x5931;&#x6557;&#x7684;&#x6E2C;&#x8A66;.</p>
<p><strong>&#x7DF4;&#x7FD2; 11.1:</strong> &#x7232; 4.3&#x7BC0; &#x4E2D;&#x7684; charcount &#x7A0B;&#x5E8F;&#x7DE8;&#x5BEB;&#x6E2C;&#x8A66;.</p>
<p><strong>&#x7DF4;&#x7FD2; 11.2:</strong> &#x7232; (&#xA7;6.5)&#x7684; IntSet &#x7DE8;&#x5BEB;&#x4E00;&#x7D44;&#x6E2C;&#x8A66;, &#x7528;&#x65BC;&#x6AA2;&#x67FB;&#x6BCF;&#x7B87;&#x64CD;&#x4F5C;&#x5F8C;&#x7684;&#x884C;&#x7232;&#x548C;&#x57FA;&#x65BC;&#x5167;&#x7F6E; map &#x7684;&#x96C6;&#x95A4;&#x7B49;&#x50F9; , &#x5F8C;&#x9EAB; &#x7DF4;&#x7FD2;11.7 &#x5C07;&#x6703;&#x7528;&#x5230;.</p>
<h3 id="1121-&#x96A8;&#x6A5F;&#x6E2C;&#x8A66;">11.2.1. &#x96A8;&#x6A5F;&#x6E2C;&#x8A66;</h3>
<p>TODO</p>
<p>&#x9336;&#x683C;&#x9A45;&#x52D5;&#x7684;&#x6E2C;&#x8A66;&#x4FBF;&#x65BC;&#x69CB;&#x9020;&#x57FA;&#x65BC;&#x7CBE;&#x5FC3;&#x6311;&#x9078;&#x7684;&#x6E2C;&#x8A66;&#x6578;&#x64DA;&#x7684;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;. &#x53E6;&#x4E00;&#x7A2E;&#x6E2C;&#x8A66;&#x601D;&#x8DEF;&#x662F;&#x96A8;&#x6A5F;&#x6E2C;&#x8A66;, &#x4E5F;&#x5C31;&#x662F;&#x901A;&#x904E;&#x69CB;&#x9020;&#x66F4;&#x5EE3;&#x6C4E;&#x7684;&#x96A8;&#x6A5F;&#x8F38;&#x5165;&#x4F86;&#x6E2C;&#x8A66;&#x63A2;&#x7D22;&#x51FD;&#x6578;&#x7684;&#x884C;&#x7232;.</p>
<p>&#x90A3;&#x9EBC;&#x5C0D;&#x65BC;&#x4E00;&#x7B87;&#x96A8;&#x6A5F;&#x7684;&#x8F38;&#x5165;, &#x6211;&#x5011;&#x5982;&#x4F55;&#x80FD;&#x77E5;&#x9053;&#x5E0C;&#x671B;&#x7684;&#x8F38;&#x9F63;&#x7D50;&#x679C;&#x5462;? &#x9019;&#x88E1;&#x6709;&#x5169;&#x7A2E;&#x7B56;&#x7565;. &#x7B2C;&#x4E00;&#x7B87;&#x662F;&#x7DE8;&#x5BEB;&#x53E6;&#x4E00;&#x7B87;&#x51FD;&#x6578;, &#x4F7F;&#x7528;&#x7C21;&#x55AE;&#x548C;&#x6E05;&#x6670;&#x7684;&#x7B97;&#x6CD5;, &#x96D6;&#x7136;&#x6548;&#x7387;&#x8F03;&#x4F4E;&#x4F46;&#x662F;&#x884C;&#x7232;&#x548C;&#x8981;&#x6E2C;&#x8A66;&#x7684;&#x51FD;&#x6578;&#x4E00;&#x7DFB;, &#x7136;&#x5F8C;&#x937C;&#x5C0D;&#x76F8;&#x8855;&#x7684;&#x96A8;&#x6A5F;&#x8F38;&#x5165;&#x6AA2;&#x67FB;&#x5169;&#x8005;&#x7684;&#x8F38;&#x9F63;&#x7D50;&#x679C;. &#x7B2C;&#x4E8C;&#x7A2E;&#x662F;&#x751F;&#x6210;&#x7684;&#x96A8;&#x6A5F;&#x8F38;&#x5165;&#x7684;&#x6578;&#x64DA;&#x9075;&#x5FAA;&#x7279;&#x5B9A;&#x7684;&#x6A21;&#x5F0F;, &#x9019;&#x6A23;&#x6211;&#x5011;&#x5C31;&#x53EF;&#x4EE5;&#x77E5;&#x9053;&#x671F;&#x671B;&#x7684;&#x8F38;&#x9F63;&#x7684;&#x6A21;&#x5F0F;.</p>
<p>&#x4E0B;&#x9EAB;&#x7684;&#x4F8B;&#x5B50;&#x4F7F;&#x7528;&#x7684;&#x662F;&#x7B2C;&#x4E8C;&#x7A2E;&#x65B9;&#x6CD5;: randomPalindrome &#x51FD;&#x6578;&#x7528;&#x65BC;&#x96A8;&#x6A5F;&#x751F;&#x6210;&#x8FF4;&#x6587;&#x5B57;&#x7B26;&#x4E32;.</p>
<pre><code class="lang-Go"><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;math/rand&quot;</span>
<span class="hljs-comment">// randomPalindrome returns a palindrome whose length and contents</span>
<span class="hljs-comment">// are derived from the pseudo-random number generator rng.</span>
<span class="hljs-keyword">func</span> randomPalindrome(rng *rand.Rand) <span class="hljs-typename">string</span> {
n := rng.Intn(<span class="hljs-number">25</span>) <span class="hljs-comment">// random length up to 24</span>
runes := <span class="hljs-built_in">make</span>([]<span class="hljs-typename">rune</span>, n)
<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; (n+<span class="hljs-number">1</span>)/<span class="hljs-number">2</span>; i++ {
r := <span class="hljs-typename">rune</span>(rng.Intn(<span class="hljs-number">0x1000</span>)) <span class="hljs-comment">// random rune up to &apos;\u0999&apos;</span>
runes[i] = r
runes[n-<span class="hljs-number">1</span>-i] = r
}
<span class="hljs-keyword">return</span> <span class="hljs-typename">string</span>(runes)
}
<span class="hljs-keyword">func</span> TestRandomPalindromes(t *testing.T) {
<span class="hljs-comment">// Initialize a pseudo-random number generator.</span>
seed := time.Now().UTC().UnixNano()
t.Logf(<span class="hljs-string">&quot;Random seed: %d&quot;</span>, seed)
rng := rand.New(rand.NewSource(seed))
<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++ {
p := randomPalindrome(rng)
<span class="hljs-keyword">if</span> !IsPalindrome(p) {
t.Errorf(<span class="hljs-string">&quot;IsPalindrome(%q) = false&quot;</span>, p)
}
}
}
</code></pre>
<p>&#x96D6;&#x7136;&#x96A8;&#x6A5F;&#x6E2C;&#x8A66;&#x6709;&#x4E0D;&#x78BA;&#x5B9A;&#x56E0;&#x7D20;, &#x4F46;&#x662F;&#x5B83;&#x4E5F;&#x662F;&#x81F3;&#x95DC;&#x91CD;&#x8981;&#x7684;, &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x5F9E;&#x5931;&#x6557;&#x6E2C;&#x8A66;&#x7684;&#x65E5;&#x8A8C;&#x7A6B;&#x53D6;&#x8DB3;&#x5920;&#x7684;&#x4FE1;&#x606F;. &#x5728;&#x6211;&#x5011;&#x7684;&#x4F8B;&#x5B50;&#x4E2D;, &#x8F38;&#x5165; IsPalindrome &#x7684; p &#x53C3;&#x6578;&#x5C07;&#x544A;&#x8A34;&#x6211;&#x5011;&#x771E;&#x5BE6;&#x7684;&#x6578;&#x64DA;, &#x4F46;&#x662F;&#x5C0D;&#x65BC;&#x51FD;&#x6578;&#x5C07;&#x63A5;&#x53D7;&#x66F4;&#x5FA9;&#x96DC;&#x7684;&#x8F38;&#x5165;, &#x4E0D;&#x9700;&#x8981;&#x4FDD;&#x5B58;&#x6240;&#x6709;&#x7684;&#x8F38;&#x5165;, &#x96BB;&#x8981;&#x65E5;&#x8A8C;&#x4E2D;&#x7C21;&#x55AE;&#x5730;&#x8A18;&#x5F54;&#x96A8;&#x6A5F;&#x6578;&#x7A2E;&#x5B50;&#x537D;&#x53EF;(&#x50CF;&#x4E0A;&#x9EAB;&#x7684;&#x65B9;&#x5F0F;). &#x6709;&#x4E86;&#x9019;&#x4E9B;&#x96A8;&#x6A5F;&#x6578;&#x521D;&#x59CB;&#x5316;&#x7A2E;&#x5B50;, &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x5F88;&#x5BB9;&#x6613;&#x8129;&#x6539;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;&#x4EE5;&#x91CD;&#x73FE;&#x5931;&#x6557;&#x7684;&#x96A8;&#x6A5F;&#x6E2C;&#x8A66;.</p>
<p>&#x901A;&#x904E;&#x4F7F;&#x7528;&#x5679;&#x524D;&#x6642;&#x9593;&#x4F5C;&#x7232;&#x96A8;&#x6A5F;&#x7A2E;&#x5B50;, &#x5728;&#x6574;&#x7B87;&#x904E;&#x7A0B;&#x4E2D;&#x7684;&#x6BCF;&#x6B21;&#x904B;&#x884C;&#x6E2C;&#x8A66;&#x547D;&#x4EE4;&#x6642;&#x90FD;&#x5C07;&#x63A2;&#x7D22;&#x65B0;&#x7684;&#x96A8;&#x6A5F;&#x6578;&#x64DA;. &#x5982;&#x679C;&#x4F60;&#x4F7F;&#x7528;&#x7684;&#x662F;&#x5B9A;&#x671F;&#x904B;&#x884C;&#x7684;&#x81EA;&#x52D5;&#x5316;&#x6E2C;&#x8A66;&#x96C6;&#x6210;&#x7E6B;&#x7D71;, &#x96A8;&#x6A5F;&#x6E2C;&#x8A66;&#x5C07;&#x7279;&#x5225;&#x6709;&#x50F9;&#x503C;.</p>
<p><strong>&#x7DF4;&#x7FD2; 11.3:</strong> TestRandomPalindromes &#x96BB;&#x6E2C;&#x8A66;&#x4E86;&#x8FF4;&#x6587;&#x5B57;&#x7B26;&#x4E32;. &#x7DE8;&#x5BEB;&#x65B0;&#x7684;&#x96A8;&#x6A5F;&#x6E2C;&#x8A66;&#x751F;&#x6210;&#x5668;, &#x7528;&#x65BC;&#x6E2C;&#x8A66;&#x96A8;&#x6A5F;&#x751F;&#x6210;&#x7684;&#x975E;&#x8FF4;&#x6587;&#x5B57;&#x7B26;&#x4E32;.</p>
<p><strong>&#x7DF4;&#x7FD2; 11.4:</strong> &#x8129;&#x6539; randomPalindrome &#x51FD;&#x6578;, &#x4EE5;&#x63A2;&#x7D22; IsPalindrome &#x5C0D;&#x6A19;&#x9EDE;&#x548C;&#x7A7A;&#x683C;&#x7684;&#x8655;&#x7406;.</p>
<h3 id="1122-&#x6E2C;&#x8A66;&#x4E00;&#x500B;&#x547D;&#x4EE4;">11.2.2. &#x6E2C;&#x8A66;&#x4E00;&#x500B;&#x547D;&#x4EE4;</h3>
<p>TODO</p>
<h3 id="1123-&#x767D;&#x76D2;&#x6E2C;&#x8A66;">11.2.3. &#x767D;&#x76D2;&#x6E2C;&#x8A66;</h3>

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11.3" data-chapter-title="測試覆蓋率" data-filepath="ch11/ch11-03.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11.3" data-chapter-title="測試覆蓋率" data-filepath="ch11/ch11-03.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">
@@ -2060,7 +2060,75 @@
<section class="normal" id="section-">
<h2 id="113-&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;">11.3. &#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;</h2>
<p>TODO</p>
<p>&#x5C31;&#x5176;&#x6027;&#x8CEA;&#x800C;&#x8A00;, &#x6E2C;&#x8A66;&#x4E0D;&#x53EF;&#x80FD;&#x662F;&#x5B8C;&#x6574;&#x7684;. &#x8A08;&#x7B97;&#x6A5F;&#x79D1;&#x5B78;&#x50A2; Edsger Dijkstra &#x66FE;&#x8AAC;&#x904E;: &quot;&#x6E2C;&#x8A66;&#x53EF;&#x4EE5;&#x986F;&#x793A;&#x5B58;&#x5728;&#x7F3A;&#x9677;, &#x4F46;&#x662F;&#x4F75;&#x4E0D;&#x662F;&#x8AAC;&#x6C92;&#x6709;BUG.&quot; &#x518D;&#x591A;&#x7684;&#x6E2C;&#x8A66;&#x4E5F;&#x4E0D;&#x80FD;&#x8B49;&#x660E;&#x4E00;&#x500B;&#x5305;&#x6C92;&#x6709;BUG. &#x5728;&#x6700;&#x597D;&#x7684;&#x60C5;&#x6CC1;&#x4E0B;, &#x6E2C;&#x8A66;&#x53EF;&#x4EE5;&#x589E;&#x5F37;&#x6211;&#x5011;&#x7684;&#x4FE1;&#x606F;, &#x5305;&#x5728;&#x6211;&#x5011;&#x6E2C;&#x8A66;&#x7684;&#x74B0;&#x5883;&#x662F;&#x53EF;&#x4EE5;&#x6B63;&#x5E38;&#x5DE5;&#x4F5C;&#x7684;.</p>
<p>&#x7531;&#x6E2C;&#x8A66;&#x9A45;&#x52D5;&#x89F8;&#x767C;&#x904B;&#x884C;&#x5230;&#x7684;&#x88AB;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x7684;&#x4EE3;&#x78BC;&#x6578;&#x76EE;&#x7A31;&#x7232;&#x6E2C;&#x8A66;&#x7684;&#x8986;&#x84CB;&#x7387;. &#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;&#x4F75;&#x4E0D;&#x80FD;&#x91CF;&#x5316; &#x2014; &#x751A;&#x81F3;&#x9023;&#x6700;&#x7C21;&#x55AE;&#x7684;&#x52D5;&#x614B;&#x7A0B;&#x5E8F;&#x4E5F;&#x96E3;&#x4EE5;&#x7CBE;&#x78BA;&#x6E2C;&#x91CF; &#x2014; &#x4F46;&#x662F;&#x53EF;&#x4EE5;&#x5553;&#x767C;&#x4F75;&#x5E6B;&#x52A9;&#x6211;&#x5011;&#x7DE8;&#x5BEB;&#x7684;&#x6709;&#x6548;&#x7684;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;.</p>
<p>&#x9019;&#x4E9B;&#x5E6B;&#x52A9;&#x4FE1;&#x606F;&#x4E2D;&#x8A9E;&#x53E5;&#x7684;&#x8986;&#x84CB;&#x7387;&#x662F;&#x6700;&#x7C21;&#x55AE;&#x548C;&#x6700;&#x5EE3;&#x6C4E;&#x4F7F;&#x7528;&#x7684;. &#x8A9E;&#x53E5;&#x7684;&#x8986;&#x84CB;&#x7387;&#x662F;&#x6307;&#x5728;&#x6E2C;&#x8A66;&#x4E2D;&#x81F3;&#x5C11;&#x88AB;&#x904B;&#x884C;&#x4E00;&#x6B21;&#x7684;&#x4EE3;&#x78BC;&#x4F54;&#x7E3D;&#x4EE3;&#x78BC;&#x6578;&#x7684;&#x6BD4;&#x4F8B;. &#x5728;&#x672C;&#x7BC0;&#x4E2D;, &#x6211;&#x5011;&#x4F7F;&#x7528; <code>go test</code> &#x4E2D;&#x96C6;&#x6210;&#x7684;&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;&#x5DE5;&#x5177;, &#x4F86;&#x5EA6;&#x91CF;&#x4E0B;&#x9EAB;&#x4EE3;&#x78BC;&#x7684;&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;, &#x5E6B;&#x52A9;&#x6211;&#x5011;&#x8B58;&#x5F46;&#x6E2C;&#x8A66;&#x548C;&#x6211;&#x5011;&#x671F;&#x671B;&#x9593;&#x7684;&#x5DEE;&#x8DDD;.</p>
<p>The code below is a table-driven test for the expression evaluator we built back in Chapter 7:</p>
<p>&#x4E0B;&#x9EAB;&#x7684;&#x4EE3;&#x78BC;&#x662F;&#x4E00;&#x500B;&#x9336;&#x683C;&#x9A45;&#x52D5;&#x7684;&#x6E2C;&#x8A66;, &#x7528;&#x65BC;&#x6E2C;&#x8A66;&#x7B2C;&#x4E03;&#x7AE0;&#x7684;&#x9336;&#x9054;&#x5F0F;&#x6C42;&#x503C;&#x7A0B;&#x5E8F;:</p>
<pre><code class="lang-Go">gopl.io/ch7/eval
<span class="hljs-keyword">func</span> TestCoverage(t *testing.T) {
<span class="hljs-keyword">var</span> tests = []<span class="hljs-keyword">struct</span> {
input <span class="hljs-typename">string</span>
env Env
want <span class="hljs-typename">string</span> <span class="hljs-comment">// expected error from Parse/Check or result from Eval</span>
}{
{<span class="hljs-string">&quot;x % 2&quot;</span>, <span class="hljs-constant">nil</span>, <span class="hljs-string">&quot;unexpected &apos;%&apos;&quot;</span>},
{<span class="hljs-string">&quot;!true&quot;</span>, <span class="hljs-constant">nil</span>, <span class="hljs-string">&quot;unexpected &apos;!&apos;&quot;</span>},
{<span class="hljs-string">&quot;log(10)&quot;</span>, <span class="hljs-constant">nil</span>, <span class="hljs-string">`unknown function &quot;log&quot;`</span>},
{<span class="hljs-string">&quot;sqrt(1, 2)&quot;</span>, <span class="hljs-constant">nil</span>, <span class="hljs-string">&quot;call to sqrt has 2 args, want 1&quot;</span>},
{<span class="hljs-string">&quot;sqrt(A / pi)&quot;</span>, Env{<span class="hljs-string">&quot;A&quot;</span>: <span class="hljs-number">87616</span>, <span class="hljs-string">&quot;pi&quot;</span>: math.Pi}, <span class="hljs-string">&quot;167&quot;</span>},
{<span class="hljs-string">&quot;pow(x, 3) + pow(y, 3)&quot;</span>, Env{<span class="hljs-string">&quot;x&quot;</span>: <span class="hljs-number">9</span>, <span class="hljs-string">&quot;y&quot;</span>: <span class="hljs-number">10</span>}, <span class="hljs-string">&quot;1729&quot;</span>},
{<span class="hljs-string">&quot;5 / 9 * (F - 32)&quot;</span>, Env{<span class="hljs-string">&quot;F&quot;</span>: -<span class="hljs-number">40</span>}, <span class="hljs-string">&quot;-40&quot;</span>},
}
<span class="hljs-keyword">for</span> _, test := <span class="hljs-keyword">range</span> tests {
expr, err := Parse(test.input)
<span class="hljs-keyword">if</span> err == <span class="hljs-constant">nil</span> {
err = expr.Check(<span class="hljs-keyword">map</span>[Var]<span class="hljs-typename">bool</span>{})
}
<span class="hljs-keyword">if</span> err != <span class="hljs-constant">nil</span> {
<span class="hljs-keyword">if</span> err.Error() != test.want {
t.Errorf(<span class="hljs-string">&quot;%s: got %q, want %q&quot;</span>, test.input, err, test.want)
}
<span class="hljs-keyword">continue</span>
}
got := fmt.Sprintf(<span class="hljs-string">&quot;%.6g&quot;</span>, expr.Eval(test.env))
<span class="hljs-keyword">if</span> got != test.want {
t.Errorf(<span class="hljs-string">&quot;%s: %v =&gt; %s, want %s&quot;</span>,
test.input, test.env, got, test.want)
}
}
}
</code></pre>
<p>&#x9996;&#x5148;, &#x6211;&#x5011;&#x8981;&#x78BA;&#x4FDD;&#x6240;&#x6709;&#x7684;&#x6E2C;&#x8A66;&#x90FD;&#x6B63;&#x5E38;&#x901A;&#x904E;:</p>
<pre><code>$ go test -v -run=Coverage gopl.io/ch7/eval
=== RUN TestCoverage
--- PASS: TestCoverage (0.00s)
PASS
ok gopl.io/ch7/eval 0.011s
</code></pre><p>&#x4E0B;&#x9EAB;&#x9019;&#x500B;&#x547D;&#x4EE4;&#x53EF;&#x4EE5;&#x986F;&#x793A;&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;&#x5DE5;&#x5177;&#x7684;&#x7528;&#x6CD5;&#x4FE1;&#x606F;:</p>
<pre><code>$ go tool cover
Usage of &apos;go tool cover&apos;:
Given a coverage profile produced by &apos;go test&apos;:
go test -coverprofile=c.out
Open a web browser displaying annotated source code:
go tool cover -html=c.out
...
</code></pre><p><code>go tool</code> &#x547D;&#x4EE4;&#x904B;&#x884C;Go&#x5DE5;&#x5177;&#x93C8;&#x7684;&#x5E95;&#x5C64;&#x53EF;&#x57F7;&#x884C;&#x7A0B;&#x5E8F;. &#x9019;&#x4E9B;&#x5E95;&#x5C64;&#x53EF;&#x57F7;&#x884C;&#x7A0B;&#x5E8F;&#x653E;&#x5728; $GOROOT/pkg/tool/${GOOS}_${GOARCH} &#x76EE;&#x5F54;. &#x56E0;&#x7232; <code>go build</code> &#x7684;&#x539F;&#x56E0;, &#x6211;&#x5011;&#x5F88;&#x5C0F;&#x76F4;&#x63A5;&#x8ABF;&#x7528;&#x9019;&#x4E9B;&#x5E95;&#x5C64;&#x5DE5;&#x5177;.</p>
<p>&#x73FE;&#x5728;&#x6211;&#x5011;&#x53EF;&#x4EE5;&#x7528; <code>-coverprofile</code> &#x6A19;&#x8A8C;&#x8518;&#x6578;&#x91CD;&#x65B0;&#x904B;&#x884C;:</p>
<pre><code>$ go test -run=Coverage -coverprofile=c.out gopl.io/ch7/eval
ok gopl.io/ch7/eval 0.032s coverage: 68.5% of statements
</code></pre><p>&#x9019;&#x500B;&#x6A19;&#x8A8C;&#x8518;&#x6578;&#x901A;&#x904E;&#x63D2;&#x5165;&#x751F;&#x6210;&#x9264;&#x5B50;&#x4EE3;&#x78BC;&#x4F86;&#x7D71;&#x8A08;&#x8986;&#x84CB;&#x7387;&#x6578;&#x64DA;. &#x4E5F;&#x5C31;&#x662F;&#x8AAC;, &#x5728;&#x904B;&#x884C;&#x6BCF;&#x500B;&#x6E2C;&#x8A66;&#x524D;, &#x5B83;&#x6703;&#x8129;&#x6539;&#x8981;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;&#x7684;&#x526F;&#x672C;, &#x5728;&#x6BCF;&#x500B;&#x584A;&#x90FD;&#x6703;&#x8A2D;&#x7F6E;&#x4E00;&#x500B;&#x4F48;&#x723E;&#x6A19;&#x8A8C;&#x8B8A;&#x91CF;. &#x5679;&#x88AB;&#x8129;&#x6539;&#x5F8C;&#x7684;&#x88AB;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;&#x904B;&#x884C;&#x9000;&#x9F63;&#x6642;, &#x5C07;&#x7D71;&#x8A08;&#x65E5;&#x8A8C;&#x6578;&#x64DA;&#x5BEB;&#x5165; c.out &#x6587;&#x4EF6;, &#x4F75;&#x6253;&#x5370;&#x4E00;&#x90E8;&#x5206;&#x57F7;&#x884C;&#x7684;&#x8A9E;&#x53E5;&#x7684;&#x4E00;&#x500B;&#x7E3D;&#x7D50;. (&#x5982;&#x679C;&#x4F60;&#x9700;&#x8981;&#x7684;&#x662F;&#x6458;&#x8981;,&#x4F7F;&#x7528; <code>go test -cover</code>.)</p>
<p>&#x5982;&#x679C;&#x4F7F;&#x7528;&#x4E86; <code>-covermode=count</code> &#x6A19;&#x8A8C;&#x8518;&#x6578;, &#x90A3;&#x9EBD;&#x5C07;&#x5728;&#x6BCF;&#x500B;&#x4EE3;&#x78BC;&#x584A;&#x63D2;&#x5165;&#x4E00;&#x500B;&#x8A08;&#x6578;&#x5668;&#x800C;&#x4E0D;&#x662F;&#x4F48;&#x723E;&#x6A19;&#x8A8C;&#x91CF;. &#x5728;&#x7D71;&#x8A08;&#x7D50;&#x679C;&#x4E2D;&#x8A18;&#x5F54;&#x4E86;&#x6BCF;&#x500B;&#x584A;&#x7684;&#x57F7;&#x884C;&#x6B21;&#x6578;, &#x9019;&#x53EF;&#x4EE5;&#x7528;&#x65BC;&#x8861;&#x91CF;&#x54EA;&#x4E9B;&#x662F;&#x88AB;&#x983B;&#x7E41;&#x57F7;&#x884C;&#x7684;&#x71B1;&#x9EDE;&#x4EE3;&#x78BC;.</p>
<p>&#x7232;&#x4E86;&#x6536;&#x96C6;&#x6578;&#x64DA;, &#x6211;&#x5011;&#x904B;&#x884C;&#x4E86;&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;&#x5DE5;&#x5177;, &#x6253;&#x5370;&#x4E86;&#x6E2C;&#x8A66;&#x65E5;&#x8A8C;, &#x751F;&#x6210;&#x4E00;&#x500B;HTML&#x5831;&#x544A;, &#x7136;&#x5F8C;&#x5728;&#x700F;&#x89BD;&#x5668;&#x4E2D;&#x6253;&#x958B;(&#x5716;11.3).</p>
<pre><code>$ go tool cover -html=c.out
</code></pre><p><img src="../images/ch11-03.png" alt=""></p>
<p>&#x7DA0;&#x8272;&#x7684;&#x4EE3;&#x78BC;&#x584A;&#x88AB;&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x5230;&#x4E86;, &#x7D05;&#x8272;&#x7684;&#x5247;&#x9336;&#x793A;&#x6C92;&#x6709;&#x88AB;&#x8986;&#x84CB;&#x5230;. &#x7232;&#x4E86;&#x6E05;&#x6670;&#x8D77;&#x898B;, &#x6211;&#x5011;&#x5C07;&#x7684;&#x80CC;&#x666F;&#x7D05;&#x8272;&#x6587;&#x672C;&#x7684;&#x80CC;&#x666F;&#x8A2D;&#x7F6E;&#x6210;&#x4E86;&#x9670;&#x5F71;&#x6548;&#x679C;. &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x99AC;&#x4E0A;&#x767C;&#x73FE; unary &#x64CD;&#x4F5C;&#x7684; Eval &#x65B9;&#x6CD5;&#x4F75;&#x6C92;&#x6709;&#x88AB;&#x57F7;&#x884C;&#x5230;. &#x5982;&#x679C;&#x6211;&#x5011;&#x91DD;&#x5C0D;&#x9019;&#x90E8;&#x5206;&#x672A;&#x88AB;&#x8986;&#x84CB;&#x7684;&#x4EE3;&#x78BC;&#x6DFB;&#x52A0;&#x4E0B;&#x9EAB;&#x7684;&#x6E2C;&#x8A66;, &#x7136;&#x5F8C;&#x91CD;&#x65B0;&#x904B;&#x884C;&#x4E0A;&#x9EAB;&#x7684;&#x547D;&#x4EE4;, &#x90A3;&#x9EBD;&#x6211;&#x5011;&#x5C07;&#x6703;&#x770B;&#x5230;&#x90A3;&#x500B;&#x7D05;&#x8272;&#x90E8;&#x5206;&#x7684;&#x4EE3;&#x78BC;&#x4E5F;&#x8B8A;&#x6210;&#x7DA0;&#x8272;&#x4E86;:</p>
<pre><code>{&quot;-x * -x&quot;, eval.Env{&quot;x&quot;: 2}, &quot;4&quot;}
</code></pre><p>&#x4E0D;&#x904E;&#x5169;&#x500B; panic &#x8A9E;&#x53E5;&#x4F9D;&#x7136;&#x662F;&#x7D05;&#x8272;&#x7684;. &#x9019;&#x662F;&#x6C92;&#x6709;&#x554F;&#x984C;&#x7684;, &#x56E0;&#x7232;&#x9019;&#x5169;&#x500B;&#x8A9E;&#x53E5;&#x4F75;&#x4E0D;&#x6703;&#x88AB;&#x57F7;&#x884C;&#x5230;.</p>
<p>&#x5BE6;&#x73FE; 100% &#x7684;&#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;&#x807D;&#x8D77;&#x4F86;&#x5F88;&#x597D;, &#x4F46;&#x662F;&#x5728;&#x5177;&#x9AD4;&#x5BE6;&#x8E10;&#x4E2D;&#x901A;&#x5E38;&#x662F;&#x4E0D;&#x53EF;&#x884C;&#x7684;, &#x4E5F;&#x4E0D;&#x662F;&#x503C;&#x5F97;&#x63A8;&#x85A6;&#x7684;&#x505A;&#x6CD5;. &#x56E0;&#x7232;&#x90A3;&#x96BB;&#x80FD;&#x8AAC;&#x660E;&#x4EE3;&#x78BC;&#x88AB;&#x57F7;&#x884C;&#x904E;&#x800C;&#x5DF2;, &#x4F75;&#x4E0D;&#x610F;&#x5473;&#x7740;&#x4EE3;&#x78BC;&#x662F;&#x6C92;&#x6709;BUG&#x7684;; &#x56E0;&#x7232;&#x5C0D;&#x65BC;&#x908F;&#x8F2F;&#x5FA9;&#x96DC;&#x7684;&#x8A9E;&#x53E5;&#x9700;&#x8981;&#x91DD;&#x5C0D;&#x4E0D;&#x8855;&#x7684;&#x8F38;&#x5165;&#x57F7;&#x884C;&#x591A;&#x6B21;. &#x6709;&#x4E00;&#x4E9B;&#x8A9E;&#x53E5;, &#x4F8B;&#x5982;&#x4E0A;&#x9EAB;&#x7684; panic &#x8A9E;&#x53E5;&#x5247;&#x6C38;&#x9060;&#x90FD;&#x4E0D;&#x6703;&#x88AB;&#x57F7;&#x884C;&#x5230;. &#x53E6;&#x5916;, &#x9084;&#x6709;&#x4E00;&#x4E9B;&#x96B1;&#x6666;&#x7684;&#x932F;&#x8AA4;&#x5728;&#x73FE;&#x5BE6;&#x4E2D;&#x5F88;&#x5C11;&#x9047;&#x5230;&#x4E5F;&#x5F88;&#x96E3;&#x7DE8;&#x5BEB;&#x5C0D;&#x61C9;&#x7684;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;. &#x6E2C;&#x8A66;&#x5F9E;&#x672C;&#x8CEA;&#x4E0A;&#x4F86;&#x8AAC;&#x662F;&#x4E00;&#x500B;&#x6BD4;&#x8F03;&#x52D9;&#x5BE6;&#x7684;&#x5DE5;&#x4F5C;, &#x7DE8;&#x5BEB;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;&#x548C;&#x7DE8;&#x5BEB;&#x61C9;&#x7528;&#x4EE3;&#x78BC;&#x7684;&#x6210;&#x672C;&#x5C0D;&#x6BD4;&#x662F;&#x9700;&#x8981;&#x8003;&#x616E;&#x7684;. &#x6E2C;&#x8A66;&#x8986;&#x84CB;&#x7387;&#x5DE5;&#x5177;&#x53EF;&#x4EE5;&#x5E6B;&#x52A9;&#x6211;&#x5011;&#x5FEB;&#x901F;&#x8B58;&#x5F46;&#x6E2C;&#x8A66;&#x8584;&#x5F31;&#x7684;&#x5730;&#x65B9;, &#x4F46;&#x662F;&#x8A2D;&#x8A08;&#x597D;&#x7684;&#x6E2C;&#x8A66;&#x7528;&#x4F8B;&#x548C;&#x7DE8;&#x5BEB;&#x61C9;&#x7528;&#x4EE3;&#x78BC;&#x4E00;&#x6A23;&#x9700;&#x8981;&#x56B4;&#x5BC6;&#x7684;&#x601D;&#x8003;.</p>
</section>

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11.4" data-chapter-title="基準測試" data-filepath="ch11/ch11-04.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11.4" data-chapter-title="基準測試" data-filepath="ch11/ch11-04.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">
@@ -2060,7 +2060,72 @@
<section class="normal" id="section-">
<h2 id="114-&#x57FA;&#x6E96;&#x6E2C;&#x8A66;">11.4. &#x57FA;&#x6E96;&#x6E2C;&#x8A66;</h2>
<p>TODO</p>
<p>&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x662F;&#x6E2C;&#x91CF;&#x4E00;&#x7B87;&#x7A0B;&#x5E8F;&#x5728;&#x56FA;&#x5B9A;&#x5DE5;&#x4F5C;&#x8CA0;&#x8F09;&#x4E0B;&#x7684;&#x6027;&#x80FD;. &#x5728;Go&#x8A9E;&#x8A00;&#x4E2D;, &#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x548C;&#x666E;&#x901A;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x985E;&#x4F3C;, &#x4F46;&#x662F;&#x4EE5;Benchmark&#x7232;&#x524D;&#x7DB4;&#x540D;, &#x4F75;&#x4E14;&#x5E36;&#x6709;&#x4E00;&#x7B87; <code>*testing.B</code> &#x985E;&#x578B;&#x7684;&#x53C3;&#x6578;; <code>*testing.B</code> &#x9664;&#x4E86;&#x63D0;&#x4F9B;&#x548C; <code>*testing.T</code> &#x985E;&#x4F3C;&#x7684;&#x65B9;&#x6CD5;, &#x9084;&#x6709;&#x984D;&#x5916;&#x4E00;&#x4E9B;&#x548C;&#x6027;&#x80FD;&#x6E2C;&#x91CF;&#x76F8;&#x95DC;&#x7684;&#x65B9;&#x6CD5;. &#x5B83;&#x9084;&#x63D0;&#x4F9B;&#x4E86;&#x4E00;&#x7B87;&#x6574;&#x6578;N, &#x7528;&#x65BC;&#x6307;&#x5B9A;&#x64CD;&#x4F5C;&#x57F7;&#x884C;&#x7684;&#x5FAA;&#x74B0;&#x6B21;&#x6578;.</p>
<p>&#x4E0B;&#x9EAB;&#x662F; IsPalindrome &#x51FD;&#x6578;&#x7684;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;, &#x5176;&#x4E2D;&#x5FAA;&#x74B0;&#x5C07;&#x57F7;&#x884C;N&#x6B21;.</p>
<pre><code class="lang-Go"><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;testing&quot;</span>
<span class="hljs-keyword">func</span> BenchmarkIsPalindrome(b *testing.B) {
<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; b.N; i++ {
IsPalindrome(<span class="hljs-string">&quot;A man, a plan, a canal: Panama&quot;</span>)
}
}
</code></pre>
<p>&#x6211;&#x5011;&#x7528;&#x4E0B;&#x9EAB;&#x7684;&#x547D;&#x4EE4;&#x904B;&#x884C;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;. &#x548C;&#x666E;&#x901A;&#x6E2C;&#x8A66;&#x4E0D;&#x8855;&#x7684;&#x662F;, &#x9ED8;&#x8A8D;&#x60C5;&#x6CC1;&#x4E0B;&#x4E0D;&#x904B;&#x884C;&#x4EFB;&#x4F55;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;. &#x6211;&#x5011;&#x9700;&#x8981;&#x901A;&#x904E; <code>-bench</code> &#x547D;&#x4EE4;&#x884C;&#x6A19;&#x8A8C;&#x53C3;&#x6578;&#x624B;&#x5DE5;&#x6307;&#x5B9A;&#x8981;&#x904B;&#x884C;&#x7684;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;. &#x8A72;&#x53C3;&#x6578;&#x662F;&#x4E00;&#x7B87;&#x6B63;&#x5247;&#x9336;&#x9054;&#x5F0F;, &#x7528;&#x65BC;&#x5339;&#x914D;&#x8981;&#x57F7;&#x884C;&#x7684;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x7684;&#x540D;&#x5B57;, &#x9ED8;&#x8A8D;&#x503C;&#x662F;&#x7A7A;&#x7684;. &#x5176;&#x4E2D; &#x2018;&#x2018;.&#x2019;&#x2019; &#x6A21;&#x5F0F;&#x5C07;&#x53EF;&#x4EE5;&#x5339;&#x914D;&#x6240;&#x6709;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;, &#x4F46;&#x662F;&#x9019;&#x88E1;&#x7E3D;&#x5171;&#x96BB;&#x6709;&#x4E00;&#x7B87;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;, &#x56E0;&#x6B64; &#x548C; <code>-bench=IsPalindrome</code> &#x53C3;&#x6578;&#x662F;&#x7B49;&#x50F9;&#x7684;&#x6548;&#x679C;.</p>
<pre><code>$ cd $GOPATH/src/gopl.io/ch11/word2
$ go test -bench=.
PASS
BenchmarkIsPalindrome-8 1000000 1035 ns/op
ok gopl.io/ch11/word2 2.179s
</code></pre><p>&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x540D;&#x7684;&#x6578;&#x5B57;&#x5F8C;&#x7DB4;&#x90E8;&#x5206;, &#x9019;&#x88E1;&#x662F;8, &#x9336;&#x793A;&#x904B;&#x884C;&#x6642;&#x5C0D;&#x61C9;&#x7684; GOMAXPROCS &#x7684;&#x503C;, &#x9019;&#x5C0D;&#x65BC;&#x4E00;&#x4E9B;&#x548C;&#x4F75;&#x767C;&#x76F8;&#x95DC;&#x7684;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x662F;&#x91CD;&#x8981;&#x7684;&#x4FE1;&#x606F;.</p>
<p>&#x5831;&#x544A;&#x986F;&#x793A;&#x6BCF;&#x6B21;&#x8ABF;&#x7528; IsPalindrome &#x51FD;&#x6578;&#x82B1;&#x8CBB; 1.035&#x5FAE;&#x79D2;, &#x662F;&#x57F7;&#x884C; 1,000,000 &#x6B21;&#x7684;&#x5E73;&#x5747;&#x6642;&#x9593;. &#x56E0;&#x7232;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x9A45;&#x52D5;&#x5668;&#x4F75;&#x4E0D;&#x77E5;&#x9053;&#x6BCF;&#x7B87;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x904B;&#x884C;&#x6240;&#x82B1;&#x7684;&#x6642;&#x5019;, &#x5B83;&#x6703;&#x5617;&#x8A66;&#x5728;&#x771E;&#x6B63;&#x904B;&#x884C;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x524D;&#x5148;&#x5617;&#x8A66;&#x7528;&#x8F03;&#x5C0F;&#x7684; N &#x904B;&#x884C;&#x6E2C;&#x8A66;&#x4F86;&#x4F30;&#x7B97;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x6240;&#x9700;&#x8981;&#x7684;&#x6642;&#x9593;, &#x7136;&#x5F8C;&#x63A8;&#x65B7;&#x4E00;&#x7B87;&#x8F03;&#x5927;&#x7684;&#x6642;&#x9593;&#x4FDD;&#x8A3C;&#x7A69;&#x5B9A;&#x7684;&#x6E2C;&#x91CF;&#x7D50;&#x679C;.</p>
<p>&#x5FAA;&#x74B0;&#x5728;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x5167;&#x5BE6;&#x73FE;, &#x800C;&#x4E0D;&#x662F;&#x653E;&#x5728;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x6846;&#x67B6;&#x5167;&#x5BE6;&#x73FE;, &#x9019;&#x6A23;&#x53EF;&#x4EE5;&#x8B93;&#x6BCF;&#x7B87;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x6709;&#x6A5F;&#x6703;&#x5728;&#x5FAA;&#x74B0;&#x555F;&#x52D5;&#x524D;&#x57F7;&#x884C;&#x521D;&#x59CB;&#x5316;&#x4EE3;&#x78BC;, &#x9019;&#x6A23;&#x4F75;&#x4E0D;&#x6703;&#x986F;&#x8457;&#x5F71;&#x97FF;&#x6BCF;&#x6B21;&#x8FED;&#x4EE3;&#x7684;&#x5E73;&#x5747;&#x904B;&#x884C;&#x6642;&#x9593;. &#x5982;&#x679C;&#x9084;&#x662F;&#x64D4;&#x5FC3;&#x521D;&#x59CB;&#x5316;&#x4EE3;&#x78BC;&#x90E8;&#x5206;&#x5C0D;&#x6E2C;&#x91CF;&#x6642;&#x9593;&#x5E36;&#x4F86;&#x4E7E;&#x64FE;, &#x90A3;&#x9EBC;&#x53EF;&#x4EE5;&#x901A;&#x904E; testing.B &#x53C3;&#x6578;&#x7684;&#x65B9;&#x6CD5;&#x4F86;&#x81E8;&#x6642;&#x95DC;&#x9589;&#x6216;&#x91CD;&#x7F6E;&#x8A08;&#x6642;&#x5668;, &#x4E0D;&#x904E;&#x9019;&#x4E9B;&#x4E00;&#x822C;&#x5F88;&#x5C11;&#x6703;&#x7528;&#x5230;.</p>
<p>&#x73FE;&#x5728;&#x6211;&#x5011;&#x6709;&#x4E86;&#x4E00;&#x7B87;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x548C;&#x666E;&#x901A;&#x6E2C;&#x8A66;, &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x5F88;&#x5BB9;&#x6613;&#x6E2C;&#x8A66;&#x65B0;&#x7684;&#x8B93;&#x7A0B;&#x5E8F;&#x904B;&#x884C;&#x66F4;&#x5FEB;&#x7684;&#x60F3;&#x6CD5;. &#x4E5F;&#x8A31;&#x6700;&#x660E;&#x986F;&#x7684;&#x512A;&#x5316;&#x662F;&#x5728; IsPalindrome &#x51FD;&#x6578;&#x4E2D;&#x7B2C;&#x4E8C;&#x7B87;&#x5FAA;&#x74B0;&#x7684;&#x505C;&#x6B62;&#x6AA2;&#x67FB;, &#x9019;&#x6A23;&#x53EF;&#x4EE5;&#x907F;&#x514D;&#x6BCF;&#x7B87;&#x6BD4;&#x8F03;&#x90FD;&#x505A;&#x5169;&#x6B21;:</p>
<pre><code class="lang-Go">n := <span class="hljs-built_in">len</span>(letters)/<span class="hljs-number">2</span>
<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; n; i++ {
<span class="hljs-keyword">if</span> letters[i] != letters[<span class="hljs-built_in">len</span>(letters)-<span class="hljs-number">1</span>-i] {
<span class="hljs-keyword">return</span> <span class="hljs-constant">false</span>
}
}
<span class="hljs-keyword">return</span> <span class="hljs-constant">true</span>
</code></pre>
<p>&#x4E0D;&#x904E;&#x5F88;&#x591A;&#x60C5;&#x6CC1;&#x4E0B;, &#x4E00;&#x7B87;&#x660E;&#x986F;&#x7684;&#x512A;&#x5316;&#x4F75;&#x4E0D;&#x4E00;&#x5B9A;&#x5C31;&#x80FD;&#x4EE3;&#x78BC;&#x9810;&#x671F;&#x7684;&#x6548;&#x679C;. &#x9019;&#x7B87;&#x6539;&#x9032;&#x5728;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x4E2D;&#x503C;&#x5E36;&#x4F86;&#x4E86; 4% &#x7684;&#x6027;&#x80FD;&#x63D0;&#x6607;.</p>
<pre><code>$ go test -bench=.
PASS
BenchmarkIsPalindrome-8 1000000 992 ns/op
ok gopl.io/ch11/word2 2.093s
</code></pre><p>&#x53E6;&#x4E00;&#x7B87;&#x6539;&#x9032;&#x60F3;&#x6CD5;&#x662F;&#x5728;&#x958B;&#x59CB;&#x7232;&#x6BCF;&#x7B87;&#x5B57;&#x7B26;&#x9810;&#x5148;&#x5206;&#x914D;&#x4E00;&#x7B87;&#x8DB3;&#x5920;&#x5927;&#x7684;&#x6578;&#x7D44;, &#x9019;&#x6A23;&#x5C31;&#x53EF;&#x4EE5;&#x907F;&#x514D;&#x5728; append &#x8ABF;&#x7528;&#x6642;&#x53EF;&#x80FD;&#x6703;&#x5C0E;&#x7DFB;&#x5167;&#x5B58;&#x7684;&#x591A;&#x6B21;&#x91CD;&#x65B0;&#x5206;&#x914D;. &#x8072;&#x660E;&#x4E00;&#x7B87; letters &#x6578;&#x7D44;&#x8B8A;&#x91CF;, &#x4F75;&#x6307;&#x5B9A;&#x95A4;&#x9069;&#x7684;&#x5927;&#x5C0F;, &#x50CF;&#x9019;&#x6A23;,</p>
<pre><code class="lang-Go">letters := <span class="hljs-built_in">make</span>([]<span class="hljs-typename">rune</span>, <span class="hljs-number">0</span>, <span class="hljs-built_in">len</span>(s))
<span class="hljs-keyword">for</span> _, r := <span class="hljs-keyword">range</span> s {
<span class="hljs-keyword">if</span> unicode.IsLetter(r) {
letters = <span class="hljs-built_in">append</span>(letters, unicode.ToLower(r))
}
}
</code></pre>
<p>&#x9019;&#x7B87;&#x6539;&#x9032;&#x63D0;&#x6607;&#x6027;&#x80FD;&#x7D04; 35%, &#x5831;&#x544A;&#x7D50;&#x679C;&#x662F;&#x57FA;&#x65BC; 2,000,000 &#x6B21;&#x8FED;&#x4EE3;&#x7684;&#x5E73;&#x5747;&#x904B;&#x884C;&#x6642;&#x9593;&#x7D71;&#x8A08;.</p>
<pre><code>$ go test -bench=.
PASS
BenchmarkIsPalindrome-8 2000000 697 ns/op
ok gopl.io/ch11/word2 1.468s
</code></pre><p>&#x5982;&#x9019;&#x7B87;&#x4F8B;&#x5B50;&#x6240;&#x793A;, &#x5FEB;&#x7684;&#x7A0B;&#x5E8F;&#x5F80;&#x5F80;&#x662F;&#x6709;&#x5F88;&#x5C11;&#x7684;&#x5167;&#x5B58;&#x5206;&#x914D;. <code>-benchmem</code> &#x547D;&#x4EE4;&#x884C;&#x6A19;&#x8A8C;&#x53C3;&#x6578;&#x5C07;&#x5728;&#x5831;&#x544A;&#x4E2D;&#x5305;&#x542B;&#x5167;&#x5B58;&#x7684;&#x5206;&#x914D;&#x6578;&#x64DA;&#x7D71;&#x8A08;. &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x6BD4;&#x8F03;&#x512A;&#x5316;&#x524D;&#x5F8C;&#x5167;&#x5B58;&#x7684;&#x5206;&#x914D;&#x60C5;&#x6CC1;:</p>
<pre><code>$ go test -bench=. -benchmem
PASS
BenchmarkIsPalindrome 1000000 1026 ns/op 304 B/op 4 allocs/op
</code></pre><p>&#x9019;&#x662F;&#x512A;&#x5316;&#x4E4B;&#x5F8C;&#x7684;&#x7D50;&#x679C;:</p>
<pre><code>$ go test -bench=. -benchmem
PASS
BenchmarkIsPalindrome 2000000 807 ns/op 128 B/op 1 allocs/op
</code></pre><p>&#x4E00;&#x6B21;&#x5167;&#x5B58;&#x5206;&#x914D;&#x4EE3;&#x66FF;&#x591A;&#x6B21;&#x7684;&#x5167;&#x5B58;&#x5206;&#x914D;&#x7BC0;&#x7701;&#x4E86;75%&#x7684;&#x5206;&#x914D;&#x8ABF;&#x7528;&#x6B21;&#x6578;&#x548C;&#x6E1B;&#x5C11;&#x8FD1;&#x4E00;&#x534A;&#x7684;&#x5167;&#x5B58;&#x9700;&#x6C42;.</p>
<p>&#x9019;&#x7B87;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x544A;&#x8A34;&#x6211;&#x5011;&#x6240;&#x9700;&#x7684;&#x7D55;&#x5C0D;&#x6642;&#x9593;&#x4F9D;&#x8CF4;&#x7D66;&#x5B9A;&#x7684;&#x5177;&#x9AD4;&#x64CD;&#x4F5C;, &#x5169;&#x7B87;&#x4E0D;&#x8855;&#x7684;&#x64CD;&#x4F5C;&#x6240;&#x9700;&#x6642;&#x9593;&#x7684;&#x5DEE;&#x7570;&#x4E5F;&#x662F;&#x548C;&#x4E0D;&#x8855;&#x74B0;&#x5883;&#x76F8;&#x95DC;&#x7684;. &#x4F8B;&#x5982;, &#x5982;&#x679C;&#x4E00;&#x7B87;&#x51FD;&#x6578;&#x9700;&#x8981; 1ms &#x8655;&#x7406; 1,000 &#x7B87;&#x5143;&#x7D20;, &#x90A3;&#x9EBC;&#x8655;&#x7406; 10000 &#x6216; 1&#x767E;&#x842C; &#x5C07;&#x9700;&#x8981;&#x591A;&#x5C11;&#x6642;&#x9593;&#x5462;? &#x9019;&#x6A23;&#x7684;&#x6BD4;&#x8F03;&#x63ED;&#x793A;&#x4E86;&#x6F38;&#x8FD1;&#x589E;&#x9577;&#x51FD;&#x6578;&#x7684;&#x904B;&#x884C;&#x6642;&#x9593;. &#x53E6;&#x4E00;&#x7B87;&#x4F8B;&#x5B50;: I/O &#x7DE9;&#x5B58;&#x8A72;&#x8A2D;&#x7F6E;&#x7232;&#x591A;&#x5927;&#x5462;? &#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x53EF;&#x4EE5;&#x5E6B;&#x52A9;&#x6211;&#x5011;&#x9078;&#x64C7;&#x8F03;&#x5C0F;&#x7684;&#x7DE9;&#x5B58;&#x4F46;&#x80FD;&#x5E36;&#x4F86;&#x6EFF;&#x610F;&#x7684;&#x6027;&#x80FD;. &#x7B2C;&#x4E09;&#x7B87;&#x4F8B;&#x5B50;: &#x5C0D;&#x65BC;&#x4E00;&#x7B87;&#x78BA;&#x5B9A;&#x7684;&#x5DE5;&#x4F5C;&#x90A3;&#x7A2E;&#x7B97;&#x6CD5;&#x66F4;&#x597D;? &#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x53EF;&#x4EE5;&#x8A55;&#x4F30;&#x5169;&#x7A2E;&#x4E0D;&#x8855;&#x7B97;&#x6CD5;&#x5C0D;&#x65BC;&#x76F8;&#x8855;&#x7684;&#x8F38;&#x5165;&#x5728;&#x4E0D;&#x8855;&#x7684;&#x5834;&#x666F;&#x548C;&#x8CA0;&#x8F09;&#x4E0B;&#x7684;&#x512A;&#x7F3A;&#x9EDE;.</p>
<p>&#x6BD4;&#x8F03;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x90FD;&#x662F;&#x7D50;&#x69CB;&#x985E;&#x4F3C;&#x7684;&#x4EE3;&#x78BC;. &#x5B83;&#x5011;&#x901A;&#x5E38;&#x662F;&#x5BC0;&#x7528;&#x4E00;&#x7B87;&#x53C3;&#x6578;&#x7684;&#x51FD;&#x6578;, &#x5F9E;&#x5E7E;&#x7B87;&#x6A19;&#x8A8C;&#x7684;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x51FD;&#x6578;&#x5165;&#x53E3;&#x8ABF;&#x7528;, &#x5C31;&#x50CF;&#x9019;&#x6A23;:</p>
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> benchmark(b *testing.B, size <span class="hljs-typename">int</span>) { <span class="hljs-comment">/* ... */</span> }
<span class="hljs-keyword">func</span> Benchmark10(b *testing.B) { benchmark(b, <span class="hljs-number">10</span>) }
<span class="hljs-keyword">func</span> Benchmark100(b *testing.B) { benchmark(b, <span class="hljs-number">100</span>) }
<span class="hljs-keyword">func</span> Benchmark1000(b *testing.B) { benchmark(b, <span class="hljs-number">1000</span>) }
</code></pre>
<p>&#x901A;&#x904E;&#x51FD;&#x6578;&#x53C3;&#x6578;&#x4F86;&#x6307;&#x5B9A;&#x8F38;&#x5165;&#x7684;&#x5927;&#x5C0F;, &#x4F46;&#x662F;&#x53C3;&#x6578;&#x8B8A;&#x91CF;&#x5C0D;&#x65BC;&#x6BCF;&#x7B87;&#x5177;&#x9AD4;&#x7684;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x90FD;&#x662F;&#x56FA;&#x5B9A;&#x7684;. &#x8981;&#x907F;&#x514D;&#x76F4;&#x63A5;&#x8129;&#x6539; b.N &#x4F86;&#x63A7;&#x88FD;&#x8F38;&#x5165;&#x7684;&#x5927;&#x5C0F;. &#x9664;&#x975E;&#x4F60;&#x5C07;&#x5B83;&#x4F5C;&#x7232;&#x4E00;&#x7B87;&#x56FA;&#x5B9A;&#x5927;&#x5C0F;&#x7684;&#x8FED;&#x4EE3;&#x8A08;&#x7B97;&#x8F38;&#x5165;, &#x5426;&#x5247;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x7684;&#x7D50;&#x679C;&#x5C07;&#x6BEB;&#x7121;&#x610F;&#x7FA9;.</p>
<p>&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x5C0D;&#x65BC;&#x7DE8;&#x5BEB;&#x4EE3;&#x78BC;&#x662F;&#x5F88;&#x6709;&#x5E6B;&#x52A9;&#x7684;, &#x4F46;&#x662F;&#x537D;&#x4F7F;&#x5DE5;&#x4F5C;&#x5B8C;&#x6210;&#x4E86;&#x61C9;&#x61C9;&#x5679;&#x4FDD;&#x5B58;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x4EE3;&#x78BC;. &#x56E0;&#x7232;&#x96A8;&#x7740;&#x9805;&#x76EE;&#x7684;&#x767C;&#x5C55;, &#x6216;&#x8005;&#x662F;&#x8F38;&#x5165;&#x7684;&#x589E;&#x52A0;, &#x6216;&#x8005;&#x662F;&#x90E8;&#x7F72;&#x5230;&#x65B0;&#x7684;&#x64CD;&#x4F5C;&#x7E6B;&#x7D71;&#x6216;&#x4E0D;&#x8855;&#x7684;&#x8655;&#x7406;&#x5668;, &#x6211;&#x5011;&#x53EF;&#x4EE5;&#x518D;&#x6B21;&#x7528;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x4F86;&#x5E6B;&#x52A9;&#x6211;&#x5011;&#x6539;&#x9032;&#x8A2D;&#x8A08;.</p>
<p><strong>&#x7DF4;&#x7FD2; 11.6:</strong> &#x7232; 2.6.2&#x7BC0; &#x7684; &#x7DF4;&#x7FD2; 2.4 &#x548C; &#x7DF4;&#x7FD2; 2.5 &#x7684; PopCount &#x51FD;&#x6578;&#x7DE8;&#x5BEB;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;. &#x770B;&#x770B;&#x57FA;&#x65BC;&#x9336;&#x683C;&#x7B97;&#x6CD5;&#x5728;&#x4E0D;&#x8855;&#x60C5;&#x6CC1;&#x4E0B;&#x7684;&#x6027;&#x80FD;.</p>
<p><strong>&#x7DF4;&#x7FD2; 11.7:</strong> &#x7232; *IntSet (&#xA7;6.5) &#x7684; Add, UnionWith &#x548C; &#x5176;&#x4ED6;&#x65B9;&#x6CD5;&#x7DE8;&#x5BEB;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;, &#x4F7F;&#x7528;&#x5927;&#x91CF;&#x96A8;&#x6A5F;&#x9F63;&#x5165;. &#x4F60;&#x53EF;&#x4EE5;&#x8B93;&#x9019;&#x4E9B;&#x65B9;&#x6CD5;&#x8DD1;&#x591A;&#x5FEB;? &#x9078;&#x64C7;&#x5B57;&#x7684;&#x5927;&#x5C0F;&#x5C0D;&#x65BC;&#x6027;&#x80FD;&#x7684;&#x5F71;&#x97FF;&#x5982;&#x4F55;? IntSet &#x548C;&#x57FA;&#x65BC;&#x5167;&#x5EFA; map &#x7684;&#x5BE6;&#x73FE;&#x76F8;&#x6BD4;&#x6709;&#x591A;&#x5FEB;?</p>
</section>

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11.5" data-chapter-title="剖析" data-filepath="ch11/ch11-05.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11.5" data-chapter-title="剖析" data-filepath="ch11/ch11-05.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">
@@ -2060,7 +2060,50 @@
<section class="normal" id="section-">
<h2 id="115-&#x5256;&#x6790;">11.5. &#x5256;&#x6790;</h2>
<p>TODO</p>
<p>&#x6E2C;&#x91CF;&#x57FA;&#x6E96;&#x5C0D;&#x65BC;&#x8861;&#x91CF;&#x7279;&#x5B9A;&#x64CD;&#x4F5C;&#x7684;&#x6027;&#x80FD;&#x662F;&#x6709;&#x5E6B;&#x52A9;&#x7684;, &#x4F46;&#x662F;, &#x5679;&#x6211;&#x5011;&#x8996;&#x5716;&#x8B93;&#x7A0B;&#x5E8F;&#x8DD1;&#x7684;&#x66F4;&#x5FEB;&#x7684;&#x6642;&#x5019;, &#x6211;&#x5011;&#x901A;&#x5E38;&#x4F75;&#x4E0D;&#x77E5;&#x9053;&#x5F9E;&#x54EA;&#x88E1;&#x958B;&#x59CB;&#x512A;&#x5316;. &#x6BCF;&#x500B;&#x78BC;&#x8FB2;&#x90FD;&#x61C9;&#x8A72;&#x77E5;&#x9053; Donald Knuth &#x5728;1974&#x5E74;&#x7684; &#x2018;&#x2018;Structured Programming with go to Statements&#x2019;&#x2019; &#x4E0A;&#x6240;&#x8AAC;&#x7684;&#x683C;&#x8A00;. &#x96D6;&#x7136;&#x7D93;&#x5E38;&#x88AB;&#x89E3;&#x8B80;&#x7232;&#x4E0D;&#x91CD;&#x8996;&#x6027;&#x80FD;&#x7684;&#x610F;&#x601D;, &#x4F46;&#x662F;&#x5F9E;&#x539F;&#x6587;&#x6211;&#x5011;&#x53EF;&#x4EE5;&#x770B;&#x5230;&#x4E0D;&#x8855;&#x7684;&#x542B;&#x7FA9;:</p>
<blockquote>
<p>&#x6BEB;&#x7121;&#x7591;&#x554F;, &#x6548;&#x7387;&#x6703;&#x5C0E;&#x7DFB;&#x5404;&#x7A2E;&#x6FEB;&#x7528;. &#x7A0B;&#x5E8F;&#x54E1;&#x9700;&#x8981;&#x6D6A;&#x8CBB;&#x5927;&#x91CF;&#x7684;&#x6642;&#x9593;&#x601D;&#x8003;, &#x6216;&#x8005;&#x64D4;&#x5FC3;, &#x88AB;&#x90E8;&#x5206;&#x7A0B;&#x5E8F;&#x7684;&#x901F;&#x5EA6;&#x6240;&#x4E7E;&#x64FE;, &#x5BE6;&#x969B;&#x4E0A;&#x9019;&#x4E9B;&#x5690;&#x8A66;&#x63D0;&#x6607;&#x6548;&#x7387;&#x7684;&#x884C;&#x7232;&#x53EF;&#x80FD;&#x7523;&#x751F;&#x5F37;&#x70C8;&#x7684;&#x8CA0;&#x9EAB;&#x5F71;&#x97FF;, &#x7279;&#x5F46;&#x662F;&#x5679;&#x8ABF;&#x8A66;&#x548C;&#x7DAD;&#x8B77;&#x7684;&#x6642;&#x5019;. &#x6211;&#x5011;&#x4E0D;&#x61C9;&#x8A72;&#x904E;&#x5EA6;&#x7CFE;&#x7D50;&#x65BC;&#x7D30;&#x7BC0;&#x7684;&#x512A;&#x5316;, &#x61C9;&#x8A72;&#x8AAC;&#x7D04;97%&#x7684;&#x5834;&#x666F;: &#x904E;&#x65E9;&#x7684;&#x512A;&#x5316;&#x662F;&#x842C;&#x60E1;&#x4E4B;&#x6E90;.</p>
<p>&#x6211;&#x5011;&#x5679;&#x7136;&#x4E0D;&#x61C9;&#x8A72;&#x653E;&#x68C4;&#x90A3;&#x95DC;&#x9375;&#x7684;3%&#x7684;&#x6A5F;&#x6703;. &#x4E00;&#x500B;&#x597D;&#x7684;&#x7A0B;&#x5E8F;&#x54E1;&#x4E0D;&#x6703;&#x56E0;&#x7232;&#x9019;&#x500B;&#x7406;&#x7531;&#x800C;&#x6EFF;&#x8DB3;, &#x4ED6;&#x5011;&#x6703;&#x660E;&#x667A;&#x5730;&#x89C0;&#x5BDF;&#x548C;&#x8B58;&#x5F46;&#x54EA;&#x4E9B;&#x662F;&#x95DC;&#x9375;&#x7684;&#x4EE3;&#x78BC;; &#x4F46;&#x662F;&#x96BB;&#x6709;&#x5728;&#x95DC;&#x9375;&#x4EE3;&#x78BC;&#x5DF2;&#x7D93;&#x88AB;&#x78BA;&#x8A8D;&#x7684;&#x524D;&#x63D0;&#x4E0B;&#x7E94;&#x6703;&#x9032;&#x884C;&#x512A;&#x5316;. &#x5C0D;&#x65BC;&#x5224;&#x65B7;&#x54EA;&#x4E9B;&#x90E8;&#x5206;&#x662F;&#x95DC;&#x9375;&#x4EE3;&#x78BC;&#x662F;&#x7D93;&#x5E38;&#x5BB9;&#x6613;&#x72AF;&#x7D93;&#x9A57;&#x6027;&#x932F;&#x8AA4;&#x7684;&#x5730;&#x65B9;, &#x56E0;&#x6B64;&#x7A0B;&#x5E8F;&#x54E1;&#x666E;&#x901A;&#x4F7F;&#x7528;&#x7684;&#x6E2C;&#x91CF;&#x5DE5;&#x5177;, &#x4F7F;&#x5F97;&#x4ED6;&#x5011;&#x7684;&#x76F4;&#x89BA;&#x5F88;&#x4E0D;&#x9760;&#x8B5C;.</p>
</blockquote>
<p>&#x5679;&#x6211;&#x5011;&#x60F3;&#x4ED4;&#x7D30;&#x89C0;&#x5BDF;&#x6211;&#x5011;&#x7A0B;&#x5E8F;&#x7684;&#x904B;&#x884C;&#x901F;&#x5EA6;&#x7684;&#x6642;&#x5019;, &#x6700;&#x597D;&#x7684;&#x6280;&#x8853;&#x662F;&#x5982;&#x4F55;&#x8B58;&#x5F46;&#x95DC;&#x9375;&#x4EE3;&#x78BC;. &#x81EA;&#x52D5;&#x5316;&#x7684;&#x5256;&#x6790;&#x6280;&#x8853;&#x662F;&#x57FA;&#x65BC;&#x7A0B;&#x5E8F;&#x57F7;&#x884C;&#x671F;&#x9593;&#x4E00;&#x4E9B;&#x62BD;&#x6A23;&#x6578;&#x64DA;, &#x7136;&#x5F8C;&#x63A8;&#x65B7;&#x5F8C;&#x9EAB;&#x7684;&#x57F7;&#x884C;&#x72C0;&#x614B;; &#x6700;&#x7D42;&#x7523;&#x751F;&#x4E00;&#x500B;&#x904B;&#x884C;&#x6642;&#x9593;&#x7684;&#x7D71;&#x8A08;&#x6578;&#x64DA;&#x6587;&#x4EF6;.</p>
<p>Go&#x8A9E;&#x8A00;&#x652F;&#x6301;&#x591A;&#x7A2E;&#x985E;&#x578B;&#x7684;&#x5256;&#x6790;&#x6027;&#x80FD;&#x5206;&#x6790;, &#x6BCF;&#x4E00;&#x7A2E;&#x95DC;&#x8A3B;&#x4E0D;&#x8855;&#x7684;&#x65B9;&#x9EAB;, &#x4F46;&#x5B83;&#x5011;&#x90FD;&#x6D89;&#x53CA;&#x5230;&#x6BCF;&#x500B;&#x5BC0;&#x6A23;&#x8A18;&#x5F54;&#x7684;&#x611F;&#x8208;&#x8DA3;&#x7684;&#x4E00;&#x7E6B;&#x5217;&#x4E8B;&#x4EF6;&#x6D88;&#x606F;, &#x6BCF;&#x500B;&#x4E8B;&#x4EF6;&#x90FD;&#x5305;&#x542B;&#x51FD;&#x6578;&#x8ABF;&#x7528;&#x6642;&#x51FD;&#x6578;&#x8ABF;&#x7528;&#x5806;&#x68E7;&#x7684;&#x4FE1;&#x606F;. &#x5167;&#x5EFA;&#x7684; <code>go test</code> &#x5DE5;&#x5177;&#x5C0D;&#x5E7E;&#x7A2E;&#x5206;&#x6790;&#x65B9;&#x5F0F;&#x90FD;&#x63D0;&#x4F9B;&#x4E86;&#x652F;&#x6301;.</p>
<p>CPU&#x5206;&#x6790;&#x6587;&#x4EF6;&#x6A19;&#x8B58;&#x4E86;&#x51FD;&#x6578;&#x57F7;&#x884C;&#x6642;&#x6240;&#x9700;&#x8981;&#x7684;CPU&#x6642;&#x9593;. &#x5679;&#x524D;&#x904B;&#x884C;&#x7684;&#x7E6B;&#x7D71;&#x7DDA;&#x7A0B;&#x5728;&#x6BCF;&#x9694;&#x5E7E;&#x6BEB;&#x79D2;&#x90FD;&#x6703;&#x9047;&#x5230;&#x64CD;&#x4F5C;&#x7E6B;&#x7D71;&#x7684;&#x4E2D;&#x65B7;&#x4E8B;&#x4EF6;, &#x6BCF;&#x6B21;&#x4E2D;&#x65B7;&#x6642;&#x90FD;&#x6703;&#x8A18;&#x5F54;&#x4E00;&#x500B;&#x5206;&#x6790;&#x6587;&#x4EF6;&#x7136;&#x5F8C;&#x6062;&#x5FA9;&#x6B63;&#x5E38;&#x7684;&#x904B;&#x884C;.</p>
<p>&#x5806;&#x5206;&#x6790;&#x5247;&#x8A18;&#x5F54;&#x4E86;&#x7A0B;&#x5E8F;&#x7684;&#x5167;&#x5B58;&#x4F7F;&#x7528;&#x60C5;&#x6CC1;. &#x6BCF;&#x500B;&#x5167;&#x5B58;&#x5206;&#x914D;&#x64CD;&#x4F5C;&#x90FD;&#x6703;&#x89F8;&#x767C;&#x5167;&#x90E8;&#x5E73;&#x5747;&#x5167;&#x5B58;&#x5206;&#x914D;&#x4F8B;&#x7A0B;, &#x6BCF;&#x500B; 512KB &#x7684;&#x5167;&#x5B58;&#x7533;&#x8ACB;&#x90FD;&#x6703;&#x89F8;&#x767C;&#x4E00;&#x500B;&#x4E8B;&#x4EF6;.</p>
<p>&#x963B;&#x585E;&#x5206;&#x6790;&#x5247;&#x8A18;&#x5F54;&#x4E86;goroutine&#x6700;&#x5927;&#x7684;&#x963B;&#x585E;&#x64CD;&#x4F5C;, &#x4F8B;&#x5982;&#x7E6B;&#x7D71;&#x8ABF;&#x7528;, &#x7BA1;&#x9053;&#x767C;&#x9001;&#x548C;&#x63A5;&#x6536;, &#x9084;&#x6709;&#x7A6B;&#x53D6;&#x9396;&#x7B49;. &#x5206;&#x6790;&#x5EAB;&#x6703;&#x8A18;&#x5F54;&#x6BCF;&#x500B;goroutine&#x88AB;&#x963B;&#x585E;&#x6642;&#x7684;&#x76F8;&#x95DC;&#x64CD;&#x4F5C;.</p>
<p>&#x5728;&#x6E2C;&#x8A66;&#x74B0;&#x5883;&#x4E0B;&#x96BB;&#x9700;&#x8981;&#x4E00;&#x500B;&#x6A19;&#x8A8C;&#x8518;&#x6578;&#x5C31;&#x53EF;&#x4EE5;&#x751F;&#x6210;&#x5404;&#x7A2E;&#x5206;&#x6790;&#x6587;&#x4EF6;. &#x5679;&#x4E00;&#x6B21;&#x4F7F;&#x7528;&#x591A;&#x500B;&#x6A19;&#x8A8C;&#x8518;&#x6578;&#x6642;&#x9700;&#x8981;&#x5679;&#x5FC3;, &#x56E0;&#x7232;&#x5206;&#x6790;&#x64CD;&#x4F5C;&#x672C;&#x8EAB;&#x4E5F;&#x53EF;&#x80FD;&#x6703;&#x5F71;&#x50CF;&#x7A0B;&#x5E8F;&#x7684;&#x904B;&#x884C;.</p>
<pre><code>$ go test -cpuprofile=cpu.out
$ go test -blockprofile=block.out
$ go test -memprofile=mem.out
</code></pre><p>&#x5C0D;&#x65BC;&#x4E00;&#x4E9B;&#x975E;&#x6E2C;&#x8A66;&#x7A0B;&#x5E8F;&#x4E5F;&#x5F88;&#x5BB9;&#x6613;&#x652F;&#x6301;&#x5206;&#x6790;&#x7684;&#x7279;&#x6027;, &#x5177;&#x9AD4;&#x7684;&#x5BE6;&#x73FE;&#x65B9;&#x5F0F;&#x548C;&#x7A0B;&#x5E8F;&#x662F;&#x77ED;&#x6642;&#x9593;&#x904B;&#x884C;&#x7684;&#x5C0F;&#x5DE5;&#x5177;&#x9084;&#x662F;&#x9577;&#x6642;&#x9593;&#x904B;&#x884C;&#x7684;&#x670D;&#x52D9;&#x6703;&#x6709;&#x5F88;&#x5927;&#x4E0D;&#x8855;, &#x56E0;&#x6B64;Go&#x7684;runtim&#x904B;&#x884C;&#x6642;&#x5305;&#x63D0;&#x4F9B;&#x4E86;&#x7A0B;&#x5E8F;&#x904B;&#x884C;&#x6642;&#x63A7;&#x88FD;&#x5206;&#x6790;&#x7279;&#x6027;&#x7684;&#x63A5;&#x53E3;.</p>
<p>&#x4E00;&#x65E6;&#x6211;&#x5011;&#x5DF2;&#x7D93;&#x6536;&#x96C6;&#x5230;&#x4E86;&#x7528;&#x65BC;&#x5206;&#x6790;&#x7684;&#x5BC0;&#x6A23;&#x6578;&#x64DA;, &#x6211;&#x5011;&#x5C31;&#x53EF;&#x4EE5;&#x4F7F;&#x7528; pprof &#x64DA;&#x4F86;&#x5206;&#x6790;&#x9019;&#x4E9B;&#x6578;&#x64DA;. &#x9019;&#x662F;Go&#x5DE5;&#x5177;&#x7BB1;&#x81EA;&#x5E36;&#x7684;&#x4E00;&#x500B;&#x5DE5;&#x5177;, &#x4F46;&#x4F75;&#x4E0D;&#x662F;&#x4E00;&#x500B;&#x65E5;&#x5E38;&#x5DE5;&#x5177;, &#x5B83;&#x5C0D;&#x61C9; <code>go tool pprof</code> &#x547D;&#x4EE4;. &#x8A72;&#x547D;&#x4EE4;&#x6709;&#x8A31;&#x591A;&#x7279;&#x6027;&#x548C;&#x9078;&#x9805;, &#x4F46;&#x662F;&#x6700;&#x91CD;&#x8981;&#x7684;&#x6709;&#x5169;&#x500B;, &#x5C31;&#x662F;&#x751F;&#x6210;&#x9019;&#x500B;&#x6982;&#x8981;&#x6587;&#x4EF6;&#x7684;&#x53EF;&#x57F7;&#x884C;&#x7A0B;&#x5E8F;&#x548C;&#x5C0D;&#x65BC;&#x7684;&#x5206;&#x6790;&#x65E5;&#x8A8C;&#x6587;&#x4EF6;.</p>
<p>&#x7232;&#x4E86;&#x63D0;&#x9AD8;&#x5206;&#x6790;&#x6548;&#x7387;&#x548C;&#x6E1B;&#x5C11;&#x7A7A;&#x9593;, &#x5206;&#x6790;&#x65E5;&#x8A8C;&#x672C;&#x8EAB;&#x4F75;&#x4E0D;&#x5305;&#x542B;&#x51FD;&#x6578;&#x7684;&#x540D;&#x5B57;; &#x5B83;&#x96BB;&#x5305;&#x542B;&#x51FD;&#x6578;&#x5C0D;&#x61C9;&#x7684;&#x5730;&#x5740;. &#x4E5F;&#x5C31;&#x662F;&#x8AAC;pprof&#x9700;&#x8981;&#x548C;&#x5206;&#x6790;&#x65E5;&#x8A8C;&#x5C0D;&#x65BC;&#x7684;&#x53EF;&#x57F7;&#x884C;&#x7A0B;&#x5E8F;. &#x96D6;&#x7136; <code>go test</code> &#x547D;&#x4EE4;&#x901A;&#x5E38;&#x6703;&#x4E1F;&#x68C4;&#x81E8;&#x6642;&#x7528;&#x7684;&#x6E2C;&#x8A66;&#x7A0B;&#x5E8F;, &#x4F46;&#x662F;&#x5728;&#x5553;&#x7528;&#x5206;&#x6790;&#x7684;&#x6642;&#x5019;&#x6703;&#x5C07;&#x6E2C;&#x8A66;&#x7A0B;&#x5E8F;&#x4FDD;&#x5B58;&#x7232; foo.test &#x6587;&#x4EF6;, &#x5176;&#x4E2D; foo &#x90E8;&#x5206;&#x5C0D;&#x65BC;&#x6E2C;&#x8A66;&#x5305;&#x7684;&#x540D;&#x5B57;.</p>
<p>&#x4E0B;&#x9EAB;&#x7684;&#x547D;&#x4EE4;&#x6F14;&#x793A;&#x4E86;&#x5982;&#x4F55;&#x751F;&#x6210;&#x4E00;&#x500B;CPU&#x5206;&#x6790;&#x6587;&#x4EF6;. &#x6211;&#x5011;&#x9078;&#x64C7; <code>net/http</code> &#x5305;&#x7684;&#x4E00;&#x500B;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;. &#x901A;&#x5E38;&#x662F;&#x57FA;&#x65BC;&#x4E00;&#x500B;&#x5DF2;&#x7D93;&#x78BA;&#x5B9A;&#x4E86;&#x662F;&#x95DC;&#x9375;&#x4EE3;&#x78BC;&#x7684;&#x90E8;&#x5206;&#x9032;&#x884C;&#x57FA;&#x6E96;&#x6E2C;&#x8A66;. &#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x6703;&#x9ED8;&#x8A8D;&#x5305;&#x542B;&#x55AE;&#x5143;&#x6E2C;&#x8A66;, &#x9019;&#x88E1;&#x6211;&#x5011;&#x7528; -run=NONE &#x7981;&#x6B62;&#x55AE;&#x5143;&#x6E2C;&#x8A66;.</p>
<pre><code>$ go test -run=NONE -bench=ClientServerParallelTLS64 \
-cpuprofile=cpu.log net/http
PASS
BenchmarkClientServerParallelTLS64-8 1000
3141325 ns/op 143010 B/op 1747 allocs/op
ok net/http 3.395s
$ go tool pprof -text -nodecount=10 ./http.test cpu.log
2570ms of 3590ms total (71.59%)
Dropped 129 nodes (cum &lt;= 17.95ms)
Showing top 10 nodes out of 166 (cum &gt;= 60ms)
flat flat% sum% cum cum%
1730ms 48.19% 48.19% 1750ms 48.75% crypto/elliptic.p256ReduceDegree
230ms 6.41% 54.60% 250ms 6.96% crypto/elliptic.p256Diff
120ms 3.34% 57.94% 120ms 3.34% math/big.addMulVVW
110ms 3.06% 61.00% 110ms 3.06% syscall.Syscall
90ms 2.51% 63.51% 1130ms 31.48% crypto/elliptic.p256Square
70ms 1.95% 65.46% 120ms 3.34% runtime.scanobject
60ms 1.67% 67.13% 830ms 23.12% crypto/elliptic.p256Mul
60ms 1.67% 68.80% 190ms 5.29% math/big.nat.montgomery
50ms 1.39% 70.19% 50ms 1.39% crypto/elliptic.p256ReduceCarry
50ms 1.39% 71.59% 60ms 1.67% crypto/elliptic.p256Sum
</code></pre><p>&#x8518;&#x6578; <code>-text</code> &#x6A19;&#x8A8C;&#x8518;&#x6578;&#x7528;&#x65BC;&#x6307;&#x5B9A;&#x8F38;&#x9F63;&#x683C;&#x5F0F;, &#x5728;&#x9019;&#x88E1;&#x6BCF;&#x884C;&#x662F;&#x4E00;&#x500B;&#x51FD;&#x6578;, &#x6839;&#x64DA;&#x4F7F;&#x7528;CPU&#x7684;&#x6642;&#x9593;&#x4F86;&#x6392;&#x5E8F;. &#x5176;&#x4E2D; <code>-nodecount=10</code> &#x6A19;&#x8A8C;&#x8518;&#x6578;&#x9650;&#x88FD;&#x4E86;&#x96BB;&#x8F38;&#x9F63;&#x524D;10&#x884C;&#x7684;&#x7D50;&#x679C;. &#x5C0D;&#x65BC;&#x56B4;&#x91CD;&#x7684;&#x6027;&#x80FD;&#x554F;&#x984C;, &#x9019;&#x500B;&#x6587;&#x672C;&#x683C;&#x5F0F;&#x57FA;&#x672C;&#x53EF;&#x4EE5;&#x5E6B;&#x52A9;&#x67FB;&#x660E;&#x539F;&#x56E0;&#x4E86;.</p>
<p>&#x9019;&#x500B;&#x6982;&#x8981;&#x6587;&#x4EF6;&#x544A;&#x8A34;&#x6211;&#x5011;, HTTPS&#x57FA;&#x6E96;&#x6E2C;&#x8A66;&#x4E2D; <code>crypto/elliptic.p256ReduceDegree</code> &#x51FD;&#x6578;&#x4F54;&#x7528;&#x4E86;&#x5C07;&#x8FD1;&#x4E00;&#x822C;&#x7684;CPU&#x8CC7;&#x6E90;. &#x76F8;&#x6BD4;&#x4E4B;&#x4E0B;, &#x5982;&#x679C;&#x4E00;&#x500B;&#x6982;&#x8981;&#x6587;&#x4EF6;&#x4E2D;&#x4E3B;&#x8981;&#x662F;runtime&#x5305;&#x7684;&#x5167;&#x5B58;&#x5206;&#x914D;&#x7684;&#x51FD;&#x6578;, &#x90A3;&#x9EBD;&#x6E1B;&#x5C11;&#x5167;&#x5B58;&#x6D88;&#x8017;&#x53EF;&#x80FD;&#x662F;&#x4E00;&#x500B;&#x503C;&#x5F97;&#x5690;&#x8A66;&#x7684;&#x512A;&#x5316;&#x7B56;&#x7565;.</p>
<p>&#x5C0D;&#x65BC;&#x4E00;&#x4E9B;&#x66F4;&#x5FAE;&#x5999;&#x7684;&#x554F;&#x984C;, &#x4F60;&#x53EF;&#x80FD;&#x9700;&#x8981;&#x4F7F;&#x7528; pprof &#x7684;&#x5716;&#x5F62;&#x986F;&#x793A;&#x529F;&#x80FD;. &#x9019;&#x500B;&#x9700;&#x8981;&#x5B89;&#x88DD; GraphViz &#x5DE5;&#x5177;, &#x53EF;&#x4EE5;&#x5F9E; www.graphviz.org &#x4E0B;&#x8F09;. &#x8518;&#x6578; <code>-web</code> &#x7528;&#x65BC;&#x751F;&#x6210;&#x4E00;&#x500B;&#x6709;&#x66CF;&#x5716;&#x6587;&#x4EF6;, &#x5305;&#x542B;CPU&#x7684;&#x4F7F;&#x7528;&#x548C;&#x6700;&#x7279;&#x9EDE;&#x7684;&#x51FD;&#x6578;&#x7B49;&#x4FE1;&#x606F;.</p>
<p>&#x9019;&#x4E00;&#x7BC0;&#x6211;&#x5011;&#x96BB;&#x662F;&#x7C21;&#x55AE;&#x770B;&#x4E86;&#x4E0B;Go&#x8A9E;&#x8A00;&#x7684;&#x5206;&#x6790;&#x64DA;&#x5DE5;&#x5177;. &#x5982;&#x679C;&#x60F3;&#x4E86;&#x89E3;&#x66F4;&#x591A;, &#x53EF;&#x4EE5;&#x95B2;&#x8B80; Go&#x5B98;&#x65B9;&#x535A;&#x5BA2;&#x7684; &#x2018;&#x2018;Pro&#xFB01;ling Go Programs&#x2019;&#x2019; &#x4E00;&#x6587;.</p>
</section>

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11.6" data-chapter-title="示例函數" data-filepath="ch11/ch11-06.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11.6" data-chapter-title="示例函數" data-filepath="ch11/ch11-06.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">

View File

@@ -48,7 +48,7 @@
<body>
<div class="book" data-level="11" data-chapter-title="測試" data-filepath="ch11/ch11.md" data-basepath=".." data-revision="Wed Dec 09 2015 15:54:13 GMT+0800 (中国标准时间)">
<div class="book" data-level="11" data-chapter-title="測試" data-filepath="ch11/ch11.md" data-basepath=".." data-revision="Mon Dec 14 2015 11:30:54 GMT+0800 (中国标准时间)">
<div class="book-summary">