make zh2tw

This commit is contained in:
chai2010
2015-12-21 12:52:25 +08:00
parent 14665b4d9c
commit d024df28e9
7 changed files with 131 additions and 131 deletions

View File

@@ -1,20 +1,20 @@
## 3.1. 整型
Go言的数值类型包括几种不同大小的整形, 浮点数, 和复数. 每种数值类型都定了对应的大小范和是否有正负符号. 让我们先从整形数类型开始介.
Go言的數值類型包括幾種不同大小的整形, 浮點數, 和複數. 每種數值類型都定了對應的大小范和是否有正負符號. 讓我們先從整形數類型開始介.
Go同提供了有符号和无符号的整数运算. 里有四int8, int16, int32 和 int64截然不同大小的有符整形数类型, 分别对应 8, 16, 32, 64 bit 大小的有符整形, 与此对应的是 uint8, uint16, uint32, 和 uint64 四种无符号整形数类型.
Go同提供了有符號和無符號的整數運算. 里有四int8, int16, int32 和 int64截然不同大小的有符整形數類型, 分别對應 8, 16, 32, 64 bit 大小的有符整形, 與此對應的是 uint8, uint16, uint32, 和 uint64 四種無符號整形數類型.
这里还有两种对应特定平最天然或最有效率的大小有符号和无符号整数int和uint; 其中int是用最广泛的数值类型. 这两种类型都有同的大小, 32 或 64 bit, 但是我不能此做任何的假; 因不同的编译器在相同的硬件平上可能生不同的大小.
這里還有兩種對應特定平最天然或最有效率的大小有符號和無符號整數int和uint; 其中int是用最泛的數值類型. 這兩種類型都有同的大小, 32 或 64 bit, 但是我不能此做任何的假; 因不同的編譯器在相同的硬件平上可能生不同的大小.
字符rune型是和int32等价的类型, 通常用表示一Unicode码点. 这两个名称可以互使用. 同byte也是uint8型的等价类型, byte型用于强调数值是一原始的数据而不是一小的整.
字符rune型是和int32等價的類型, 通常用表示一Unicode碼點. 這兩個名稱可以互使用. 同byte也是uint8型的等價類型, byte型用於強調數值是一原始的數據而不是一小的整.
最好, 有一个无符号的整数类型 uintptr, 有指定具的bit大小但是足以容纳指针. uintptr 类型只有在底层编程是需要, 特别是Go言和C函数库或操作系统相交互的地方. 我们将在第十三章的 unsafe 包相部分看到似的例子.
最好, 有一個無符號的整數類型 uintptr, 有指定具的bit大小但是足以容納指針. uintptr 類型隻有在底層編程是需要, 特别是Go言和C函數庫或操作繫統相交互的地方. 我們將在第十三章的 unsafe 包相部分看到似的例子.
不管它的大小, int, uint, 和 uintptr 是不同型大小的兄弟型. 其中 int 和 int32 也是不同的型, 使int的大小也是32bit, 在需要int作int32型的地方需要一个显式的类型转换, 反之亦然.
不管它的大小, int, uint, 和 uintptr 是不同型大小的兄弟型. 其中 int 和 int32 也是不同的型, 使int的大小也是32bit, 在需要int作int32型的地方需要一個顯式的類型轉換, 反之亦然.
有符号数采用2的补码形式表示, 也就是最高位用作符位, 一nbit的有符号数的值域是 `-2^(n-1)``(2^(n-1)) - 1`. 无符号整数的所有bit位都用表示非负数, 值域是 0 到 `(2^n) - 1`. 例如, int8 的值域是 -128 到 127, 而 uint8 的值域是 0 到 255.
有符號數采用2的補碼形式表示, 也就是最高位用作符位, 一nbit的有符號數的值域是 `-2^(n-1)``(2^(n-1)) - 1`. 無符號整數的所有bit位都用表示非負數, 值域是 0 到 `(2^n) - 1`. 例如, int8 的值域是 -128 到 127, 而 uint8 的值域是 0 到 255.
下面是Go中关于算术, 逻辑和比的二元算符按照先级递减的顺序的列表:
下面是Go中關於算術, 邏輯和比的二元算符按照先級遞減的順序的列表:
```
* / % << >> & &^
@@ -24,14 +24,14 @@ Go同时提供了有符号和无符号的整数运算. 这里有四种int8, int1
||
```
二元算符有五种优先级. 在同一优先级, 使用左优先结合律, 使用括可以明确优先顺序, 括也可以用于提升优先级, 例如 `mask & (1 << 28)`.
二元算符有五種優先級. 在同一優先級, 使用左優先結合律, 使用括可以明確優先順序, 括也可以用於提陞優先級, 例如 `mask & (1 << 28)`.
对于上表中前行的算符, 例如 + 有一个相应的赋值结合运算符 +=, 可以用于简化赋值语句.
對於上表中前行的算符, 例如 + 有一個相應的賦值結合運算符 +=, 可以用於簡化賦值語句.
的算术运算符 +, -, *, 和 / 可以适用与整数, 浮点数和复数, 但是取模算符 % 仅用于整数. 不同编程语言间, % 取模算的行为并不相同. 在Go言中, % 取模算符的符和被取模的符号总是一致的, 因此 `-5%3``-5%-3` 果都是 -2.除法算符 `/` 的行为依赖于操作是否为整数, 因此 `5.0/4.0`果是 1.25, 但是 5/4 的果是 1, 因此整除法向着0方向截断余数.
的算術運算符 +, -, *, 和 / 可以適用與整數, 浮點數和複數, 但是取模算符 % 僅用於整數. 不同編程語言間, % 取模算的行爲併不相同. 在Go言中, % 取模算符的符和被取模的符號總是一致的, 因此 `-5%3``-5%-3` 果都是 -2.除法算符 `/` 的行爲依賴於操作是否爲整數, 因此 `5.0/4.0`果是 1.25, 但是 5/4 的果是 1, 因此整除法向着0方向截斷餘數.
如果一个算术运算的果, 不管是有符或者是无符号的, 如果需要更多的bit位能表示, 就明是溢了. 超的高位的bit位部分将被丢弃. 如果原始的值是有符号类型, 那么最终结果可能是的, 如果最左的bit是1的, 例如int8的例子:
如果一個算術運算的果, 不管是有符或者是無符號的, 如果需要更多的bit位能表示, 就明是溢了. 超的高位的bit位部分將被丟棄. 如果原始的值是有符號類型, 那麽最終結果可能是的, 如果最左的bit是1的, 例如int8的例子:
```Go
var u uint8 = 255
@@ -41,7 +41,7 @@ var i int8 = 127
fmt.Println(i, i+1, i*i) // "127 -128 1"
```
两个相同的整数类型可以使用下面的二元比较运算符行比; 比较表达式的果是布尔类型.
兩個相同的整數類型可以使用下面的二元比較運算符行比; 比較表達式的果是布爾類型.
```
== equal to
@@ -52,33 +52,33 @@ fmt.Println(i, i+1, i*i) // "127 -128 1"
>= greater than or equal to
```
上, 布型, 数字类型 和 字符串 等基本型都是可比的, 也就是说两个相同型的值可以用 == 和 != 行比. 此外, 整, 浮点数和字符串可以根据比较结果排序. 多其他型的值是不可比, 因此也就是不可排序的. 对于我们遇到的每种类型, 我需要保证规则是类似的.
上, 布型, 數字類型 和 字符串 等基本型都是可比的, 也就是説兩個相同型的值可以用 == 和 != 行比. 此外, 整, 浮點數和字符串可以根據比較結果排序. 多其他型的值是不可比, 因此也就是不可排序的. 對於我們遇到的每種類型, 我需要保證規則是類似的.
里是一元的加法和减法运算符:
里是一元的加法和減法運算符:
```
+ 一元加法 (效果)
- 负数
+ 一元加法 (效果)
- 負數
```
对于整数, +x 是 0+x 的简写, -x 是 0-x 的简写; 对于浮点数和复数, +x 就是 x, -x 是 x 的负数.
對於整數, +x 是 0+x 的簡寫, -x 是 0-x 的簡寫; 對於浮點數和複數, +x 就是 x, -x 是 x 的負數.
Go语言还提供了以下的bit位操作算符, 前面4操作算符并不区分是有符号还是无符号数:
Go語言還提供了以下的bit位操作算符, 前面4操作算符併不區分是有符號還是無符號數:
```
& 位算 AND
| 位算 OR
^ 位算 XOR
& 位算 AND
| 位算 OR
^ 位算 XOR
&^ 位清空 (AND NOT)
<< 左移
>> 右移
```
位操作算符 `^`二元算符是按位或(XOR), 用作一元算符表示按位取反; 也就是, 它返回一个每个bit位都取反的. 位操作算符 `&^`按位置零(AND NOT): 表`z = x &^ y` 果z的bit位1, 如果对应y中bit位1, 否则对应的bit位等x相的bit位的值.
位操作算符 `^`二元算符是按位或(XOR), 用作一元算符表示按位取反; 也就是, 它返迴一個每個bit位都取反的. 位操作算符 `&^`按位置零(AND NOT): 表`z = x &^ y` 果z的bit位1, 如果對應y中bit位1, 否則對應的bit位等x相的bit位的值.
下面的代演示了如何使用位操作解uint8型值的8个独立的bit位. 它使用了 Printf 函的 %b 参数打印二进制格式的字; 其中 %08b 中08表示打印至少8个数字, 不足的前用0填充.
下面的代演示了如何使用位操作解uint8型值的8個獨立的bit位. 它使用了 Printf 函的 %b 參數打印二進製格式的字; 其中 %08b 中08表示打印至少8個數字, 不足的前用0填充.
```Go
var x uint8 = 1<<1 | 1<<5
@@ -102,13 +102,13 @@ fmt.Printf("%08b\n", x<<1) // "01000100", the set {2, 6}
fmt.Printf("%08b\n", x>>1) // "00010001", the set {0, 4}
```
(6.5节给出了一可以远大于一个字节的整集的实现.)
(6.5節給齣了一可以遠大於一個字節的整集的實現.)
在 x<<n x>>n 移位算中, 定了移位操作bit部分必须是无符号数; 被操作的 x 可以是有符号或无符号数. 算上, 一 x<<n 左移算等价于乘以 2^n, x>>n 右移算等价于除以 2^n.
在 x<<n x>>n 移位算中, 定了移位操作bit部分必鬚是無符號數; 被操作的 x 可以是有符號或無符號數. 算上, 一 x<<n 左移算等價於乘以 2^n, x>>n 右移算等價於除以 2^n.
左移算用零填充右空缺的bit位, 无符号数的右移算也是用0填充左空缺的bit位, 但是有符号数的右移运算会用符位的值填充左空缺的bit位. 因为这个原因, 最好用无符号运算, 这样你可以将整数完全作一bit位模式理.
左移算用零填充右空缺的bit位, 無符號數的右移算也是用0填充左空缺的bit位, 但是有符號數的右移運算會用符位的值填充左空缺的bit位. 因爲這個原因, 最好用無符號運算, 這樣你可以將整數完全作一bit位模式理.
管Go提供了无符号数和运算, 即使数值本身不可能出现负数我们还是倾向于使用有符的int型, 就是数组的长度那, 然使用 uint 似乎是一更合理的选择. 事上, 置的 len 函数返回一个有符的int, 我可以像下面这个逆序循环那样处理.
管Go提供了無符號數和運算, 卽使數值本身不可能齣現負數我們還是傾向於使用有符的int型, 就是數組的長度那, 然使用 uint 似乎是一更合理的選擇. 事上, 置的 len 函數返迴一個有符的int, 我可以像下面這個逆序循環那樣處理.
```Go
medals := []string{"gold", "silver", "bronze"}
@@ -117,13 +117,13 @@ for i := len(medals) - 1; i >= 0; i-- {
}
```
另一个选择将是灾难性的. 如果 len 返回一个无符号数, 那 i 也将是无符号的 uint, 然后条件 i >= 0 则永远为真. 在三次迭代之, 也就是 i == 0 , i-- 语句将不会产生 -1, 而是成一uint的最大值(可能是 2^64 - 1), 然 medals[i] 表达式将发生运行时 panic 常(§5.9), 也就是试图访问一个切片范以外的元素.
另一個選擇將是災難性的. 如果 len 返迴一個無符號數, 那 i 也將是無符號的 uint, 然後條件 i >= 0 則永遠爲眞. 在三次迭代之, 也就是 i == 0 , i-- 語句將不會産生 -1, 而是成一uint的最大值(可能是 2^64 - 1), 然 medals[i] 表達式將發生運行時 panic 常(§5.9), 也就是試圖訪問一個切片范以外的元素.
出于这个原因, 无符号数往往有在位算或其它特殊的算常见才会使用, 就像 bit 集合, 分形二进制文件格式, 或者是哈希和加密操作等. 它通常不用于仅仅是表达非负数量的合.
齣於這個原因, 無符號數往往有在位算或其它特殊的算常見纔會使用, 就像 bit 集合, 分形二進製文件格式, 或者是哈希和加密操作等. 它通常不用於僅僅是表達非負數量的合.
一般来说, 需要一个显式的转换将一个值从一种类型转化位另一种类型, 且算术和逻辑运算的二元操作中必是相同的型. 虽然这偶尔会导致很的表式, 但是它消除了所有的型相关的问题, 也使得程序容易理解.
一般來説, 需要一個顯式的轉換將一個值從一種類型轉化位另一種類型, 且算術和邏輯運算的二元操作中必是相同的型. 雖然這偶爾會導致很的表式, 但是它消除了所有的型相關的問題, 也使得程序容易理解.
其他类似场景下, 考下面这个代码:
其他類似場景下, 考下面這個代碼:
```Go
var apples int32 = 1
@@ -131,19 +131,19 @@ var oranges int16 = 2
var compote int = apples + oranges // compile error
```
当尝试编译这三个语句时, 将产生一个错误信息:
當嚐試編譯這三個語句時, 將産生一個錯誤信息:
```
invalid operation: apples + oranges (mismatched types int32 and int16)
```
这种类型不匹配的问题可以有几种不同的方法修复, 最常方法是将它们都显式转型位一个常见类型:
這種類型不匹配的問題可以有幾種不同的方法脩複, 最常方法是將它們都顯式轉型位一個常見類型:
```Go
var compote = int(apples) + int(oranges)
```
如2.5所述, 对于每种类型T, 类型转换操作T(x)将x转换位T型, 如果转换允许的话. 多 整形数之间的相互转换并不会改变数值; 它们只是告诉编译器如何解释这个值. 但是对于将一个大尺寸的整数类型转位一小尺寸的整数类型, 或者是将一个浮点数转位整, 可能会改变数值或失精度:
如2.5所述, 對於每種類型T, 類型轉換操作T(x)將x轉換位T型, 如果轉換允許的話. 多 整形數之間的相互轉換併不會改變數值; 它們隻是告訴編譯器如何解釋這個值. 但是對於將一個大尺寸的整數類型轉位一小尺寸的整數類型, 或者是將一個浮點數轉位整, 可能會改變數值或失精度:
```Go
f := 3.141 // a float64
@@ -153,16 +153,16 @@ f = 1.99
fmt.Println(int(f)) // "1"
```
点数到整数的转换将丢失任何小部分, 向数轴零方向截. 你应该避免操作目标类型表示范围的数值类型转换, 因为截断的行为依赖于具体的实现:
點數到整數的轉換將丟失任何小部分, 向數軸零方向截. 你應該避免操作目標類型表示范圍的數值類型轉換, 因爲截斷的行爲依賴於具體的實現:
```Go
f := 1e100 // a float64
i := int(f) // 果依赖于具体实现
i := int(f) // 果依賴於具體實現
```
任何大小的整字面值都可以用以0始的八进制格式书写, 例如 0666, 或用以0x或0X开头的十六进制格式书写, 例如 0xdeadbeef. 十六进制数字可以用大或小字母. 如今八进制数据通常用POSIX操作系统上的文件访问权限标志, 十六进制数字则更强调数字值的bit位模式.
任何大小的整字面值都可以用以0始的八進製格式書寫, 例如 0666, 或用以0x或0X開頭的十六進製格式書寫, 例如 0xdeadbeef. 十六進製數字可以用大或小字母. 如今八進製數據通常用POSIX操作繫統上的文件訪問權限標誌, 十六進製數字則更強調數字值的bit位模式.
使用 fmt 包打印一个数值时, 我可以用 %d, %o, 或 %x 控制输出的进制格式, 就像下面的例子:
使用 fmt 包打印一個數值時, 我可以用 %d, %o, 或 %x 控製輸齣的進製格式, 就像下面的例子:
```Go
o := 0666
@@ -173,18 +173,18 @@ fmt.Printf("%d %[1]x %#[1]x %#[1]X\n", x)
// 3735928559 deadbeef 0xdeadbeef 0XDEADBEEF
```
请注意 fmt 的两个使用技巧. 通常 Printf 格式化字符串包含多 % 参数时将对应相同量的外操作, 但是 % 之`[1]`词告诉Printf函再次使用第一操作. 第二, % `#`词告诉 Printf 在用 %o, %x 或 %X 输出时生成 0, 0x 或 0X前.
請註意 fmt 的兩個使用技巧. 通常 Printf 格式化字符串包含多 % 參數時將對應相同量的外操作, 但是 % 之`[1]`詞告訴Printf函再次使用第一操作. 第二, % `#`詞告訴 Printf 在用 %o, %x 或 %X 輸齣時生成 0, 0x 或 0X前.
字符面值通过一对单引号直接包含对应字符. 最简单的例子是 ASCII 中似 'a' 字符面值, 但是我可以通过转义的数值来表示任意的Unicode码点对应的字符, 马上将会看到例子.
字符面值通過一對單引號直接包含對應字符. 最簡單的例子是 ASCII 中似 'a' 字符面值, 但是我可以通過轉義的數值來表示任意的Unicode碼點對應的字符, 馬上將會看到例子.
字符使用 `%c` 参数打印, 或者是 `%q` 参数打印带单引号的字符:
字符使用 `%c` 參數打印, 或者是 `%q` 參數打印帶單引號的字符:
```Go
ascii := 'a'
unicode := ''
unicode := ''
newline := '\n'
fmt.Printf("%d %[1]c %[1]q\n", ascii) // "97 a 'a'"
fmt.Printf("%d %[1]c %[1]q\n", unicode) // "22269 ''"
fmt.Printf("%d %[1]c %[1]q\n", unicode) // "22269 ''"
fmt.Printf("%d %[1]q\n", newline) // "10 '\n'"
```

