Merge branch 'master' of github.com:gopl-zh/gopl-zh.github.com

This commit is contained in:
Xargin 2016-08-24 15:44:11 +08:00
commit d4358fe46f
9 changed files with 13 additions and 26 deletions

View File

@ -8,7 +8,7 @@ Go语言同时提供了有符号和无符号类型的整数运算。这里有int
Unicode字符rune类型是和int32等价的类型通常用于表示一个Unicode码点。这两个名称可以互换使用。同样byte也是uint8类型的等价类型byte类型一般用于强调数值是一个原始的数据而不是一个小的整数。 Unicode字符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类型的地方需要一个显式的类型转换操作反之亦然。

View File

@ -2,7 +2,7 @@
一个布尔类型的值只有两种true和false。if和for语句的条件部分都是布尔类型的值并且==和<等比较操作也会产生布尔型的值一元操作符`!`对应逻辑非操作因此`!true`的值为`false`更罗嗦的说法是`(!true==false)==true`虽然表达方式不一样不过我们一般会采用简洁的布尔表达式就像用x来表示`x==true`。 一个布尔类型的值只有两种true和false。if和for语句的条件部分都是布尔类型的值并且==和<等比较操作也会产生布尔型的值一元操作符`!`对应逻辑非操作因此`!true`的值为`false`更罗嗦的说法是`(!true==false)==true`虽然表达方式不一样不过我们一般会采用简洁的布尔表达式就像用x来表示`x==true`。
布尔值可以和&&AND和||OR操作符结合并且可能会有短路行为:如果运算符左边值已经可以确定整个布尔表达式的值,那么运算符右边的值将不在被求值,因此下面的表达式总是安全的: 布尔值可以和&&AND和||OR操作符结合并且有短路行为如果运算符左边值已经可以确定整个布尔表达式的值那么运算符右边的值将不在被求值因此下面的表达式总是安全的
```Go ```Go
s != "" && s[0] == 'x' s != "" && s[0] == 'x'
@ -47,6 +47,3 @@ func btoi(b bool) int {
// itob reports whether i is non-zero. // itob reports whether i is non-zero.
func itob(i int) bool { return i != 0 } func itob(i int) bool { return i != 0 }
``` ```

View File

@ -27,7 +27,7 @@
可以通过十六进制或八进制转义在字符串面值包含任意的字节。一个十六进制的转义形式是\xhh其中两个h表示十六进制数字大写或小写都可以。一个八进制转义形式是\ooo包含三个八进制的o数字0到7但是不能超过`\377`译注对应一个字节的范围十进制为255。每一个单一的字节表达一个特定的值。稍后我们将看到如何将一个Unicode码点写到字符串面值中。 可以通过十六进制或八进制转义在字符串面值包含任意的字节。一个十六进制的转义形式是\xhh其中两个h表示十六进制数字大写或小写都可以。一个八进制转义形式是\ooo包含三个八进制的o数字0到7但是不能超过`\377`译注对应一个字节的范围十进制为255。每一个单一的字节表达一个特定的值。稍后我们将看到如何将一个Unicode码点写到字符串面值中。
一个原生的字符串面值形式是`...`,使用反引号```代替双引号。在原生的字符串面值中,没有转义操作;全部的内容都是字面的意思,包含退格和换行,因此一个程序中的原生字符串面值可能跨越多行(译注:在原生字符串面值内部是无法直接写```字符的,可以用八进制或十六进制转义或+"```"链接字符串常量完成。唯一的特殊处理是会删除回车以保证在所有平台上的值都是一样的包括那些把回车也放入文本文件的系统译注Windows系统会把回车和换行一起放入文本文件中 一个原生的字符串面值形式是\`...\`,使用反引号代替双引号。在原生的字符串面值中,没有转义操作;全部的内容都是字面的意思,包含退格和换行,因此一个程序中的原生字符串面值可能跨越多行(译注:在原生字符串面值内部是无法直接写\`字符的,可以用八进制或十六进制转义或+"\`"链接字符串常量完成。唯一的特殊处理是会删除回车以保证在所有平台上的值都是一样的包括那些把回车也放入文本文件的系统译注Windows系统会把回车和换行一起放入文本文件中
原生字符串面值用于编写正则表达式会很方便因为正则表达式往往会包含很多反斜杠。原生字符串面值同时被广泛应用于HTML模板、JSON面值、命令行提示信息以及那些需要扩展到多行的场景。 原生字符串面值用于编写正则表达式会很方便因为正则表达式往往会包含很多反斜杠。原生字符串面值同时被广泛应用于HTML模板、JSON面值、命令行提示信息以及那些需要扩展到多行的场景。
@ -38,8 +38,3 @@ Usage:
go command [arguments] go command [arguments]
...` ...`
``` ```

View File

@ -1,13 +1,9 @@
### 3.5.2. Unicode ### 3.5.2. Unicode
在很久以前世界还是比较简单的起码计算机世界就只有一个ASCII字符集美国信息交换标准代码。ASCII更准确地说是美国的ASCII使用7bit来表示128个字符包含英文字母的大小写、数字、各种标点符号和设控制符。对于早期的计算机程序来说这些就足够了但是这也导致了世界上很多其他地区的用户无法直接使用自己的符号系统。随着互联网的发展混合多种语言的数据变得很常见译注比如本身的英文原文或中文翻译都包含了ASCII、中文、日文等多种语言字符。如何有效处理这些包含了各种语言的丰富多样的文本数据呢 在很久以前世界还是比较简单的起码计算机世界就只有一个ASCII字符集美国信息交换标准代码。ASCII更准确地说是美国的ASCII使用7bit来表示128个字符包含英文字母的大小写、数字、各种标点符号和设控制符。对于早期的计算机程序来说这些就足够了但是这也导致了世界上很多其他地区的用户无法直接使用自己的符号系统。随着互联网的发展混合多种语言的数据变得很常见译注比如本身的英文原文或中文翻译都包含了ASCII、中文、日文等多种语言字符。如何有效处理这些包含了各种语言的丰富多样的文本数据呢
答案就是使用Unicode http://unicode.org 它收集了这个世界上所有的符号系统包括重音符号和其它变音符号制表符和回车符还有很多神秘的符号每个符号都分配一个唯一的Unicode码点Unicode码点对应Go语言中的rune整数类型译注rune是int32等价类型 答案就是使用Unicode http://unicode.org 它收集了这个世界上所有的符号系统包括重音符号和其它变音符号制表符和回车符还有很多神秘的符号每个符号都分配一个唯一的Unicode码点Unicode码点对应Go语言中的rune整数类型译注rune是int32等价类型
在第八版本的Unicode标准收集了超过120,000个字符涵盖超过100多种语言。这些在计算机程序和数据中是如何体现的呢通用的表示一个Unicode码点的数据类型是int32也就是Go语言中rune对应的类型它的同义词rune符文正是这个意思。 在第八版本的Unicode标准收集了超过120,000个字符涵盖超过100多种语言。这些在计算机程序和数据中是如何体现的呢通用的表示一个Unicode码点的数据类型是int32也就是Go语言中rune对应的类型它的同义词rune符文正是这个意思。
我们可以将一个符文序列表示为一个int32序列。这种编码方式叫UTF-32或UCS-4每个Unicode码点都使用同样的大小32bit来表示。这种方式比较简单统一但是它会浪费很多存储空间因为大数据计算机可读的文本是ASCII字符本来每个ASCII字符只需要8bit或1字节就能表示。而且即使是常用的字符也远少于65,536个也就是说用16bit编码方式就能表达常用字符。但是还有其它更好的编码方法吗 我们可以将一个符文序列表示为一个int32序列。这种编码方式叫UTF-32或UCS-4每个Unicode码点都使用同样的大小32bit来表示。这种方式比较简单统一但是它会浪费很多存储空间因为大数据计算机可读的文本是ASCII字符本来每个ASCII字符只需要8bit或1字节就能表示。而且即使是常用的字符也远少于65,536个也就是说用16bit编码方式就能表达常用字符。但是还有其它更好的编码方法吗

View File

@ -119,7 +119,7 @@ for range s {
UTF8字符串作为交换格式是非常方便的但是在程序内部采用rune序列可能更方便因为rune大小一致支持数组索引和方便切割。 UTF8字符串作为交换格式是非常方便的但是在程序内部采用rune序列可能更方便因为rune大小一致支持数组索引和方便切割。
string接受到[]rune的类型转换可以将一个UTF8编码的字符串解码为Unicode字符序列: 将[]rune类型转换应用到UTF8编码的字符串将返回字符串编码的Unicode码点序列:
```Go ```Go
// "program" in Japanese katakana // "program" in Japanese katakana

View File

@ -109,7 +109,7 @@ func Join(s [][]byte, sep []byte) []byte
它们之间唯一的区别是字符串类型参数被替换成了字节slice类型的参数。 它们之间唯一的区别是字符串类型参数被替换成了字节slice类型的参数。
bytes包还提供了Buffer类型用于字节slice的缓存。一个Buffer开始是空的但是随着string、byte或[]byte等类型数据的写入可以动态增长一个bytes.Buffer变量并不需要处理化,因为零值也是有效的: bytes包还提供了Buffer类型用于字节slice的缓存。一个Buffer开始是空的但是随着string、byte或[]byte等类型数据的写入可以动态增长一个bytes.Buffer变量并不需要初始化,因为零值也是有效的:
<u><i>gopl.io/ch3/printints</i></u> <u><i>gopl.io/ch3/printints</i></u>
```Go ```Go

View File

@ -63,7 +63,7 @@ fmt.Println(t) // "left foot"
s[0] = 'L' // compile error: cannot assign to s[0] s[0] = 'L' // compile error: cannot assign to s[0]
``` ```
不变性意味如果两个字符串共享相同的底层数据的话也是安全的这使得复制任何长度的字符串代价是低廉的。同样一个字符串s和对应的子字符串切片s[7:]的操作也可以安全地共享相同的内存,因此字符串切片操作代价也是低廉的。在这两种情况下都没有必要分配新的内存。 图3.4演示了一个字符串和两个串共享相同的底层数据。 不变性意味如果两个字符串共享相同的底层数据的话也是安全的这使得复制任何长度的字符串代价是低廉的。同样一个字符串s和对应的子字符串切片s[7:]的操作也可以安全地共享相同的内存,因此字符串切片操作代价也是低廉的。在这两种情况下都没有必要分配新的内存。 图3.4演示了一个字符串和两个串共享相同的底层数据。
{% include "./ch3-05-1.md" %} {% include "./ch3-05-1.md" %}
@ -75,6 +75,3 @@ s[0] = 'L' // compile error: cannot assign to s[0]
{% include "./ch3-05-4.md" %} {% include "./ch3-05-4.md" %}
{% include "./ch3-05-5.md" %} {% include "./ch3-05-5.md" %}

View File

@ -43,7 +43,7 @@ func TurnDown(v *Flags) { *v &^= FlagUp }
func SetBroadcast(v *Flags) { *v |= FlagBroadcast } func SetBroadcast(v *Flags) { *v |= FlagBroadcast }
func IsCast(v Flags) bool { return v&(FlagBroadcast|FlagMulticast) != 0 } func IsCast(v Flags) bool { return v&(FlagBroadcast|FlagMulticast) != 0 }
unc main() { func main() {
var v Flags = FlagMulticast | FlagUp var v Flags = FlagMulticast | FlagUp
fmt.Printf("%b %t\n", v, IsUp(v)) // "10001 true" fmt.Printf("%b %t\n", v, IsUp(v)) // "10001 true"
TurnDown(&v) TurnDown(&v)

View File

@ -37,7 +37,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 fmt.Println(5.0 / 9.0 * (f - 32)) // "100"; 5.0/9.0 is an untyped float
``` ```
只有常量可以是无类型的。当一个无类型的常量被赋值给一个变量的时候,就像上面的第一行语句,或者是像其余三个语句中右边表达式中含有明确类型的值,无类型的常量将会被隐式转换为对应的类型,如果转换合法的话。 只有常量可以是无类型的。当一个无类型的常量被赋值给一个变量的时候,就像下面的第一行语句,或者出现在有明确类型的变量声明的右边,如下面的其余三行语句,无类型的常量将会被隐式转换为对应的类型,如果转换合法的话。
```Go ```Go
var f float64 = 3 + 0i // untyped complex -> float64 var f float64 = 3 + 0i // untyped complex -> float64
@ -69,7 +69,7 @@ const (
) )
``` ```
对于一个没有显式类型的变量声明语法(包括短变量声明语法),无类型的常量会被隐式转为默认的变量类型,就像下面的例子: 对于一个没有显式类型的变量声明(包括简短变量声明),常量的形式将隐式决定变量的默认类型,就像下面的例子:
```Go ```Go
i := 0 // untyped integer; implicit int(0) i := 0 // untyped integer; implicit int(0)
@ -78,7 +78,9 @@ f := 0.0 // untyped floating-point; implicit float64(0.0)
c := 0i // untyped complex; implicit complex128(0i) c := 0i // untyped complex; implicit complex128(0i)
``` ```
注意默认类型是规则的无类型的整数常量默认转换为int对应不确定的内存大小但是浮点数和复数常量则默认转换为float64和complex128。Go语言本身并没有不确定内存大小的浮点数和复数类型而且如果不知道浮点数类型的话将很难写出正确的数值算法。 注意有一点不同无类型整数常量转换为int它的内存大小是不确定的但是无类型浮点数和复数常量则转换为内存大小明确的float64和complex128。
如果不知道浮点数类型的内存大小是很难写出正确的数值算法的因此Go语言不存在整型类似的不确定内存大小的浮点数和复数类型。
如果要给变量一个不同的类型,我们必须显式地将无类型的常量转化为所需的类型,或给声明的变量指定明确的类型,像下面例子这样: 如果要给变量一个不同的类型,我们必须显式地将无类型的常量转化为所需的类型,或给声明的变量指定明确的类型,像下面例子这样: