mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2025-12-18 11:44:20 +08:00
rebuild
This commit is contained in:
138
ch2/ch2-05.html
138
ch2/ch2-05.html
@@ -48,7 +48,7 @@
|
||||
<body>
|
||||
|
||||
|
||||
<div class="book" data-level="2.5" data-chapter-title="類型" data-filepath="ch2/ch2-05.md" data-basepath=".." data-revision="Wed Dec 16 2015 10:54:29 GMT+0800 (中国标准时间)">
|
||||
<div class="book" data-level="2.5" data-chapter-title="類型" data-filepath="ch2/ch2-05.md" data-basepath=".." data-revision="Mon Dec 21 2015 12:51:02 GMT+0800 (中国标准时间)">
|
||||
|
||||
|
||||
<div class="book-summary">
|
||||
@@ -146,7 +146,7 @@
|
||||
|
||||
<b>0.5.</b>
|
||||
|
||||
緻謝
|
||||
致謝
|
||||
</a>
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
|
||||
<b>1.3.</b>
|
||||
|
||||
査找重復的行
|
||||
査找重複的行
|
||||
</a>
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
|
||||
<b>1.4.</b>
|
||||
|
||||
GIF動畫
|
||||
GIF動畵
|
||||
</a>
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
<b>1.6.</b>
|
||||
|
||||
併髮穫取多個URL
|
||||
併發穫取多個URL
|
||||
</a>
|
||||
|
||||
|
||||
@@ -479,7 +479,7 @@
|
||||
|
||||
<b>3.3.</b>
|
||||
|
||||
復數
|
||||
複數
|
||||
</a>
|
||||
|
||||
|
||||
@@ -494,7 +494,7 @@
|
||||
|
||||
<b>3.4.</b>
|
||||
|
||||
佈爾型
|
||||
布爾型
|
||||
</a>
|
||||
|
||||
|
||||
@@ -544,7 +544,7 @@
|
||||
|
||||
<b>4.</b>
|
||||
|
||||
復閤數據類型
|
||||
複合數據類型
|
||||
</a>
|
||||
|
||||
|
||||
@@ -857,7 +857,7 @@
|
||||
|
||||
<b>6.2.</b>
|
||||
|
||||
基於指鍼對象的方法
|
||||
基於指針對象的方法
|
||||
</a>
|
||||
|
||||
|
||||
@@ -887,7 +887,7 @@
|
||||
|
||||
<b>6.4.</b>
|
||||
|
||||
方法值和方法錶達式
|
||||
方法值和方法表達式
|
||||
</a>
|
||||
|
||||
|
||||
@@ -953,7 +953,7 @@
|
||||
|
||||
<b>7.1.</b>
|
||||
|
||||
接口是閤約
|
||||
接口是合約
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1073,7 +1073,7 @@
|
||||
|
||||
<b>7.9.</b>
|
||||
|
||||
示例: 錶達式求值
|
||||
示例: 表達式求值
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1103,7 +1103,7 @@
|
||||
|
||||
<b>7.11.</b>
|
||||
|
||||
基於類型斷言識彆錯誤類型
|
||||
基於類型斷言識别錯誤類型
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1214,7 +1214,7 @@
|
||||
|
||||
<b>8.2.</b>
|
||||
|
||||
示例: 併髮的Clock服務
|
||||
示例: 併發的Clock服務
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1229,7 +1229,7 @@
|
||||
|
||||
<b>8.3.</b>
|
||||
|
||||
示例: 併髮的Echo服務
|
||||
示例: 併發的Echo服務
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1274,7 +1274,7 @@
|
||||
|
||||
<b>8.6.</b>
|
||||
|
||||
示例: 併髮的Web爬蟲
|
||||
示例: 併發的Web爬蟲
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1289,7 +1289,7 @@
|
||||
|
||||
<b>8.7.</b>
|
||||
|
||||
基於select的多路復用
|
||||
基於select的多路複用
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1304,7 +1304,7 @@
|
||||
|
||||
<b>8.8.</b>
|
||||
|
||||
示例: 併髮的字典遍歷
|
||||
示例: 併發的字典遍歷
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1319,7 +1319,7 @@
|
||||
|
||||
<b>8.9.</b>
|
||||
|
||||
併髮的退齣
|
||||
併發的退齣
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1354,7 +1354,7 @@
|
||||
|
||||
<b>9.</b>
|
||||
|
||||
基於共享變量的併髮
|
||||
基於共享變量的併發
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1415,7 +1415,7 @@
|
||||
|
||||
<b>9.4.</b>
|
||||
|
||||
內存衕步
|
||||
內存同步
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1460,7 +1460,7 @@
|
||||
|
||||
<b>9.7.</b>
|
||||
|
||||
示例: 併髮的非阻塞緩存
|
||||
示例: 併發的非阻塞緩存
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1475,7 +1475,7 @@
|
||||
|
||||
<b>9.8.</b>
|
||||
|
||||
Goroutines和綫程
|
||||
Goroutines和線程
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1748,7 +1748,7 @@
|
||||
|
||||
<b>12.1.</b>
|
||||
|
||||
為何需要反射?
|
||||
爲何需要反射?
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1793,7 +1793,7 @@
|
||||
|
||||
<b>12.4.</b>
|
||||
|
||||
示例: 編碼S錶達式
|
||||
示例: 編碼S表達式
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1823,7 +1823,7 @@
|
||||
|
||||
<b>12.6.</b>
|
||||
|
||||
示例: 解碼S錶達式
|
||||
示例: 解碼S表達式
|
||||
</a>
|
||||
|
||||
|
||||
@@ -1975,50 +1975,14 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="14" data-path="exercise/ex.html">
|
||||
|
||||
|
||||
<a href="../exercise/ex.html">
|
||||
|
||||
<i class="fa fa-check"></i>
|
||||
|
||||
<b>14.</b>
|
||||
|
||||
習題解答
|
||||
</a>
|
||||
|
||||
|
||||
<ul class="articles">
|
||||
|
||||
|
||||
<li class="chapter " data-level="14.1" data-path="exercise/ex-ch1.html">
|
||||
|
||||
|
||||
<a href="../exercise/ex-ch1.html">
|
||||
|
||||
<i class="fa fa-check"></i>
|
||||
|
||||
<b>14.1.</b>
|
||||
|
||||
第一章 入門
|
||||
</a>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="chapter " data-level="15" data-path="errata.html">
|
||||
<li class="chapter " data-level="14" data-path="errata.html">
|
||||
|
||||
|
||||
<a href="../errata.html">
|
||||
|
||||
<i class="fa fa-check"></i>
|
||||
|
||||
<b>15.</b>
|
||||
<b>14.</b>
|
||||
|
||||
勘誤
|
||||
</a>
|
||||
@@ -2060,17 +2024,17 @@
|
||||
<section class="normal" id="section-">
|
||||
|
||||
<h2 id="25-類型聲明">2.5. 類型聲明</h2>
|
||||
<p>變量或錶達式的類型定義了對應存儲值的特徵, 例如數值的存儲大小(或者是元素的bit個數), 它們在內部是如何錶達的, 是否支持一些操作符, 以及它們自己關聯的方法集,</p>
|
||||
<p>在任何程序中都會有一些變量有着相衕的內部實現, 但是錶示完全不衕的概唸.
|
||||
例如, int 類型的變量可以用來錶示一個循環的迭代索引, 或者一個時間戳, 或者一個文件描述符, 或者一個月份; 一個 float64 類型的變量可以用來錶示每秒幾米的速度, 或者是不衕溫度單位的溫度;
|
||||
一個字符串可以用來錶示一個密碼或者一個顔色的名稱.</p>
|
||||
<p>一個類型的聲明創建了一個新的類型名稱, 和現有類型具有相衕的底層結構.
|
||||
新命名的類型提供了一個方法, 用來分隔不衕概唸的類型, 卽使它們底層類型相衕也是不兼容的.</p>
|
||||
<p>變量或表達式的類型定義了對應存儲值的特徵, 例如數值的存儲大小(或者是元素的bit個數), 它們在內部是如何表達的, 是否支持一些操作符, 以及它們自己關聯的方法集,</p>
|
||||
<p>在任何程序中都會有一些變量有着相同的內部實現, 但是表示完全不同的概念.
|
||||
例如, int 類型的變量可以用來表示一個循環的迭代索引, 或者一個時間戳, 或者一個文件描述符, 或者一個月份; 一個 float64 類型的變量可以用來表示每秒幾米的速度, 或者是不同溫度單位的溫度;
|
||||
一個字符串可以用來表示一個密碼或者一個顔色的名稱.</p>
|
||||
<p>一個類型的聲明創建了一個新的類型名稱, 和現有類型具有相同的底層結構.
|
||||
新命名的類型提供了一個方法, 用來分隔不同概念的類型, 卽使它們底層類型相同也是不兼容的.</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">type</span> name underlying-<span class="hljs-keyword">type</span>
|
||||
</code></pre>
|
||||
<p>類型的聲明一般齣現在包級彆, 因此如果新創建的類型名字名字的首字符大寫, 則在外部包也可以使用.</p>
|
||||
<p>為了說明類型聲明, 我們將不衕溫度單位分彆定義為不衕的類型:</p>
|
||||
<p>為了說明類型聲明,讓我們把不衕溫度範圍分為不衕的類型:</p>
|
||||
<p>類型的聲明一般齣現在包級别, 因此如果新創建的類型名字名字的首字符大寫, 則在外部包也可以使用.</p>
|
||||
<p>爲了説明類型聲明, 我們將不同溫度單位分别定義爲不同的類型:</p>
|
||||
<p>爲了説明類型聲明,讓我們把不同溫度范圍分爲不同的類型:</p>
|
||||
<pre><code class="lang-Go">gopl.io/ch2/tempconv0
|
||||
<span class="hljs-comment">// Package tempconv performs Celsius and Fahrenheit temperature computations.</span>
|
||||
<span class="hljs-keyword">package</span> tempconv
|
||||
@@ -2090,20 +2054,20 @@
|
||||
|
||||
<span class="hljs-keyword">func</span> FToC(f Fahrenheit) Celsius { <span class="hljs-keyword">return</span> Celsius((f - <span class="hljs-number">32</span>) * <span class="hljs-number">5</span> / <span class="hljs-number">9</span>) }
|
||||
</code></pre>
|
||||
<p>這個包定義了兩種類型, Celsius 和 Fahrenheit 分彆對應不衕的溫度單位. 它們都有着相衕的底層類型 float64, 但是它們是不衕的數據類型, 因此它們不可以被相互比較或混在一個錶達式計算. 可以區分類型, 可以避免一些像無意中結閤單位的溫度進行計算的錯誤; 因為需要一個類似 Celsius(t) 或 Fahrenheit(t) 顯式的轉型操作纔能將 float64 轉為對應的類型. Celsius(t) 和 Fahrenheit(t) 是類型轉換操作, 併不是函數調用. 類型轉換不會改變值本身, 但是會使它們的語義髮生變化. 另一方麫, 函數 CToF 和 FToC 則是對兩個不衕的溫度單位進行轉換, 它們會返迴不衕的值.</p>
|
||||
<p>對於每一個類型 T, 都有一個對應的類型轉換操作 T(x), 用於將 x 轉為 T 類型.
|
||||
隻有當兩個類型的底層基礎類型相衕時, 纔允許這種轉型操作, 或者是兩者都是指曏相衕底層結構的指鍼類型,
|
||||
這些轉換隻改變類型而不會影響值本身. 如果x是可以賦值給T類型的, 那麼x必然可以被轉為T類型, 但是一般沒有必要.</p>
|
||||
<p>數值類型之間的轉型也是允許的, 併且在字符串和一些特定切片之間也是可以轉換的, 在下一章我們會看到這樣的例子. 這類轉換可能改變值的錶現. 例如, 將一個浮點數轉為整數將丟棄小數部分, 將一個字符串轉為 []byte 切片將拷貝一個字符串數據的副本. 在任何情況下, 運行時不會髮送轉換失敗的錯誤(譯註: 錯誤隻會髮生在編譯階段).</p>
|
||||
<p>底層數據類型決定了內部結構和錶達方式, 也包決定是否可以像底層類型一樣對內置運算符的支持.
|
||||
這意味着, Celsius 和 Fahrenheit 類型的算朮行為和底層的 float64 類型一樣, 正如你所期望的.</p>
|
||||
<p>這個包定義了兩種類型, Celsius 和 Fahrenheit 分别對應不同的溫度單位. 它們都有着相同的底層類型 float64, 但是它們是不同的數據類型, 因此它們不可以被相互比較或混在一個表達式計算. 可以區分類型, 可以避免一些像無意中結合單位的溫度進行計算的錯誤; 因爲需要一個類似 Celsius(t) 或 Fahrenheit(t) 顯式的轉型操作纔能將 float64 轉爲對應的類型. Celsius(t) 和 Fahrenheit(t) 是類型轉換操作, 併不是函數調用. 類型轉換不會改變值本身, 但是會使它們的語義發生變化. 另一方面, 函數 CToF 和 FToC 則是對兩個不同的溫度單位進行轉換, 它們會返迴不同的值.</p>
|
||||
<p>對於每一個類型 T, 都有一個對應的類型轉換操作 T(x), 用於將 x 轉爲 T 類型.
|
||||
隻有當兩個類型的底層基礎類型相同時, 纔允許這種轉型操作, 或者是兩者都是指向相同底層結構的指針類型,
|
||||
這些轉換隻改變類型而不會影響值本身. 如果x是可以賦值給T類型的, 那麽x必然可以被轉爲T類型, 但是一般沒有必要.</p>
|
||||
<p>數值類型之間的轉型也是允許的, 併且在字符串和一些特定切片之間也是可以轉換的, 在下一章我們會看到這樣的例子. 這類轉換可能改變值的表現. 例如, 將一個浮點數轉爲整數將丟棄小數部分, 將一個字符串轉爲 []byte 切片將拷貝一個字符串數據的副本. 在任何情況下, 運行時不會發送轉換失敗的錯誤(譯註: 錯誤隻會發生在編譯階段).</p>
|
||||
<p>底層數據類型決定了內部結構和表達方式, 也包決定是否可以像底層類型一樣對內置運算符的支持.
|
||||
這意味着, Celsius 和 Fahrenheit 類型的算術行爲和底層的 float64 類型一樣, 正如你所期望的.</p>
|
||||
<pre><code class="lang-Go">fmt.Printf(<span class="hljs-string">"%g\n"</span>, BoilingC-FreezingC) <span class="hljs-comment">// "100" °C</span>
|
||||
boilingF := CToF(BoilingC)
|
||||
fmt.Printf(<span class="hljs-string">"%g\n"</span>, boilingF-CToF(FreezingC)) <span class="hljs-comment">// "180" °F</span>
|
||||
fmt.Printf(<span class="hljs-string">"%g\n"</span>, boilingF-FreezingC) <span class="hljs-comment">// compile error: type mismatch</span>
|
||||
</code></pre>
|
||||
<p>比較運算符 <code>==</code> 和 <code><</code> 也可以用來比較一個命名類型的變量和另一個有相衕類型的變量或相衕的底層類型的值做比較.
|
||||
但是如果兩個值有着不衕的類型, 則不能直接進行比較:</p>
|
||||
<p>比較運算符 <code>==</code> 和 <code><</code> 也可以用來比較一個命名類型的變量和另一個有相同類型的變量或相同的底層類型的值做比較.
|
||||
但是如果兩個值有着不同的類型, 則不能直接進行比較:</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">var</span> c Celsius
|
||||
<span class="hljs-keyword">var</span> f Fahrenheit
|
||||
fmt.Println(c == <span class="hljs-number">0</span>) <span class="hljs-comment">// "true"</span>
|
||||
@@ -2111,13 +2075,13 @@ fmt.Println(f >= <span class="hljs-number">0</span>) <span class="hl
|
||||
fmt.Println(c == f) <span class="hljs-comment">// compile error: type mismatch</span>
|
||||
fmt.Println(c == Celsius(f)) <span class="hljs-comment">// "true"!</span>
|
||||
</code></pre>
|
||||
<p>註意最後那個語句. 盡管看起來想函數調用, 但是Celsius(f)類型轉換, 併不會改變值, 它僅僅是改變值的類型而已. 測試為眞的原因是因為 c 和 g 都是零值.</p>
|
||||
<p>一個命名的類型可以提供符號方便, 特彆是可以避免一遍又一遍地書寫復雜類型(譯註: 例如用匿名的結構體定義變量). 雖然對於像float64這種簡單的底層類型沒有簡潔很多, 但是如果是復雜的類型將會簡潔很多, 正如我們卽將討論的結構體類型:</p>
|
||||
<p>命名類型還可以為該類型的值定義新的行為. 這些行為錶示為一組關聯到類型的函數, 我們成為類型的方法集. 我們將在第六章討論方法的細節, 這裏值說寫簡單用法.</p>
|
||||
<p>下麫的聲明, Celsius 類型的參數 c 齣現在了函數名的前麫, 錶示聲明一個 Celsius 類型的 名叫 String 的方法, 方法返迴 帶着 °C 溫度單位 的參數 c 的數字打印字符串:</p>
|
||||
<p>註意最後那個語句. 盡管看起來想函數調用, 但是Celsius(f)類型轉換, 併不會改變值, 它僅僅是改變值的類型而已. 測試爲眞的原因是因爲 c 和 g 都是零值.</p>
|
||||
<p>一個命名的類型可以提供符號方便, 特别是可以避免一遍又一遍地書寫複雜類型(譯註: 例如用匿名的結構體定義變量). 雖然對於像float64這種簡單的底層類型沒有簡潔很多, 但是如果是複雜的類型將會簡潔很多, 正如我們卽將討論的結構體類型:</p>
|
||||
<p>命名類型還可以爲該類型的值定義新的行爲. 這些行爲表示爲一組關聯到類型的函數, 我們成爲類型的方法集. 我們將在第六章討論方法的細節, 這里值説寫簡單用法.</p>
|
||||
<p>下面的聲明, Celsius 類型的參數 c 齣現在了函數名的前面, 表示聲明一個 Celsius 類型的 名叫 String 的方法, 方法返迴 帶着 °C 溫度單位 的參數 c 的數字打印字符串:</p>
|
||||
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> (c Celsius) String() <span class="hljs-typename">string</span> { <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">"%g°C"</span>, c) }
|
||||
</code></pre>
|
||||
<p>許多類型都會定義個 String 方法, 因為當然用 fmt 包的打印方法時, 將會優先使用 String 方法返迴的結果打印, 將在 7.1節 講述.</p>
|
||||
<p>許多類型都會定義個 String 方法, 因爲當然用 fmt 包的打印方法時, 將會優先使用 String 方法返迴的結果打印, 將在 7.1節 講述.</p>
|
||||
<pre><code class="lang-Go">c := FToC(<span class="hljs-number">212.0</span>)
|
||||
fmt.Println(c.String()) <span class="hljs-comment">// "100°C"</span>
|
||||
fmt.Printf(<span class="hljs-string">"%v\n"</span>, c) <span class="hljs-comment">// "100°C"; no need to call String explicitly</span>
|
||||
|
||||
Reference in New Issue
Block a user