View File

@@ -1,23 +1,23 @@
## 3.2. 浮點數
Go言提供了两种精度的浮点数, float32 和 float64. 它的算术规范由 IEEE754 国际标准定义, 该浮点数规范被所有代的CPU支持.
Go言提供了兩種精度的浮點數, float32 和 float64. 它的算術規范由 IEEE754 國際標準定義, 該浮點數規范被所有代的CPU支持.
这些数值类型的范可以很微小到很大. 浮点数的范围极限值可以在 matn 包找到. 常量 math.MaxFloat32 表示 float32 能表示的最大值, 大是 3.4e38, 对应的 math.MaxFloat64 常量大是 1.8e308. 它能表示的最小值近似分别是1.4e-45 和 4.9e-324.
這些數值類型的范可以很微小到很大. 浮點數的范圍極限值可以在 matn 包找到. 常量 math.MaxFloat32 表示 float32 能表示的最大值, 大是 3.4e38, 對應的 math.MaxFloat64 常量大是 1.8e308. 它能表示的最小值近似分别是1.4e-45 和 4.9e-324.
float32 型的浮点数可以提供大约6个十进制数的精度, 而 float64 可以提供 15个十进制数精度; 通常应该优先使用 float64 型, 因 float32 型的累计计算误差很容易散, 且 float32 能精度表示的正整数并不是很大:
float32 型的浮點數可以提供大約6個十進製數的精度, 而 float64 可以提供 15個十進製數精度; 通常應該優先使用 float64 型, 因 float32 型的纍計計算誤差很容易散, 且 float32 能精度表示的正整數併不是很大:
```Go
var f float32 = 16777216 // 1 << 24
fmt.Println(f == f+1) // "true"!
```
点数的字面值可以直接写小数部分, 想这样:
點數的字面值可以直接寫小數部分, 想這樣:
```Go
const e = 2.71828 // (approximately)
```
数点前面或面的字都可能被省略(例如 .707 或 1.). 很小或很大的最好用科学计数法书写, 通e或E指定指部分:
數點前面或面的字都可能被省略(例如 .707 或 1.). 很小或很大的最好用科學計數法書寫, 通e或E指定指部分:
```Go
const Avogadro = 6.02214129e23
@@ -25,7 +25,7 @@ const Planck = 6.62606957e-34
```
用 Printf 函的 %g 参数打印浮点数, 采用紧凑的表示形式打印, 提供足的精度, 但是对应表格的数据, 使用 %e (带指数) 或 %f 的形式打印可能更合. 所有的这三个打印形式都可以指定打印的度和控打印精度.
用 Printf 函的 %g 參數打印浮點數, 采用緊湊的表示形式打印, 提供足的精度, 但是對應表格的數據, 使用 %e (帶指數) 或 %f 的形式打印可能更合. 所有的這三個打印形式都可以指定打印的度和控打印精度.
```Go
for x := 0; x < 8; x++ {
@@ -33,7 +33,7 @@ for x := 0; x < 8; x++ {
}
```
上面代打印e的, 打印精度是小数点后三个小数精度和8字符度:
上面代打印e的, 打印精度是小數點後三個小數精度和8字符度:
```
x = 0 e^x = 1.000
@@ -46,21 +46,21 @@ x = 6 e^x = 403.429
x = 7 e^x = 1096.633
```
math 包中除了提供大量常用的数学函数外, 提供了IEEE754标准中特殊值的建和测试: 正无穷大和负无穷大, 分别用表示太大溢出的数字和除零的果; 有 NaN 非, 一般用表示效的除法操作果 0/0 或 Sqrt(-1).
math 包中除了提供大量常用的數學函數外, 提供了IEEE754標準中特殊值的建和測試: 正無窮大和負無窮大, 分别用表示太大溢齣的數字和除零的果; 有 NaN 非, 一般用表示效的除法操作果 0/0 或 Sqrt(-1).
```Go
var z float64
fmt.Println(z, -z, 1/z, -1/z, z/z) // "0 -0 +Inf -Inf NaN"
```
math.IsNaN 用于测试一个数是否是非 NaN, math.NaN 则返回非数对应的值. 然可以用 math.NaN 表示一非法的果, 但是测试一个结果是否是非 NaN 是充满风险, 因 NaN 和任何都是不相等的:
math.IsNaN 用於測試一個數是否是非 NaN, math.NaN 則返迴非數對應的值. 然可以用 math.NaN 表示一非法的果, 但是測試一個結果是否是非 NaN 是充滿風險, 因 NaN 和任何都是不相等的:
```Go
nan := math.NaN()
fmt.Println(nan == nan, nan < nan, nan > nan) // "false false false"
```
如果一个函数返回的浮点数结果可能失, 最好的做法是用单独的标志报告失, 像这样:
如果一個函數返迴的浮點數結果可能失, 最好的做法是用單獨的標誌報告失, 像這樣:
```Go
func compute() (value float64, ok bool) {
@@ -72,7 +72,7 @@ func compute() (value float64, ok bool) {
}
```
接下的程序演示了浮点计算图形. 它是带有两个参数的 z = f(x, y) 函的三形式, 使用了可放矢量形(SVG)格式输出, 一个用于矢量线绘制的XML标准. 3.1示了 sin(r)/r 函数的输出图形, 其中 r 是 sqrt(x*x+y*y).
接下的程序演示了浮點計算圖形. 它是帶有兩個參數的 z = f(x, y) 函的三形式, 使用了可放矢量形(SVG)格式輸齣, 一個用於矢量線繪製的XML標準. 3.1示了 sin(r)/r 函數的輸齣圖形, 其中 r 是 sqrt(x*x+y*y).
![](../images/ch3-01.png)
@@ -135,32 +135,32 @@ func f(x, y float64) float64 {
}
```
意的是 corner 返回了两个结果, 对应 corner 的坐标参数.
意的是 corner 返迴了兩個結果, 對應 corner 的坐標參數.
要解程序是如何工作的需要了解基本的何知, 但是我可以跳过几何原理, 因程序的重是演示浮点运算. 程序的本是三不同的坐标系中映射关系, 如3.2所示. 第一是 100x100 的二维网格, 对应整数整数坐标(i,j), 从远处的 (0, 0) 位置始. 我们从远处像前面绘制, 因此远处先绘制的多形有可能被前面后绘制的多形覆.
要解程序是如何工作的需要了解基本的何知, 但是我可以跳過幾何原理, 因程序的重是演示浮點運算. 程序的本是三不同的坐標繫中映射關繫, 如3.2所示. 第一是 100x100 的二維網格, 對應整數整數坐標(i,j), 從遠處的 (0, 0) 位置始. 我們從遠處像前面繪製, 因此遠處先繪製的多形有可能被前面後繪製的多形覆.
第二个坐标系是一个三维的网格浮点坐标(x,y,z), 其中x和y是i和j的线性函, 通平移转换位center的中心, 然用xyrange系数缩放. 高度z是函f(x,y)的值.
第二個坐標繫是一個三維的網格浮點坐標(x,y,z), 其中x和y是i和j的性函, 通平移轉換位center的中心, 然用xyrange繫數縮放. 高度z是函f(x,y)的值.
第三个坐标系是一个二维的画布, 起(0,0)在左上角. 布中的坐用(sx, sy)表示. 我使用等角投影将三维点
第三個坐標繫是一個二維的畵布, 起(0,0)在左上角. 布中的坐用(sx, sy)表示. 我使用等角投影將三維點
![](../images/ch3-02.png)
(x,y,z) 投影到二维的画布中. 布中从远处到右边的点对应较大的x值和大的y值. 并且画布中x和y值越大, 则对应的z值越小. x和y的垂直和水平缩放系数来自30度角的正弦和余弦值. z的缩放系数0.4, 是一任意选择的参数.
(x,y,z) 投影到二維的畵布中. 布中從遠處到右邊的點對應較大的x值和大的y值. 併且畵布中x和y值越大, 則對應的z值越小. x和y的垂直和水平縮放繫數來自30度角的正絃和餘絃值. z的縮放繫數0.4, 是一任意選擇的參數.
对于二维网格中的每一个单位, main函数计算单元的四个顶点在画布中对应多边形ABCD的顶点, 其中B对应(i,j)顶点位置, A, C, 和 D是相邻的顶点, 然后输出SVG的绘制指令.
對於二維網格中的每一個單位, main函數計算單元的四個頂點在畵布中對應多邊形ABCD的頂點, 其中B對應(i,j)頂點位置, A, C, 和 D是相鄰的頂點, 然後輸齣SVG的繪製指令.
**练习3.1:** 如果 f 函数返回的是无限制的 float64 值, 那SVG文件可能输出无效的<polygon>形元素(虽然许多SVG渲染器妥善处理这类问题). 改程序跳过无效的多形.
**練習3.1:** 如果 f 函數返迴的是無限製的 float64 值, 那SVG文件可能輸齣無效的<polygon>形元素(雖然許多SVG渲染器妥善處理這類問題). 改程序跳過無效的多形.
**练习3.2:** 试验math包中其他函的渲染形. 你是否能输出一个egg box, moguls, 或 a saddle 案?
**練習3.2:** 試驗math包中其他函的渲染形. 你是否能輸齣一個egg box, moguls, 或 a saddle 案?
**练习3.3:**根高度给每个多边形上色, 那样峰值部将是红色(#ff0000), 谷部将是蓝色(#0000ff).
**練習3.3:**根高度給每個多邊形上色, 那樣峯值部將是紅色(#ff0000), 谷部將是藍色(#0000ff).
**3.4:** 考1.7Lissajous例子的函, 造一web服器, 用于计算函数曲面然后返回SVG数据给客户端. 服器必须设置 Content-Type 部:
**3.4:** 考1.7Lissajous例子的函, 造一web服器, 用於計算函數麴面然後返迴SVG數據給客戶端. 服器必鬚設置 Content-Type 部:
```Go
w.Header().Set("Content-Type", "image/svg+xml")
```
(一步在Lissajous例子中不是必的, 因为服务器使用标准的PNG像格式, 可以根前面的512个字节自动输出对应的头部.) 允许客户端通HTTP请求参数设置高度, 度, 和色等参数.
(一步在Lissajous例子中不是必的, 因爲服務器使用標準的PNG像格式, 可以根前面的512個字節自動輸齣對應的頭部.) 允許客戶端通HTTP請求參數設置高度, 度, 和色等參數.

View File

@@ -1,7 +1,7 @@
## 3.3. 複數
Go提供了两种精度的复数类似, complex64 和 complex128, 分别对应 float32 和 float64精度. 置的 complex 函数用于构建复数, 建的 real 和 imag 函数返回复数的实部和部:
Go提供了兩種精度的複數類似, complex64 和 complex128, 分别對應 float32 和 float64精度. 置的 complex 函數用於構建複數, 建的 real 和 imag 函數返迴複數的實部和部:
```Go
var x complex128 = complex(1, 2) // 1+2i
@@ -11,28 +11,28 @@ fmt.Println(real(x*y)) // "-5"
fmt.Println(imag(x*y)) // "10"
```
如果一个浮点数面值或一个十进制整数面值面跟着一i, 例如 3.141592i 或 2i, 它将构成一个复数的虚部, 复数的实部是0:
如果一個浮點數面值或一個十進製整數面值面跟着一i, 例如 3.141592i 或 2i, 它將構成一個複數的虛部, 複數的實部是0:
```Go
fmt.Println(1i * 1i) // "(-1+0i)", i^2 = -1
```
在常量算术规则下, 一个复数常量可以加到另一常量(整或浮点数, 部或部), 我可以用自然的方式写复数, 就像 1+2i, 或之等价的写法 2i+1. 上面x和y的声明语句还可以化:
在常量算術規則下, 一個複數常量可以加到另一常量(整或浮點數, 部或部), 我可以用自然的方式寫複數, 就像 1+2i, 或之等價的寫法 2i+1. 上面x和y的聲明語句還可以化:
```Go
x := 1 + 2i
y := 3 + 4i
```
复数也可以用 == 和 != 行相等比. 只有两个复数的实部和部都相等的候它们才是相等的.
複數也可以用 == 和 != 行相等比. 隻有兩個複數的實部和部都相等的候它們纔是相等的.
math/cmplx 包提供了复数处理的多函, 例如求复数的平方根函和求幂函数.
math/cmplx 包提供了複數處理的多函, 例如求複數的平方根函和求冪函數.
```Go
fmt.Println(cmplx.Sqrt(-1)) // "(0+1i)"
```
下面的程序使用complex128复数算法生成一Mandelbrot像.
下面的程序使用complex128複數算法生成一Mandelbrot像.
```Go
gopl.io/ch3/mandelbrot
@@ -83,19 +83,19 @@ func mandelbrot(z complex128) color.Color {
}
```
1024x1024像每个点的两个嵌套的循环对应 -2 到 +2 区间的复数平面. 程序反复测试每个点对应复数值平方值加一增量值对应的点是否超出半径为2的. 如果超了, 通过根据逃逸的迭代次数对应的灰度颜色来代替. 如果不是, 该点属于Mandelbrot集合, 使用黑色颜色标记. 最程序生成的PNG格式分形图像图像输出到标准输出, 如3.3所示.
1024x1024像每個點的兩個嵌套的循環對應 -2 到 +2 區間的複數平面. 程序反複測試每個點對應複數值平方值加一增量值對應的點是否超齣半徑爲2的. 如果超了, 通過根據逃逸的迭代次數對應的灰度顔色來代替. 如果不是, 該點屬於Mandelbrot集合, 使用黑色顔色標記. 最程序生成的PNG格式分形圖像圖像輸齣到標準輸齣, 如3.3所示.
**练习3.5:** 实现一个彩色的Mandelbrot像, 使用 image.NewRGBA 创建图像, 使用 color.RGBA 或 color.YCbCr 生成色.
**練習3.5:** 實現一個綵色的Mandelbrot像, 使用 image.NewRGBA 創建圖像, 使用 color.RGBA 或 color.YCbCr 生成色.
**练习3.6:** 超采样技术可以降低每像素对计算颜色值和平均值的影. 简单的方法是将每个像素分层四个子像素, 实现它.
**練習3.6:** 超采樣技術可以降低每像素對計算顔色值和平均值的影. 簡單的方法是將每個像素分層四個子像素, 實現它.
**练习3.7:** 另一生成分形像的方式是使用牛顿法来求解一个复数方程, 例如 z^4 1 = 0. 每个起点到四根的迭代次数对应阴影的灰度. 方程根对应的点用颜色表示.
**練習3.7:** 另一生成分形像的方式是使用牛頓法來求解一個複數方程, 例如 z^4 1 = 0. 每個起點到四根的迭代次數對應陰影的灰度. 方程根對應的點用顔色表示.
![](../images/ch3-03.png)
**练习3.8:**提高精度生成更多别的分形. 使用四不同精度型的数字实现相同的分形: complex64, complex128, big.Float, and big.Rat. (后面两种类型在 math/big 包明. Float是有指定限精度的浮点数; Rat是效精度的有理.) 它们间的性能和存使用比如何? 渲染图可见时缩放的别是多少?
**練習3.8:**提高精度生成更多别的分形. 使用四不同精度型的數字實現相同的分形: complex64, complex128, big.Float, and big.Rat. (後面兩種類型在 math/big 包明. Float是有指定限精度的浮點數; Rat是效精度的有理.) 它們間的性能和存使用比如何? 渲染圖可見時縮放的别是多少?
**练习3.9:** 编写一个web服器, 用于给客户端生成分形的像. 行客端用HTTP参数参数指定x,y和zoom参数.
**練習3.9:** 編寫一個web服器, 用於給客戶端生成分形的像. 行客端用HTTP參數參數指定x,y和zoom參數.

View File

@@ -1,15 +1,15 @@
### 3.5.4. 字符串和Byte切片
标准库中有四个包对字符串理尤重要: bytes, strings, strconv, 和 unicode. strings 包提供了多如字符串的查询, 替, 比, 截, 拆分, 和合等功能.
標準庫中有四個包對字符串理尤重要: bytes, strings, strconv, 和 unicode. strings 包提供了多如字符串的査詢, 替, 比, 截, 拆分, 和合等功能.
bytes 包也提供了很多似功能的函, 但是针对和字符串有着相同结构的 []byte 型. 因字符串是只读的, 因此逐步建字符串会导致很多分配和复制. 在这种情况下, 使用 bytes.Buffer 类型会更有效, 稍后我们将展示.
bytes 包也提供了很多似功能的函, 但是針對和字符串有着相同結構的 []byte 型. 因字符串是隻讀的, 因此逐步建字符串會導致很多分配和複製. 在這種情況下, 使用 bytes.Buffer 類型會更有效, 稍後我們將展示.
strconv 包提供了 布型, 整型, 浮点数和对应字符串的相互转换, 提供了双引号的字符串面值形式的转换.
strconv 包提供了 布型, 整型, 浮點數和對應字符串的相互轉換, 提供了雙引號的字符串面值形式的轉換.
unicode 包提供了似 IsDigit, IsLetter, IsUpper, 和 IsLower 等功能, 它们用于给字符分. 每个函数有一个单一的rune型的参数, 然后返回一个布尔值. 像 ToUpper 和 ToLower 之类的转换函数将用于rune字符的大小写转换. 所有的些函都是遵循Unicode标准定义的字母,字等分类规范. strings 包也有似的函, 它是 ToUpper 和 ToLower, 原始字符串的每字符都做相应的转换, 然后返回新的字符串.
unicode 包提供了似 IsDigit, IsLetter, IsUpper, 和 IsLower 等功能, 它們用於給字符分. 每個函數有一個單一的rune型的參數, 然後返迴一個布爾值. 像 ToUpper 和 ToLower 之類的轉換函數將用於rune字符的大小寫轉換. 所有的些函都是遵循Unicode標準定義的字母,字等分類規范. strings 包也有似的函, 它是 ToUpper 和 ToLower, 原始字符串的每字符都做相應的轉換, 然後返迴新的字符串.
下面的 basename 函数的灵感由Unix shell的同名工具而. 在我们实现的版本中, basename(s) 看起像是系统路径的前缀删除, 同时将看似文件型的后缀名删除:
下面的 basename 函數的靈感由Unix shell的同名工具而. 在我們實現的版本中, basename(s) 看起像是繫統路徑的前綴刪除, 同時將看似文件型的後綴名刪除:
```Go
fmt.Println(basename("a/b/c.go")) // "c"
@@ -17,7 +17,7 @@ fmt.Println(basename("c.d.go")) // "c.d"
fmt.Println(basename("abc")) // "abc"
```
第一版本并没有使用任何, 全部手工实现:
第一版本併沒有使用任何, 全部手工實現:
```Go
gopl.io/ch3/basename1
@@ -42,7 +42,7 @@ func basename(s string) string {
}
```
个简化的版本使用了 strings.LastIndex 库函数:
個簡化的版本使用了 strings.LastIndex 庫函數:
```Go
gopl.io/ch3/basename2
@@ -57,10 +57,10 @@ func basename(s string) string {
}
```
path 和 path/filepath 包提供了关于文件名更一般的函操作. 使用斜分隔路可以在任何操作系统上工作. 斜本身不应该用于文件名, 但是在其他一些域可能是有效的, 例如URL路径组件. 相比之下, path/filepath 包使用操作系统本身的路径规则, 例如 POSIX 系统使用 /foo/bar, Microsoft Windows 使用 c:\foo\bar 等.
path 和 path/filepath 包提供了關於文件名更一般的函操作. 使用斜分隔路可以在任何操作繫統上工作. 斜本身不應該用於文件名, 但是在其他一些域可能是有效的, 例如URL路徑組件. 相比之下, path/filepath 包使用操作繫統本身的路徑規則, 例如 POSIX 繫統使用 /foo/bar, Microsoft Windows 使用 c:\foo\bar 等.
让我们继续另一字符串的例子. 任务是将一个表示整值的字符串, 每隔三字符插入一个逗号, 例如 "12345" 处理后成为 "12,345". 这个版本只适用于整数类型; 支持浮点数类型的支持留做练习.
讓我們繼續另一字符串的例子. 任務是將一個表示整值的字符串, 每隔三字符插入一個逗號, 例如 "12345" 處理後成爲 "12,345". 這個版本隻適用於整數類型; 支持浮點數類型的支持留做練習.
```Go
gopl.io/ch3/comma
@@ -75,11 +75,11 @@ func comma(s string) string {
}
```
入 comma 的参数是一字符串. 如果入字符串的度小或等3的, 不需要插入逗. 否, comma 在最后三个字符前切割为两个两个子串, 然用前面的子串递归调用自身.
入 comma 的參數是一字符串. 如果入字符串的度小或等3的, 不需要插入逗. 否, comma 在最後三個字符前切割爲兩個兩個子串, 然用前面的子串遞歸調用自身.
字符串包含的字节数组, 一旦建, 是不可的. 相比之下, 一个字节切片的原始可以自由地改.
字符串包含的字節數組, 一旦建, 是不可的. 相比之下, 一個字節切片的原始可以自由地改.
字符串和字切片可以相互转换:
字符串和字切片可以相互轉換:
```Go
s := "abc"
@@ -87,9 +87,9 @@ b := []byte(s)
s2 := string(b)
```
概念上, []byte(s) 转换是分配了一新的字节数组保存了字符串数据的拷, 然引用这个字节数组. 编译器的化可以避免在一些景下分配和复制字符串数据, 但总的来说需要保在b被改的情下, 原始的s字符串也不会改变. 将一个字节切片到字符串的 string(b) 操作则是构造一个拷贝, 以保s2字符串是只读的.
概念上, []byte(s) 轉換是分配了一新的字節數組保存了字符串數據的拷, 然引用這個字節數組. 編譯器的化可以避免在一些景下分配和複製字符串數據, 但總的來説需要保在b被改的情下, 原始的s字符串也不會改變. 將一個字節切片到字符串的 string(b) 操作則是構造一個拷貝, 以保s2字符串是隻讀的.
了避免转换中不必要的存分配, bytes包和strings同提供了许多类似的用函. 下面是strings包中的六个函数:
了避免轉換中不必要的存分配, bytes包和strings同提供了許多類似的用函. 下面是strings包中的六個函數:
```Go
func Contains(s, substr string) bool
@@ -100,7 +100,7 @@ func Index(s, sep string) int
func Join(a []string, sep string) string
```
bytes 包中对应的六个函数:
bytes 包中對應的六個函數:
```Go
func Contains(b, subslice []byte) bool
@@ -111,9 +111,9 @@ func Index(s, sep []byte) int
func Join(s [][]byte, sep []byte) []byte
```
唯一的别是字符串类型参数被替成了字切片型的参数.
唯一的别是字符串類型參數被替成了字切片型的參數.
bytes 包提供了 Buffer 型用于字节切片的存. 一 Buffer 始是空的, 但是着 string, byte, 和 []byte 等类型数据的写入可以动态增长, 一 bytes.Buffer 变量并不需要理化, 因此零值也是有效的:
bytes 包提供了 Buffer 型用於字節切片的存. 一 Buffer 始是空的, 但是着 string, byte, 和 []byte 等類型數據的寫入可以動態增長, 一 bytes.Buffer 變量併不需要理化, 因此零值也是有效的:
```Go
gopl.io/ch3/printints
@@ -137,16 +137,16 @@ func main() {
}
```
向 bytes.Buffer 添加任意字符的UTF8编码, 最好使用 bytes.Buffer 的 WriteRune 方法, 但是 WriteByte 方法对于写入类似 '[' 和 ']' 等 ASCII 字符更有效.
向 bytes.Buffer 添加任意字符的UTF8編碼, 最好使用 bytes.Buffer 的 WriteRune 方法, 但是 WriteByte 方法對於寫入類似 '[' 和 ']' 等 ASCII 字符更有效.
bytes.Buffer 型有着诸多实用的功能, 我在第七章讨论接口时层涉及到, 我们将看看如何它用作一I/O 的入和输出对象, 例如 Fprintf 的 io.Writer 输出, 或作为输入源 io.Reader.
bytes.Buffer 型有着諸多實用的功能, 我在第七章討論接口時層涉及到, 我們將看看如何它用作一I/O 的入和輸齣對象, 例如 Fprintf 的 io.Writer 輸齣, 或作爲輸入源 io.Reader.
**练习3.10:** 编写一个非递归版本的comma函, 使用 bytes.Buffer 代替字符串接操作.
**練習3.10:** 編寫一個非遞歸版本的comma函, 使用 bytes.Buffer 代替字符串接操作.
**练习3.11:** 完善 comma 函, 以支持浮点数处理和一个可选的正负号处理.
**練習3.11:** 完善 comma 函, 以支持浮點數處理和一個可選的正負號處理.
**练习3.12:** 编写一个函数, 判断两个字符串是否是是相互打的, 也就是说它们有着相同的字符, 但是对应不同的序.
**練習3.12:** 編寫一個函數, 判斷兩個字符串是否是是相互打的, 也就是説它們有着相同的字符, 但是對應不同的序.

View File

@@ -1,9 +1,9 @@
### 3.6.1. iota 常量生成器
常量明可以使用 iota 常量生成器, 用生成一相似的常量值, 但是不用每行都一遍. 在一 const 声明语句中, 在始一行 iota 将会被置0, 然在每一有常量明的行加一.
常量明可以使用 iota 常量生成器, 用生成一相似的常量值, 但是不用每行都一遍. 在一 const 聲明語句中, 在始一行 iota 將會被置0, 然在每一有常量明的行加一.
下面是自 time 包的例子, 它首先定了Weekday命名型, 然后为一周的每天定义一个常量, 从周日0始. 这种类型一般被称为枚举类型.
下面是自 time 包的例子, 它首先定了Weekday命名型, 然後爲一週的每天定義一個常量, 從週日0始. 這種類型一般被稱爲枚舉類型.
```Go
type Weekday int
@@ -19,9 +19,9 @@ const (
)
```
周一将对应0, 周一为1, 如此等等.
週一將對應0, 週一爲1, 如此等等.
也可以在复杂的常量表式中使用 iota, 下面是自 net 包的例子, 用于给一个无符号整数的最低5bit的每bit定一名字:
也可以在複雜的常量表式中使用 iota, 下面是自 net 包的例子, 用於給一個無符號整數的最低5bit的每bit定一名字:
```Go
type Flags uint
@@ -35,7 +35,7 @@ const (
)
```
着 iota 的增, 每常量对应表达式 1 << iota, 连续的2的, 分别对应一个bit位置. 使用些常量可以测试, , 或清除对应的bit位的值:
着 iota 的增, 每常量對應表達式 1 << iota, 連續的2的, 分别對應一個bit位置. 使用些常量可以測試, , 或清除對應的bit位的值:
```Go
gopl.io/ch3/netflag
@@ -56,7 +56,7 @@ unc main() {
}
```
下面是一个更复杂的例子, 常量都是1024的:
下面是一個更複雜的例子, 常量都是1024的:
```Go
const (
@@ -72,8 +72,8 @@ const (
)
```
iota 机制也有其局限性. 例如, 不能用于产生1000的(KB,MB,等等), 为并没有计算幂的运算符.
iota 機製也有其局限性. 例如, 不能用於産生1000的(KB,MB,等等), 爲併沒有計算冪的運算符.
**练习3.13:** 编写KB,MB的常量, 后扩展到YB.
**練習3.13:** 編寫KB,MB的常量, 後擴展到YB.

View File

@@ -1,15 +1,15 @@
### 3.6.2. 無類型常量
Go言的常量有点不寻常. 然一常量可以有任意有一个确定的基础类型, 例如 int 或 float64, 或者是似 time.Duration 这样命名的基础类型, 但是多常量并没有一个明确的基础类型. 编译期为这些没有明的基础类型的字常量提供比基础类型或器更高精度的算术运算; 你可以认为至少有256bit的算精度. 里有六未明确类型的常量型, 分别是 无类型的布型, 无类型的整, 无类型的字符, 无类型的浮点数, 无类型的复数, 无类型的字符串.
Go言的常量有點不尋常. 然一常量可以有任意有一個確定的基礎類型, 例如 int 或 float64, 或者是似 time.Duration 這樣命名的基礎類型, 但是多常量併沒有一個明確的基礎類型. 編譯期爲這些沒有明的基礎類型的字常量提供比基礎類型或器更高精度的算術運算; 你可以認爲至少有256bit的算精度. 里有六未明確類型的常量型, 分别是 無類型的布型, 無類型的整, 無類型的字符, 無類型的浮點數, 無類型的複數, 無類型的字符串.
过延迟明确具体类型, 无类型的常量不可以提供更高的精度, 而且可以直接用更多的表式而不需要类型转换. 例如 例子中的 ZiB 和 YiB 的值已经超出任何Go中整数类型能表的范, 但是它依然是合法的常量, 而且可以像下面表达式这样使用:
過延遲明確具體類型, 無類型的常量不可以提供更高的精度, 而且可以直接用更多的表式而不需要類型轉換. 例如 例子中的 ZiB 和 YiB 的值已經超齣任何Go中整數類型能表的范, 但是它依然是合法的常量, 而且可以像下面表達式這樣使用:
```Go
fmt.Println(YiB/ZiB) // "1024"
```
另一例子, math.Pi 无类型的浮点数常量, 可以直接用任意需要浮点数或复数的地方:
另一例子, math.Pi 無類型的浮點數常量, 可以直接用任意需要浮點數或複數的地方:
```Go
var x float32 = math.Pi
@@ -17,7 +17,7 @@ var y float64 = math.Pi
var z complex128 = math.Pi
```
如果 math.Pi 被确定为特定型, 比如 float64, 那么结果精度可能不一, 同时对于需要float32或complex128型值的地方需要一个明确的类型转换:
如果 math.Pi 被確定爲特定型, 比如 float64, 那麽結果精度可能不一, 同時對於需要float32或complex128型值的地方需要一個明確的類型轉換:
```Go
const Pi64 float64 = math.Pi
@@ -27,9 +27,9 @@ var y float64 = Pi64
var z complex128 = complex128(Pi64)
```
对于常量面值, 不同的写法对应不同的型. 例如 0, 0.0, 0i, 和 '\u0000' 然有着相同的常量值, 但是它分别对应无类型的整数,无类型的浮点数,无类型的复数,和无类型的字符等不同的常量型. 同, true 和 false 也是无类型的布尔类型, 字符串面值常量是无类型的字符串.
對於常量面值, 不同的寫法對應不同的型. 例如 0, 0.0, 0i, 和 '\u0000' 然有着相同的常量值, 但是它分别對應無類型的整數,無類型的浮點數,無類型的複數,和無類型的字符等不同的常量型. 同, true 和 false 也是無類型的布爾類型, 字符串面值常量是無類型的字符串.
前面说过除法算符 / 根操作数的类型生成对应类型的果. 因此, 不同法的常量除法表式可能对应不同的果:
前面説過除法算符 / 根操作數的類型生成對應類型的果. 因此, 不同法的常量除法表式可能對應不同的果:
```Go
var f float64 = 212
@@ -38,7 +38,7 @@ fmt.Println(5 / 9 * (f - 32)) // "0"; 5/9 is an untyped integer, 0
fmt.Println(5.0 / 9.0 * (f - 32)) // "100"; 5.0/9.0 is an untyped float
```
有常量可以是无类型的. 当一个无类型的常量被赋值给一个变量, 就像上面的第一行句, 或者是像其余三个语句中右边表达式中含有明确类型的值, 无类型的常量将会被隐式转换为对应的类型, 如果可能的.
有常量可以是無類型的. 當一個無類型的常量被賦值給一個變量, 就像上面的第一行句, 或者是像其餘三個語句中右邊表達式中含有明確類型的值, 無類型的常量將會被隱式轉換爲對應的類型, 如果可能的.
```Go
var f float64 = 3 + 0i // untyped complex -> float64
@@ -47,7 +47,7 @@ f = 1e123 // untyped floating-point -> float64
f = 'a' // untyped rune -> float64
```
上面的句相当于:
上面的句相當於:
```Go
var f float64 = float64(3 + 0i)
@@ -56,7 +56,7 @@ f = float64(1e123)
f = float64('a')
```
无论是隐式或式, 将一种类型转换为另一种类型要求目可以表示原始值. 对于浮点数和复数, 可能有舍入理:
無論是隱式或式, 將一種類型轉換爲另一種類型要求目可以表示原始值. 對於浮點數和複數, 可能有舍入理:
```Go
const (
@@ -70,7 +70,7 @@ const (
)
```
对于一个没有显式类型的变量声明(包括短变量声明语法), 无类型的常量会被隐式转为默认的变量类型, 就像下面的例子:
對於一個沒有顯式類型的變量聲明(包括短變量聲明語法), 無類型的常量會被隱式轉爲默認的變量類型, 就像下面的例子:
```Go
i := 0 // untyped integer; implicit int(0)
@@ -79,16 +79,16 @@ f := 0.0 // untyped floating-point; implicit float64(0.0)
c := 0i // untyped complex; implicit complex128(0i)
```
意默认类型是规则的: 无类型的整常量默认转换为int, 对应不确定的尺寸, 但是浮点数好复数常量则默认转换为float64和complex128. Go言本身并没有不定的尺寸的浮点数和复数类型, 因如何不知道浮点数类型的话很难写出正确的数值算法.
意默認類型是規則的: 無類型的整常量默認轉換爲int, 對應不確定的尺寸, 但是浮點數好複數常量則默認轉換爲float64和complex128. Go言本身併沒有不定的尺寸的浮點數和複數類型, 因如何不知道浮點數類型的話很難寫齣正確的數值算法.
如果要给变量一不同的型, 我们必须显式地将无类型的常量转化为所需的型, 或给声明的量指定型, 像下面例子这样:
如果要給變量一不同的型, 我們必鬚顯式地將無類型的常量轉化爲所需的型, 或給聲明的量指定型, 像下面例子這樣:
```Go
var i = int8(0)
var i int8 = 0
```
当尝试将这些无类型的常量转为一个接口值时(见第7章), 些默认类型将显得尤重要, 因要靠它们明确接口对应的动态类型.
當嚐試將這些無類型的常量轉爲一個接口值時(見第7章), 些默認類型將顯得尤重要, 因要靠它們明確接口對應的動態類型.
```Go
fmt.Printf("%T\n", 0) // "int"
@@ -97,7 +97,7 @@ fmt.Printf("%T\n", 0i) // "complex128"
fmt.Printf("%T\n", '\000') // "int32" (rune)
```
在我们已经讲述了Go言中全部的基础数据类型. 下一步演示如何用基础数据类型组合成数组或结构体等复杂数据类型, 然后构建用于解决实际编程问题的数据结构, 这将是第四章的讨论主题.
在我們已經講述了Go言中全部的基礎數據類型. 下一步演示如何用基礎數據類型組合成數組或結構體等複雜數據類型, 然後構建用於解決實際編程問題的數據結構, 這將是第四章的討論主題.

View File

@@ -1,15 +1,15 @@
## 3.6. 常量
常量表式的值在编译期计算, 而不是在行期. 每常量的潜在类型都是基础类型: boolean, string, 或字.
常量表式的值在編譯期計算, 而不是在行期. 每常量的潛在類型都是基礎類型: boolean, string, 或字.
常量的声明语句定了常量的名字, 和量的声明语法类似, 常量的值不可改, 这样可以防止在行期被意外或意的改. 例如, 常量比量更合用于表达像 π 之类的数学常数, 因为它们的值不会变化:
常量的聲明語句定了常量的名字, 和量的聲明語法類似, 常量的值不可改, 這樣可以防止在行期被意外或意的改. 例如, 常量比量更合用於表達像 π 之類的數學常數, 因爲它們的值不會變化:
```Go
const pi = 3.14159 // approximately; math.Pi is a better approximation
```
变量声明一, 可以批量明多常量; 这比较适合声明一组相关的常量:
變量聲明一, 可以批量明多常量; 這比較適合聲明一組相關的常量:
```Go
const (
@@ -18,11 +18,11 @@ const (
)
```
多常量的算可以在编译期完成, 这样可以减少运行时的工作, 也方便其他编译优化. 操作是常量, 一些运行时的错误可以在编译时发现, 例如整除零, 字符串索引越界, 任何导致无效浮点数的操作等.
多常量的算可以在編譯期完成, 這樣可以減少運行時的工作, 也方便其他編譯優化. 操作是常量, 一些運行時的錯誤可以在編譯時發現, 例如整除零, 字符串索引越界, 任何導致無效浮點數的操作等.
常量的所有算术运算, 逻辑运算和比较运算的果也是常量, 常量的类型转换操作或以下函数调用都是返常量果: len, cap, real, imag, complex, 和 unsafe.Sizeof(§13.1).
常量的所有算術運算, 邏輯運算和比較運算的果也是常量, 常量的類型轉換操作或以下函數調用都是返常量果: len, cap, real, imag, complex, 和 unsafe.Sizeof(§13.1).
为它们的值是在编译期就定的, 因此常量可以是构成类型的一部分, 例如用指定数组类型的度:
爲它們的值是在編譯期就定的, 因此常量可以是構成類型的一部分, 例如用指定數組類型的度:
```Go
const IPv4Len = 4
@@ -34,7 +34,7 @@ func parseIPv4(s string) IP {
}
```
常量的明也可以包含一个类型和一值, 但是如果没有显式指明型, 那么将从右边的表式推断类型. 在下面的代中, time.Duration 是一命名型, 底层类型是 int64, time.Minute 是对应类型的常量. 下面明的两个常量都是 time.Duration 型, 可以通 %T 参数打印型信息:
常量的明也可以包含一個類型和一值, 但是如果沒有顯式指明型, 那麽將從右邊的表式推斷類型. 在下面的代中, time.Duration 是一命名型, 底層類型是 int64, time.Minute 是對應類型的常量. 下面明的兩個常量都是 time.Duration 型, 可以通 %T 參數打印型信息:
```Go
const noDelay time.Duration = 0
@@ -44,7 +44,7 @@ fmt.Printf("%T %[1]v\n", timeout) // "time.Duration 5m0s
fmt.Printf("%T %[1]v\n", time.Minute) // "time.Duration 1m0s"
```
如果是批量明的常量, 除了第一外其他常量的右的表生可以省略, 如果省略表示使用前面的表式, 对应的常量型也一. 例如:
如果是批量明的常量, 除了第一外其他常量的右的表生可以省略, 如果省略表示使用前面的表式, 對應的常量型也一. 例如:
```Go
const (
@@ -57,7 +57,7 @@ const (
fmt.Println(a, b, c, d) // "1 1 2 2"
```
如果只是简单地复制右边的常量表式, 并没有太用的值. 但是它可以带来其他的特性, 那就是 iota 常量生成器.
如果隻是簡單地複製右邊的常量表式, 併沒有太用的值. 但是它可以帶來其他的特性, 那就是 iota 常量生成器.
{% include "./ch3-06-1.md" %}