Unknown há 11 anos atrás
pai
commit
ff809d956a
4 ficheiros alterados com 78 adições e 66 exclusões
  1. 1 1
      README.md
  2. 73 64
      eBook/07.2.md
  3. 3 1
      eBook/07.3.md
  4. 1 0
      eBook/directory.md

+ 1 - 1
README.md

@@ -9,7 +9,7 @@
 
 ## 翻译进度
 
-7.1 [声明和初始化](eBook/07.1.md)
+7.2 [For-range 结构](eBook/07.2.md)
 
 ## 支持本书
 

+ 73 - 64
eBook/07.2.md

@@ -1,52 +1,53 @@
 # 7.2 切片
 
-164
-
 ## 7.2.1 概念
-slice是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以slice是一个引用类型(因此更类似于C/C++中的数组类型,或者Python中的list类型)。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在slice内。Slice提供了一个相关数组的动态窗口。
 
-Slice是可索引的,并且可以由len()方法获取长度。
+slice 是对数组一个连续片段的引用(该数组我们称之为相关数组,通常是匿名的),所以 slice 是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型)。这个片段可以是整个数组,或者是由起始和终止索引标识的一些项的子集。需要注意的是,终止索引标识的项不包括在 slice 内。 Slice 提供了一个相关数组的动态窗口。
+
+Slice 是可索引的,并且可以由 len() 方法获取长度。
 
-给定项的slice索引可能比相关数组的相同元素的索引小。和数组不同的是,slice的长度可以在运行时修改,最小为0最大为相关数组的长度:slice是一个`长度可变的数组`。
+给定项的 slice 索引可能比相关数组的相同元素的索引小。和数组不同的是,slice 的长度可以在运行时修改,最小为 0 最大为相关数组的长度:slice 是一个 **长度可变的数组**
 
-slice提供了计算容量的方法cap()可以测量slice最长可以达到多少:它等于slice的长度 + 数组除slice之外的长度。如果s是一个slice,cap就是从s[0]到数组末尾的数组长度。slice的长度永远不会超过它的容量,所以对于slice s来说该不等式永远成立: 0 <= len(s) <= cap(s)
+slice 提供了计算容量的方法 cap() 可以测量 slice 最长可以达到多少:它等于 slice 的长度 + 数组除 slice 之外的长度。如果 s 是一个 slice,cap 就是从 s[0] 到数组末尾的数组长度。slice 的长度永远不会超过它的容量,所以对于 slice s 来说该不等式永远成立: 0 <= len(s) <= cap(s)
 
-多个slice如果表示同一个数组的片段,它们可以共享数据;因此一个slice和相关数组的其他slice是共享存储的,相反,不同的数组总是代表不同的存储。数组实际上是slice的构建块。
+多个 slice 如果表示同一个数组的片段,它们可以共享数据;因此一个 slice 和相关数组的其他 slice 是共享存储的,相反,不同的数组总是代表不同的存储。数组实际上是 slice 的构建块。
 
-`优点: ` 因为slice是引用,所以它们不需要使用额外的内存并且比使用数组更有效率,所以在Go代码中slice比数组更常用。
+**优点** 因为 slice 是引用,所以它们不需要使用额外的内存并且比使用数组更有效率,所以在 Go 代码中 slice 比数组更常用。
 
-声明slice的格式是: var identifier []type   不需要说明长度
+声明 slice 的格式是: `var identifier []type` 不需要说明长度
 
-一个slice在未初始化之前默认为nil,长度为0。
+一个 slice 在未初始化之前默认为 nil,长度为 0。
 
-slice的初始化格式是: var slice1 []type = arr1[start:end]
+slice 的初始化格式是:`var slice1 []type = arr1[start:end]`
 
-这表示slice1是由数组arr1从start索引到end-1索引之间的元素构成的子集(切分数组,start:end被称为slice表达式)。所以slice1[0]就等于arr1[start]。这可以在arr1被填充前就定义好。
+这表示 slice1 是由数组 arr1  start 索引到 end-1 索引之间的元素构成的子集(切分数组,start:end 被称为 slice 表达式)。所以 slice1[0] 就等于 arr1[start]。这可以在 arr1 被填充前就定义好。
 
