Skip to content

Commit 7762d86

Browse files
committed
[update] add space between latin and charcter
1 parent 746d1dc commit 7762d86

36 files changed

+665
-663
lines changed

chapter02/02.0.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
进行复杂的文本处理必然离不开正则表达式。*regexp* 包提供了正则表达式功能,它的语法基于 [RE2](http://code.google.com/p/re2/wiki/Syntax)*regexp/syntax* 子包进行正则表达式解析。
1010

11-
Go 代码使用 UTF-8 编码(且不能带 BOM),同时标识符支持 Unicode 字符。在标准库 *unicode* 包及其子包 utf8、utf16中,提供了对 Unicode 相关编码、解码的支持,同时提供了测试 Unicode 码点(Unicode code points)属性的功能。
11+
Go 代码使用 UTF-8 编码(且不能带 BOM),同时标识符支持 Unicode 字符。在标准库 *unicode* 包及其子包 utf8、utf16 中,提供了对 Unicode 相关编码、解码的支持,同时提供了测试 Unicode 码点(Unicode code points)属性的功能。
1212

1313
在开发过程中,可能涉及到字符集的转换,作为补充,本章最后会讲解一个第三方库:mahonia — 纯 Go 语言实现的字符集转换库,以方便需要进行字符集转换的读者。
1414

chapter02/02.1.md

+260-258
Large diffs are not rendered by default.

chapter02/02.2.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
![](https://ws2.sinaimg.cn/large/006tKfTcly1g1kncpzk5zj30u021ltda.jpg)
1111

12-
## 2.2.1 是否存在某个子slice
12+
## 2.2.1 是否存在某个子 slice
1313

14-
// 子slice subslice 在 b 中,返回 true
14+
// 子 slice subslice 在 b 中,返回 true
1515
func Contains(b, subslice []byte) bool
1616

1717
该函数的内部调用了 bytes.Index 函数(在后面会讲解):

chapter02/02.3.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 2.3 strconv — 字符串和基本数据类型之间转换 #
22

3-
这里的基本数据类型包括:布尔、整型(包括有/无符号、二进制、八进制、十进制和十六进制)和浮点型等。
3+
这里的基本数据类型包括:布尔、整型(包括有 / 无符号、二进制、八进制、十进制和十六进制)和浮点型等。
44

55
## 2.3.1 strconv 包转换错误处理 ##
66

@@ -53,12 +53,12 @@
5353

5454
这里有必要说一下,当 bitSize==0 时的情况。
5555

56-
Go中,int/uint 类型,不同系统能表示的范围是不一样的,目前的实现是,32 位系统占 4 个字节;64 位系统占 8 个字节。当 bitSize==0 时,应该表示 32 位还是 64 位呢?这里没有利用 *runtime.GOARCH* 之类的方式,而是巧妙的通过如下表达式确定 intSize:
56+
Go 中,int/uint 类型,不同系统能表示的范围是不一样的,目前的实现是,32 位系统占 4 个字节;64 位系统占 8 个字节。当 bitSize==0 时,应该表示 32 位还是 64 位呢?这里没有利用 *runtime.GOARCH* 之类的方式,而是巧妙的通过如下表达式确定 intSize:
5757

5858
const intSize = 32 << uint(^uint(0)>>63)
5959
const IntSize = intSize // number of bits in int, uint (32 or 64)
6060

61-
主要是 *^uint(0)>>63* 这个表达式。操作符 *^* 在这里是一元操作符 按位取反,而不是 按位异或。更多解释可以参考:[Go位运算:取反和异或](http://studygolang.com/topics/303)
61+
主要是 *^uint(0)>>63* 这个表达式。操作符 *^* 在这里是一元操作符 按位取反,而不是 按位异或。更多解释可以参考:[Go 位运算:取反和异或](http://studygolang.com/topics/303)
6262

6363
问题:下面的代码 n 和 err 的值分别是什么?
6464

@@ -80,7 +80,7 @@ Go中,int/uint 类型,不同系统能表示的范围是不一样的,目前
8080

8181
### 2.3.2.2 整型转为字符串 ###
8282

83-
实际应用中,我们经常会遇到需要将字符串和整型连接起来,在Java中,可以通过操作符 "+" 做到。不过,在Go语言中,你需要将整型转为字符串类型,然后才能进行连接。这个时候,*strconv* 包中的整型转字符串的相关函数就派上用场了。这些函数签名如下:
83+
实际应用中,我们经常会遇到需要将字符串和整型连接起来,在 Java 中,可以通过操作符 "+" 做到。不过,在 Go 语言中,你需要将整型转为字符串类型,然后才能进行连接。这个时候,*strconv* 包中的整型转字符串的相关函数就派上用场了。这些函数签名如下:
8484

8585
func FormatUint(i uint64, base int) string // 无符号整型转字符串
8686
func FormatInt(i int64, base int) string // 有符号整型转字符串
@@ -128,7 +128,7 @@ Go中,int/uint 类型,不同系统能表示的范围是不一样的,目前
128128
}
129129
fmt.Println(time.Now().Sub(startTime))
130130

131-
我们分别循环转换了10000次*Sprintf* 的时间是 3.549761ms,而 *Itoa* 的时间是 848.208us,相差 4 倍多。
131+
我们分别循环转换了 10000 次*Sprintf* 的时间是 3.549761ms,而 *Itoa* 的时间是 848.208us,相差 4 倍多。
132132

133133
*Sprintf* 性能差些可以预见,因为它接收的是 interface,需要进行反射等操作。个人建议使用 *strconv* 包中的方法进行转换。
134134

@@ -142,7 +142,7 @@ Go中,int/uint 类型,不同系统能表示的范围是不一样的,目前
142142

143143
## 2.3.3 字符串和布尔值之间的转换 ##
144144

145-
Go中字符串和布尔值之间的转换比较简单,主要有三个函数:
145+
Go 中字符串和布尔值之间的转换比较简单,主要有三个函数:
146146

147147
// 接受 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False 等字符串;
148148
// 其他形式的字符串会返回错误
@@ -163,7 +163,7 @@ Go中字符串和布尔值之间的转换比较简单,主要有三个函数:
163163

164164
函数的命名和作用跟上面讲解的其他类型一致。
165165

166-
关于 *FormatFloat**fmt* 参数, 在第一章第三节[格式化IO](/chapter01/01.3.md)中有详细介绍。而 *prec* 表示有效数字(对 *fmt='b'* 无效),对于 'e', 'E' 和 'f',有效数字用于小数点之后的位数;对于 'g' 和 'G',则是所有的有效数字。例如:
166+
关于 *FormatFloat**fmt* 参数, 在第一章第三节[格式化 IO](/chapter01/01.3.md) 中有详细介绍。而 *prec* 表示有效数字(对 *fmt='b'* 无效),对于 'e', 'E' 和 'f',有效数字用于小数点之后的位数;对于 'g' 和 'G',则是所有的有效数字。例如:
167167

168168
strconv.FormatFloat(1223.13252, 'e', 3, 32) // 结果:1.223e+03
169169
strconv.FormatFloat(1223.13252, 'g', 3, 32) // 结果:1.22e+03

chapter02/02.4.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
# 2.4 regexp — 正则表达式
22

3-
正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式为文本处理提供了强大的功能。Go作为一门通用语言,自然提供了对正则表达式的支持。
3+
正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。正则表达式为文本处理提供了强大的功能。Go 作为一门通用语言,自然提供了对正则表达式的支持。
44

55
`regexp` 包实现了正则表达式搜索。
66

7-
正则表达式采用RE2语法(除了\c、\C),和Perl、Python等语言的正则基本一致。确切地说是兼容 `RE2` 语法。相关资料:[http://code.google.com/p/re2/wiki/Syntax](http://code.google.com/p/re2/wiki/Syntax)[包:regexp/syntax](http://docs.studygolang.com/pkg/regexp/syntax/)
7+
正则表达式采用 RE2 语法(除了 \c、\C),和 Perl、Python 等语言的正则基本一致。确切地说是兼容 `RE2` 语法。相关资料:[http://code.google.com/p/re2/wiki/Syntax](http://code.google.com/p/re2/wiki/Syntax)[包:regexp/syntax](http://docs.studygolang.com/pkg/regexp/syntax/)
88

9-
注意:`regexp` 包的正则表达式实现保证运行时间随着输入大小线性增长的(即复杂度为O\(n\)其中n为输入的长度),这一点,很多正则表达式的开源实现无法保证,参见:RSC 的 [《Regular Expression Matching Can Be Simple And Fast
9+
注意:`regexp` 包的正则表达式实现保证运行时间随着输入大小线性增长的(即复杂度为 O\(n\)其中 n 为输入的长度),这一点,很多正则表达式的开源实现无法保证,参见:RSC 的 [《Regular Expression Matching Can Be Simple And Fast
1010
\(but is slow in Java, Perl, PHP, Python, Ruby, ...\)](http://swtch.com/~rsc/regexp/regexp1.html)
1111

12-
另外,所有的字符都被视为utf-8编码的码值\(Code Point\)
12+
另外,所有的字符都被视为 utf-8 编码的码值 \(Code Point\)
1313

14-
Regexp类型提供了多达16个方法,用于匹配正则表达式并获取匹配的结果。它们的名字满足如下正则表达式:
14+
Regexp 类型提供了多达 16 个方法,用于匹配正则表达式并获取匹配的结果。它们的名字满足如下正则表达式:
1515

1616
```
1717
Find(All)?(String)?(Submatch)?(Index)?
@@ -24,7 +24,7 @@ Find(All)?(String)?(Submatch)?(Index)?
2424
# 导航
2525

2626
* 上一节:[strconv — 字符串和基本数据类型之间转换](02.3.md)
27-
* 下一节:[unicode — Unicode码点、UTF-8/16编码](02.5.md)
27+
* 下一节:[unicode — Unicode 码点、UTF-8/16 编码](02.5.md)
2828

2929

3030

chapter02/02.5.md

+36-36
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
1-
# 2.5 unicode — Unicode码点、UTF-8/16编码 #
1+
# 2.5 unicode — Unicode 码点、UTF-8/16 编码 #
22

33
世界中的字符有许许多多,有英文,中文,韩文等。我们强烈需要一个大大的映射表把世界上的字符映射成计算机可以阅读的二进制数字(字节)。
44
这样,每个字符都给予一个独一无二的编码,就不会出现写文字的人和阅读文字的人编码不同而出现无法读取的乱码现象了。
55

6-
于是Unicode就出现了,它是一种所有符号的编码映射。最开始的时候,unicode认为使用两个字节,也就是16位就能包含所有的字符了
7-
但是非常可惜,两个字节最多只能覆盖65536个字符,这显然是不够的,于是附加了一套字符编码,即unicode4.0,附加的字符用4个字节表示
8-
现在为止,大概Unicode可以覆盖100多万个字符了
6+
于是 Unicode 就出现了,它是一种所有符号的编码映射。最开始的时候,unicode 认为使用两个字节,也就是 16 位就能包含所有的字符了
7+
但是非常可惜,两个字节最多只能覆盖 65536 个字符,这显然是不够的,于是附加了一套字符编码,即 unicode4.0,附加的字符用 4 个字节表示
8+
现在为止,大概 Unicode 可以覆盖 100 多万个字符了
99

10-
Unicode只是定义了一个字符和一个编码的映射,但是呢,对应的存储却没有制定。
11-
比如一个编码0x0041代表大写字母A,那么可能有一种存储至少有4个字节,那可能0x00000041来存储代表A
12-
这个就是unicode的具体实现。unicode的具体实现有很多种,UTF-8和UTF-16就是其中两种
10+
Unicode 只是定义了一个字符和一个编码的映射,但是呢,对应的存储却没有制定。
11+
比如一个编码 0x0041 代表大写字母 A,那么可能有一种存储至少有 4 个字节,那可能 0x00000041 来存储代表 A
12+
这个就是 unicode 的具体实现。unicode 的具体实现有很多种,UTF-8 和 UTF-16 就是其中两种
1313

14-
UTF-8表示最少用一个字节就能表示一个字符的编码实现。它采取的方式是对不同的语言使用不同的方法,将unicode编码按照这个方法进行转换
14+
UTF-8 表示最少用一个字节就能表示一个字符的编码实现。它采取的方式是对不同的语言使用不同的方法,将 unicode 编码按照这个方法进行转换
1515
我们只要记住最后的结果是英文占一个字节,中文占三个字节。这种编码实现方式也是现在应用最为广泛的方式了。
1616

17-
UTF-16表示最少用两个字节能表示一个字符的编码实现。同样是对unicode编码进行转换,它的结果是英文占用两个字节,中文占用两个或者四个字节。
18-
实际上,UTF-16就是最严格实现了unicode4.0。但由于英文是最通用的语言,所以推广程度没有UTF-8那么普及
17+
UTF-16 表示最少用两个字节能表示一个字符的编码实现。同样是对 unicode 编码进行转换,它的结果是英文占用两个字节,中文占用两个或者四个字节。
18+
实际上,UTF-16 就是最严格实现了 unicode4.0。但由于英文是最通用的语言,所以推广程度没有 UTF-8 那么普及
1919

20-
回到go对unicode包的支持,由于UTF-8的作者Ken Thompson同时也是go语言的创始人,所以说,在字符支持方面,几乎没有语言的理解会高于go了
21-
go对unicode的支持包含三个包:
20+
回到 go 对 unicode 包的支持,由于 UTF-8 的作者 Ken Thompson 同时也是 go 语言的创始人,所以说,在字符支持方面,几乎没有语言的理解会高于 go 了
21+
go 对 unicode 的支持包含三个包 :
2222

2323
* unicode
2424
* unicode/utf8
2525
* unicode/utf16
2626

27-
unicode包包含基本的字符判断函数。utf8包主要负责rune和byte之间的转换。utf16包负责rune和uint16数组之间的转换
27+
unicode 包包含基本的字符判断函数。utf8 包主要负责 rune 和 byte 之间的转换。utf16 包负责 rune 和 uint16 数组之间的转换
2828

29-
由于字符的概念有的时候比较模糊,比如字符(小写a)普通显示为a,在重音字符中(grave-accented)中显示为à。
30-
这时候字符(character)的概念就有点不准确了,因为a和à显然是两个不同的unicode编码,但是却代表同一个字符,所以引入了rune
31-
一个rune就代表一个unicode编码,所以上面的a和à是两个不同的rune
29+
由于字符的概念有的时候比较模糊,比如字符(小写 a)普通显示为 a,在重音字符中(grave-accented)中显示为à。
30+
这时候字符(character)的概念就有点不准确了,因为 a 和à显然是两个不同的 unicode 编码,但是却代表同一个字符,所以引入了 rune
31+
一个 rune 就代表一个 unicode 编码,所以上面的 a 和à是两个不同的 rune
3232

33-
这里有个要注意的事情,go语言的所有代码都是UTF8的,所以如果我们在程序中的字符串都是utf8编码的,但是我们的单个字符(单引号扩起来的)却是unicode的
33+
这里有个要注意的事情,go 语言的所有代码都是 UTF8 的,所以如果我们在程序中的字符串都是 utf8 编码的,但是我们的单个字符(单引号扩起来的)却是 unicode 的
3434

35-
## 2.5.1 unicode包 ##
35+
## 2.5.1 unicode 包 ##
3636

37-
unicode包含了对rune的判断。这个包把所有unicode涉及到的编码进行了分类,使用结构
37+
unicode 包含了对 rune 的判断。这个包把所有 unicode 涉及到的编码进行了分类,使用结构
3838

3939
```golang
4040
type RangeTable struct {
@@ -43,7 +43,7 @@ type RangeTable struct {
4343
LatinOffset int
4444
}
4545
```
46-
来表示这个功能的字符集。这些字符集都集中列表在table.go这个源码里面
46+
来表示这个功能的字符集。这些字符集都集中列表在 table.go 这个源码里面
4747

4848
比如控制字符集:
4949

@@ -63,18 +63,18 @@ var _Pc = &RangeTable{
6363

6464
```
6565
func IsControl(r rune) bool // 是否控制字符
66-
func IsDigit(r rune) bool // 是否阿拉伯数字字符,即1-9
66+
func IsDigit(r rune) bool // 是否阿拉伯数字字符,即 1-9
6767
func IsGraphic(r rune) bool // 是否图形字符
6868
func IsLetter(r rune) bool // 是否字母
6969
func IsLower(r rune) bool // 是否小写字符
7070
func IsMark(r rune) bool // 是否符号字符
7171
func IsNumber(r rune) bool // 是否数字字符,比如罗马数字Ⅷ也是数字字符
72-
func IsOneOf(ranges []*RangeTable, r rune) bool // 是否是RangeTable中的一个
72+
func IsOneOf(ranges []*RangeTable, r rune) bool // 是否是 RangeTable 中的一个
7373
func IsPrint(r rune) bool // 是否可打印字符
7474
func IsPunct(r rune) bool // 是否标点符号
7575
func IsSpace(r rune) bool // 是否空格
7676
func IsSymbol(r rune) bool // 是否符号字符
77-
func IsTitle(r rune) bool // 是否title case
77+
func IsTitle(r rune) bool // 是否 title case
7878
func IsUpper(r rune) bool // 是否大写字符
7979
```
8080

@@ -90,44 +90,44 @@ func main() {
9090
digit := rune('1')
9191
fmt.Println(unicode.IsDigit(digit)) //true
9292
fmt.Println(unicode.IsNumber(digit)) //true
93-
letter := rune('')
93+
letter := rune('')
9494
fmt.Println(unicode.IsDigit(letter)) //false
9595
fmt.Println(unicode.IsNumber(letter)) //true
9696
}
9797
```
9898

99-
## 2.5.2 utf8包 ##
99+
## 2.5.2 utf8 包 ##
100100

101-
utf8里面的函数就有一些字节和字符的转换
101+
utf8 里面的函数就有一些字节和字符的转换
102102

103-
判断是否符合utf8编码的函数
103+
判断是否符合 utf8 编码的函数
104104
* func Valid(p []byte) bool
105105
* func ValidRune(r rune) bool
106106
* func ValidString(s string) bool
107107

108-
判断rune的长度的函数
108+
判断 rune 的长度的函数
109109
* func RuneLen(r rune) int
110110

111-
判断字节串或者字符串的rune数
111+
判断字节串或者字符串的 rune 数
112112
* func RuneCount(p []byte) int
113113
* func RuneCountInString(s string) (n int)
114114

115-
编码和解码rune到byte
115+
编码和解码 rune 到 byte
116116
* func DecodeRune(p []byte) (r rune, size int)
117117
* func EncodeRune(p []byte, r rune) int
118118

119-
## 2.5.3 utf16包 ##
119+
## 2.5.3 utf16 包 ##
120120

121-
utf16的包的函数就比较少了
121+
utf16 的包的函数就比较少了
122122

123-
将int16和rune进行转换
123+
将 int16 和 rune 进行转换
124124
* func Decode(s []uint16) []rune
125125
* func Encode(s []rune) []uint16
126126

127-
unicode有个基本字符平面和增补平面的概念,基本字符平面只有65535个字符,增补平面(有16个)加上去就能表示1114112个字符
128-
utf16就是严格实现了unicode的这种编码规范
127+
unicode 有个基本字符平面和增补平面的概念,基本字符平面只有 65535 个字符,增补平面(有 16 个)加上去就能表示 1114112 个字符
128+
utf16 就是严格实现了 unicode 的这种编码规范
129129

130-
而基本字符和增补平面字符就是一个代理对(Surrogate Pair)。一个代理对可以和一个rune进行转换
130+
而基本字符和增补平面字符就是一个代理对(Surrogate Pair)。一个代理对可以和一个 rune 进行转换
131131

132132
* func DecodeRune(r1, r2 rune) rune
133133
* func EncodeRune(r rune) (r1, r2 rune)

chapter03/03.0.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
程序设计离不开数据结构和算法。数据结构是数据组织和存储的逻辑形式,以达到方便访问和修改数据的目的。而算法是根据实际输入输出的需求设计的一系列计算过程,被认为是程序的灵魂。设计良好的算法的重要意义正如*Thomas*在《算法导论》中提到“计算机可以做得很快,但不是无限快;存储器可以做到很便宜,但不是免费的。因此,计算时间是一种有限的资源,存储空间也是一种有限的资源。这些有限的资源必须有效地使用,那些时间上和空间上有效的算法可以帮助做到这一点。“
44

5-
本章内容涵盖了Go标准库中的3个包
5+
本章内容涵盖了 Go 标准库中的 3 个包
66

77
*sort* 包包含基本的排序方法,支持切片数据排序以及用户自定义数据集合排序
88

99
*index/suffixary* 包实现了后缀数组相关算法以支持许多常见的字符串操作
1010

11-
*container* 包提供了对heap、list和ring这3种数据结构的底层支持。任何实现了相应接口的数据结构都可以调用该结构的方法。
11+
*container* 包提供了对 heap、list 和 ring 这 3 种数据结构的底层支持。任何实现了相应接口的数据结构都可以调用该结构的方法。
1212

1313
# 导航 #
1414

0 commit comments

Comments
 (0)