-如果某个人写: var slice1 []type = arr1[:]那么slice1就等于完整的arr1数组(所以这种表示方式是arr1[0:len(arr1)]的一种缩写)。另外一种表述方式是:slice1 = &arr1。
+如果某个人写:`var slice1 []type = arr1[:]` 那么 slice1 就等于完整的 arr1 数组(所以这种表示方式是 `arr1[0:len(arr1)]` 的一种缩写)。另外一种表述方式是:`slice1 = &arr1`
 
-arr1[2:]和arr1[2:len(arr1)]相同,都包含了数组从第二个到最后的所有元素。
+arr1[2:]  arr1[2:len(arr1)] 相同,都包含了数组从第二个到最后的所有元素。
 
-arr1[:3]和arr1[0:3]相同,包含了从第一个到第三个元素(不包括第三个)。
+arr1[:3]  arr1[0:3] 相同,包含了从第一个到第三个元素(不包括第三个)。
 
-如果你想去掉slice1的最后一个元素,只要 slice1 = slice1[:len(slice1)-1]
+如果你想去掉 slice1 的最后一个元素,只要 `slice1 = slice1[:len(slice1)-1]`。
 
-一个由数组第1,2,3个元素组成的分片可以这么生成: s := [3]int{1,2,3} 或者 s := [...]int{1,2,3}[:]甚至更简单的s := []int{1,2,3}
+一个由数组第 1,2,3 个元素组成的分片可以这么生成:`s := [3]int{1,2,3}` 或者 `s := [...]int{1,2,3}[:]` 甚至更简单的 `s := []int{1,2,3}`
 
-s2 := s[:]是用slice组成的slice,拥有相同的元素,但是仍然指向相同的相关数组。
+`s2 := s[:]` 是用 slice 组成的 slice,拥有相同的元素,但是仍然指向相同的相关数组。
 
-一个slice s可以这样扩展到它的大小上限:s = s[:cap(s)],如果再扩大的话就会导致运行时错误(参见7.7)。
+一个 slice s 可以这样扩展到它的大小上限:`s = s[:cap(s)]`,如果再扩大的话就会导致运行时错误(参见7.7)。
 
-对于每一个slice(包括string),以下状态总是成立的:
+对于每一个 slice(包括 string),以下状态总是成立的:
 
 	s == s[:i] + s[i:] // i是一个整数且: 0 <= i <= len(s)
 	len(s) < cap(s)
 
-Slice也可以用类似数组的方式初始化: var x = []int{2, 3, 5, 7, 11}。这样就创建了一个长度为5的数组并且创建了一个相关slice。
+Slice 也可以用类似数组的方式初始化:`var x = []int{2, 3, 5, 7, 11}`。这样就创建了一个长度为5的数组并且创建了一个相关 slice。
+
+slice 在内存中的组织方式实际上是一个有 3 个域的结构体:指向相关数组的指针,slice 长度以及 slice 容量。下图给出了一个长度为 2,容量为 4 的 slice。
 
-slice在内存中的组织方式实际上是一个有3个域的结构体:指向相关数组的指针,slice长度以及slice容量。下图给出了一个长度为2,容量为4的slice。
+`y[0] = 3` 且 `y[1] = 5`。slice y[0:4]由 元素 3, 5, 7 和 11 组成
 
-y[0] = 3且y[1] = 5。slice y[0:4]由元素3, 5, 7和11组成。 ![](images/7.2_fig7.2.png?raw=true)
+![](images/7.2_fig7.2.png?raw=true)
 
 示例 7.7 [array_slices.go](exmaples/chapter_7/array_slices.go)
 
@@ -97,14 +98,15 @@ y[0] = 3且y[1] = 5。slice y[0:4]由元素3, 5, 7和11组成。 ![](images/7.
 	The length of slice1 is 4
 	The capacity of slice1 is 4
 
-如果s2是一个slice,你可以将s2向后移动一位s2 = s2[1:],但是末尾没有移动。slice只能向后移动,s2 = s2[-1:]会导致编译错误。slice不能被重新分片以获取数组的前一个元素。
+如果 s2 是一个 slice,你可以将 s2 向后移动一位 `s2 = s2[1:]`,但是末尾没有移动。slice 只能向后移动,`s2 = s2[-1:]` 会导致编译错误。slice 不能被重新分片以获取数组的前一个元素。
 
-`注意`绝对不要用指针指向slice。slice本身已经是一个引用类型,所以它本身就是一个指针!!
+**注意** 绝对不要用指针指向 slice。slice 本身已经是一个引用类型,所以它本身就是一个指针!!
 
-问题7.2: 给定slice b:= []byte{'g', 'o', 'l', 'a', 'n', 'g'},那么b[1:4],b[:2],b[2:]和b[:]分别是什么?
+问题7.2: 给定 `slice b:= []byte{'g', 'o', 'l', 'a', 'n', 'g'}`,那么 b[1:4],b[:2],b[2:]  b[:] 分别是什么?
 
-## 7.2.2 将slice传递给函数
-如果你有一个函数需要对数组做操作,你可能总是需要把参数声明为slice。当你调用该函数时,把数组分片,创建为一个slice引用并传递给该函数。这里有一个计算数组元素和的方法:
+## 7.2.2 将 slice 传递给函数
+
+如果你有一个函数需要对数组做操作,你可能总是需要把参数声明为 slice。当你调用该函数时,把数组分片,创建为一个 slice 引用并传递给该函数。这里有一个计算数组元素和的方法:
 
 	func sum(a []int) int {
 		s := 0
@@ -119,25 +121,26 @@ y[0] = 3且y[1] = 5。slice y[0:4]由元素3, 5, 7和11组成。 ![](images/7.
 		sum(arr[:])
 	}
 
-## 7.2.3 用make()创建一个slice
-当相关数组还没有定义时,我们可以使用make()方法来创建一个slice同时创建好相关数组: var slice1 []type = make([]type, len)
+## 7.2.3 用 make() 创建一个 slice
+
+当相关数组还没有定义时,我们可以使用 make() 方法来创建一个 slice 同时创建好相关数组:`var slice1 []type = make([]type, len)`
 
-也可以简写为 slice1 := make([]type, len),这里len是数组的长度并且也是slice的初始长度。
+也可以简写为 `slice1 := make([]type, len)`,这里 `len` 是数组的长度并且也是 `slice` 的初始长度。
 
-所以定义s2 := make([]int, 10),那么cap(s2) == len(s2) == 10
+所以定义 `s2 := make([]int, 10)`,那么 `cap(s2) == len(s2) == 10`
 
-make接受2个参数:元素的类型以及slice的元素个数。
+make 接受 2 个参数:元素的类型以及 slice 的元素个数。
 
-如果你想创建一个slice1,它不占用整个数组,而只是占用以len为个数个项,那么只要: slice1 := make([]type, len, cap)
+如果你想创建一个 slice1,它不占用整个数组,而只是占用以 len 为个数个项,那么只要:`slice1 := make([]type, len, cap)`
 
-make的使用方式是: func make([]T, len, cap) 其中cap是可选参数。
+make 的使用方式是:`func make([]T, len, cap)` 其中 cap 是可选参数。
 
-所以下面两种方法可以生成相同的slice:
+所以下面两种方法可以生成相同的 slice:
 
 	make([]int, 50, 100)
 	new([100]int)[0:50]
 
-下图描述了使用make方法生成的slice的内存结构:![](images/7.2_fig7.2.1.png?raw=true)
+下图描述了使用 make 方法生成的 slice 的内存结构:![](images/7.2_fig7.2.1.png?raw=true)
 
 示例 7.8 [make_slice.go](exmaples/chapter_7/make_slice.go)
 
@@ -173,25 +176,28 @@ make的使用方式是: func make([]T, len, cap) 其中cap是可选参数。
 	The length of slice1 is 10
 	The capacity of slice1 is 10
 
-因为字符串是纯粹不可变的字节数组,它们也可以被切分成slice。
+因为字符串是纯粹不可变的字节数组,它们也可以被切分成 slice。
 
-练习 7.4: fobinacci_funcarray.go: 为练习7.3写一个新的版本,主函数调用一个使用序列个数作为参数的函数,该函数返回一个大小为序列个数的Fibonacci slice。
+练习 7.4: fobinacci_funcarray.go: 为练习 7.3 写一个新的版本,主函数调用一个使用序列个数作为参数的函数,该函数返回一个大小为序列个数的 Fibonacci slice。
+
+## 7.2.4 new() 和 make() 的区别
 
-## 7.2.4 new()和make()的区别
 看起来二者没有什么区别,都在堆上分配内存,但是它们的行为不同,适用于不同的类型。
 
-new(T)为每个新的类型T分配一片内存,初始化为0并且返回内存地址,类型*T:这种方法`返回一个指向类型为T,值为0的地址的指针`,它适用于值类型如数组和结构体(参见第十章);它相当于&T{}
+new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回内存地址,类型 *T:这种方法 **返回一个指向类型为 T,值为 0 的地址的指针**,它适用于值类型如数组和结构体(参见第 10 章);它相当于 `&T{}`。
+
+make(T) **返回一个类型为 T 的初始值**,它只适用于3种内建的引用类型:slice, map 和 channel(参见第 8 章,第 13 章)
 
-make(T)`返回一个类型为T的初始值`,它只适用于3种内建的引用类型:slice, map和channel(参见第8章,第13章)
+换言之,new 方法分配内存,make 方法初始化;下图给出了区别:
 
-换言之,new方法分配内存,make方法初始化;下图给出了区别:![](images/7.3_fig7.3.png?raw=true)
+![](images/7.3_fig7.3.png?raw=true)
 
-在图7.3的第一幅图中:
+在图 7.3 的第一幅图中:
 
 	var p *[]int = new([]int) // *p == nil; with len and cap 0
 	p := new([]int)
 
-在第二幅图中, p := make([]int, 0) ,slice已经被初始化,但是指向一个空的数组。
+在第二幅图中, `p := make([]int, 0)` ,slice 已经被初始化,但是指向一个空的数组。
 
 这两种方式实用性都不高,下面的方法:
 
@@ -201,35 +207,37 @@ make(T)`返回一个类型为T的初始值`,它只适用于3种内建的引用
 	
 	v := make([]int, 10, 50)
 
-这样分配一个有50个int值的数组,并且创建了一个长度为10,容量为50的slice v,该slice指向数组的前10个元素。
+这样分配一个有 50 个 int 值的数组,并且创建了一个长度为 10,容量为 50 的 slice v,该 slice 指向数组的前 10 个元素。
+
+问题 7.3:给定 `s := make([]byte, 5)`,len(s) 和 cap(s) 分别是多少?`s = s[2:4]`,len(s) 和 cap(s) 又分别是多少?
+问题 7.4:假设 `s1 := []byte{'p', 'o', 'e', 'm'}` 且 `s2 := d[2:]`,s2 的值是多少?如果我们执行 `s2[1] == 't'`,s1 和 s2 现在的值又分配是多少?
 
-问题 7.3:给定s := make([]byte, 5),len(s)和cap(s)分别是多少?s = s[2:4],len(s)和cap(s)又分别是多少?
-问题 7.4:假设s1 := []byte{'p', 'o', 'e', 'm'}且s2 := d[2:],s2的值是多少?如果我们执行s2[1] == 't',s1和s2现在的值又分配是多少?
+## 7.2.5 多维 slice
 
-## 7.2.5 多维slice
-和数组一样,slice通常也是一维的,但是也可以由一维组合成高维。通过分片的分片(或者slice的数组),长度可以任意动态变化,所以Go语言的多维slice可以任意切分。而且,内层的slice必须单独分配(通过make方法)
+和数组一样,slice 通常也是一维的,但是也可以由一维组合成高维。通过分片的分片(或者 slice 的数组),长度可以任意动态变化,所以 Go 语言的多维 slice 可以任意切分。而且,内层的 slice 必须单独分配(通过 make 方法)
 
-## 7.2.6 bytes包
-bytes的slice十分常见,Go语言有一个bytes包专门用来解决这种类型的操作方法。
+## 7.2.6 bytes 包
 
-bytes包和字符串包十分类似(参见4.7)。而且它还包含一个十分有用的类型Buffer:
+bytes 的 slice 十分常见,Go 语言有一个 bytes 包专门用来解决这种类型的操作方法。
+
+bytes 包和字符串包十分类似(参见第 4.7 节)。而且它还包含一个十分有用的类型 Buffer:
 
 	import "bytes"
 	type Buffer struct {
 		...
 	}
 
-这是一个bytes的定长buffer,提供Read和Write方法,因为读写不知道长度的bytes最好使用buffer。
+这是一个 bytes 的定长 buffer,提供 Read  Write 方法,因为读写不知道长度的 bytes 最好使用 buffer。
 
-Buffer可以这样定义: var buffer bytes.Buffer
+Buffer 可以这样定义:`var buffer bytes.Buffer`
 
-或者new出一个指针: var r *bytes.Buffer = new(bytes.Buffer)
+或者 new 出一个指针:`var r *bytes.Buffer = new(bytes.Buffer)`
 
-或者通过函数: func NewBuffer(buf []byte) *Buffer,这就用创建了一个Buffer对象并且用buf初始化好了;NewBuffer最好用在从buf读取的时候使用。
+或者通过函数:`func NewBuffer(buf []byte) *Buffer`,这就用创建了一个 Buffer 对象并且用 buf 初始化好了;NewBuffer 最好用在从 buf 读取的时候使用。
 
-通过buffer串联字符串:类似于Java的StringBuilder类。
+通过 buffer 串联字符串:类似于 Java  StringBuilder 类。
 
-创建一个Buffer,通过buffer.WriteString(s)方法将每个string s追加到后面,最后再通过buffer.String()方法转换为string,下面是代码段:
+创建一个 Buffer,通过 buffer.WriteString(s) 方法将每个 string s 追加到后面,最后再通过 buffer.String() 方法转换为 string,下面是代码段:
 
 	var buffer bytes.Buffer
 	for {
@@ -241,14 +249,15 @@ Buffer可以这样定义: var buffer bytes.Buffer
 	}
 	fmt.Print(buffer.String(), "\n")
 
-这种实现方式比使用`+=`要更节省内存和CPU,尤其是要串联的字符串数目特别多的时候。
+这种实现方式比使用 `+=` 要更节省内存和 CPU,尤其是要串联的字符串数目特别多的时候。
 
 练习:
 
-练习 7.5: 给定slice sl,将a []byte数组追加到sl后面。写一个函数Append(slice, data []byte) []byte,该函数在sl不能存储更多数据的时候自动扩容。
-练习 7.6: 把一个缓存buf分片成两个slice:第一个是前n个bytes,后一个是剩余的,用一行代码实现。
+练习 7.5: 给定 slice sl,将 a []byte 数组追加到 sl 后面。写一个函数 `Append(slice, data []byte) []byte`,该函数在 sl 不能存储更多数据的时候自动扩容。
+练习 7.6: 把一个缓存 buf 分片成两个 slice:第一个是前 n 个 bytes,后一个是剩余的,用一行代码实现。
+
+## 链接
 
-##链接
 - [目录](directory.md)
 - 上一节:[声明和初始化](07.1.md)
-- 下一节:[For range构建方法](07.3.md)
+- 下一节:[For-range 结构](07.3.md)

+ 3 - 1
eBook/07.3.md

@@ -1,4 +1,6 @@
-#7.3 For range构建方法
+# 7.3 For-range 结构
+
+172
 
 这种构建方法可以应用与数组和slice:
 	for ix, value := range slice1 {

+ 1 - 0
eBook/directory.md

@@ -61,6 +61,7 @@
 - 第7章:[数组与切片](07.0.md)
 	- 7.1 [声明和初始化](07.1.md)
 	- 7.2 [切片](07.2.md)
+	- 7.3 [For-range 结构](07.3.md)
 - 第8章:Maps
 - 第9章:包(package)
 - 第10章:结构(struct)与方法(method)