This commit is contained in:
Unknown
2014-11-03 18:40:54 -05:00
parent 091864498c
commit 37397a7d02
4 changed files with 47 additions and 38 deletions

View File

@@ -9,7 +9,7 @@
## 翻译进度 ## 翻译进度
7.0 [数组与切片](eBook/07.0.md) 7.1 [声明和初始化](eBook/07.1.md)
## 支持本书 ## 支持本书

View File

@@ -3,36 +3,36 @@
157 157
##7.1.1 概念 ##7.1.1 概念
数组是具有相同`唯一类型`的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。数组长度必须是一个常量表达式,并且必须是一个非负整数。数组长度也是数组类型的一部分,所以[5]int和[10]int是属于不同类型的。数组的编译时值初始化是按照数组顺序完成的如下 数组是具有相同 **唯一类型** 的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。数组长度必须是一个常量表达式,并且必须是一个非负整数。数组长度也是数组类型的一部分,所以[5]int和[10]int是属于不同类型的。数组的编译时值初始化是按照数组顺序完成的如下
**注意事项** **注意事项**
如果我们想让数组元素类型为任意类型的话可以使用空接口作为类型(参考[第11章](11.9.md))。当使用值时我们必须先做一个类型判断(参考[第11章](11.3.md))。 如果我们想让数组元素类型为任意类型的话可以使用空接口作为类型(参考 [ 11 ](11.9.md))。当使用值时我们必须先做一个类型判断(参考 [ 11 ](11.3.md))。
数组元素可以通过`索引`位置来读取或者修改索引从0开始第一个元素索引为0第二个索引为1以此类推。数组以0开始在所有类C语言中是相似的。元素的数目也称为`length`或者数组大小必须是固定的并且在声明该数组时就给出编译时需要知道数组长度以便分配内存数组长度最大为2Gb。 数组元素可以通过 **索引**位置来读取或者修改索引从0开始第一个元素索引为 0第二个索引为 1以此类推。数组以 0 开始在所有类C语言中是相似的。元素的数目也称为长度或者数组大小必须是固定的并且在声明该数组时就给出(编译时需要知道数组长度以便分配内存);数组长度最大为 2Gb。
声明的格式是: var identifier [len]type 声明的格式是: `var identifier [len]type`
例如: var arr1 [5]int 例如: `var arr1 [5]int`
在内存中的结构是:![](images/7.1_fig7.1.png?raw=true) 在内存中的结构是:![](images/7.1_fig7.1.png?raw=true)
每个元素是一个整形值当声明数组时所有的元素都会被自动初始化为默认值0. 每个元素是一个整形值当声明数组时所有的元素都会被自动初始化为默认值0.
arr1的长度是5索引范围从0到len(arr1)-1 arr1 的长度是 5索引范围从 0 到 len(arr1)-1
第一个元素是arr1[0],第3个元素是arr1[2];总体来说索引i代表的元素是arr1[i]最后一个元素是arr1[len(arr1)-1]。 第一个元素是 arr1[0],第个元素是 arr1[2];总体来说索引 i 代表的元素是 arr1[i],最后一个元素是 arr1[len(arr1)-1]。
对索引项为i的数组元素赋值可以这么操作arr[i] = value所以数组是`可变的` 对索引项为 i 的数组元素赋值可以这么操作arr[i] = value所以数组是 **可变的**
只有有效的索引可以被使用当使用等于或者大于len(arr1)的索引时如果编译器可以检测到会给出索引超限的提示信息如果检测不到的话编译会通过而运行时会panic:(参考[第13章](13.0.md) 只有有效的索引可以被使用,当使用等于或者大于 len(arr1) 的索引时:如果编译器可以检测到,会给出索引超限的提示信息;如果检测不到的话编译会通过而运行时会 panic:(参考 [ 13 ](13.0.md)
runtime error: index out of range runtime error: index out of range
由于索引的存在遍历数组的方法自然就是使用for-construct: 由于索引的存在,遍历数组的方法自然就是使用 for-construct:
- 通过for初始化数组项 - 通过 for 初始化数组项
- 通过for打印数组元素 - 通过 for 打印数组元素
- 通过for依次处理元素 - 通过 for 依次处理元素
示例 7.1 [for_arrays.go](exmaples/chapter_7/for_arrays.go) 示例 7.1 [for_arrays.go](exmaples/chapter_7/for_arrays.go)
@@ -75,7 +75,7 @@ IDIOM:
... ...
} }
在这里i也是数组的索引当然这两种for-construct方式对于(slices)参考[7](07.2.md)来说也同样适用 在这里i也是数组的索引当然这两种 for-construct 方式对于(slices)参考 [ 7 ](07.2.md)来说也同样适用
**问题 7.1** 下面代码段的输出是什么 **问题 7.1** 下面代码段的输出是什么
@@ -84,20 +84,20 @@ IDIOM:
fmt.Println("Array item", i, "is", a[i]) fmt.Println("Array item", i, "is", a[i])
} }
Go语言中的数组是一种`值类型`不像C/C++中是指向首元素的指针所以可以通过`new()`来创建 var arr1 = new([5]int) Go语言中的数组是一种 **值类型**不像C/C++中是指向首元素的指针所以可以通过 `new()` 来创建 `var arr1 = new([5]int)`
那么这种方式和var arr2 [5]int的区别是什么呢arr1的类型是*[5]int而arr2的类型是[5]int 那么这种方式和 `var arr2 [5]int` 的区别是什么呢arr1 的类型是 `*[5]int` arr2的类型是 `[5]int`
这样的结果就是当把一个数组赋值给另一个时需要在做一次数组内存的拷贝操作例如 这样的结果就是当把一个数组赋值给另一个时需要在做一次数组内存的拷贝操作例如
arr := arr1 arr := arr1
arr2[2] = 100 arr2[2] = 100
这样两个数组就有了不同的值在赋值后修改arr2不会对arr1生效 这样两个数组就有了不同的值在赋值后修改 arr2 不会对 arr1 生效
所以在函数中数组作为参数传入时如func1(arr1)会产生一次数组拷贝func1方法不会修改原始的数组arr1 所以在函数中数组作为参数传入时 func1(arr1)会产生一次数组拷贝func1 方法不会修改原始的数组 arr1
如果你想修改原数组那么arr1必须通过&操作符以引用方式传过来例如func1(&arr1下面是一个例子 如果你想修改原数组那么 arr1 必须通过&操作符以引用方式传过来例如 func1(&arr1下面是一个例子
Example 7.2 [pointer_array.go](examples/chapter_7/pointer_array.go): Example 7.2 [pointer_array.go](examples/chapter_7/pointer_array.go):
@@ -117,7 +117,7 @@ Example 7.2 [pointer_array.go](examples/chapter_7/pointer_array.go):
[0 0 0] [0 0 0]
&[0 0 0] &[0 0 0]
另一种方法就是生成数组分片slice并将其传递给函数参见传递数组参数给函数7.1.4节 另一种方法就是生成数组切片并将其传递给函数参见传递数组参数给函数7.1.4节
**练习** **练习**
@@ -127,8 +127,9 @@ Example 7.2 [pointer_array.go](examples/chapter_7/pointer_array.go):
练习7.3fibonacci_array.go: 在6.6节我们看到了一个递归计算Fibonacci数值的方法但是通过数组我们可以更快的计算出Fibonacci数完成该方法并打印出前50个Fibonacci数字 练习7.3fibonacci_array.go: 在6.6节我们看到了一个递归计算Fibonacci数值的方法但是通过数组我们可以更快的计算出Fibonacci数完成该方法并打印出前50个Fibonacci数字
##7.1.2 数组常量 ## 7.1.2 数组常量
如果数组值已经提前知道了那么可以通过`数组常量`的方法来初始化数组而不用依次使用[]=方法。(所有的组成元素都有相同的常量语法
如果数组值已经提前知道了那么可以通过 **数组常量** 的方法来初始化数组而不用依次使用 `[]=` 方法所有的组成元素都有相同的常量语法)。
Example 7.3 [array_literals.go](examples/chapter_7/array_literals.go) Example 7.3 [array_literals.go](examples/chapter_7/array_literals.go)
@@ -147,19 +148,19 @@ Example 7.3 [array_literals.go](examples/chapter_7/array_literals.go)
} }
} }
第一种变化 var arrAge = [5]int{18, 20, 15, 22, 16} 第一种变化 `var arrAge = [5]int{18, 20, 15, 22, 16}`
注意[5]int可以从左边起开始忽略[10]int {1, 2, 3} :这是一个有10个元素的数组除了前三个元素外其他元素都为0 注意 `[5]int` 可以从左边起开始忽略`[10]int {1, 2, 3}` :这是一个有 10 个元素的数组除了前三个元素外其他元素都为 0
第二种变化 var arrLazy = [...]int{5, 6, 7, 8, 22} 第二种变化 `var arrLazy = [...]int{5, 6, 7, 8, 22}`
`...`可同样可以忽略从技术上说它们其实变化成了slice `...` 可同样可以忽略从技术上说它们其实变化成了切片
第三种变化key: value syntax 第三种变化`key: value syntax`
var arrKeyValue = [5]string{3: "Chris", 4:Ron"} var arrKeyValue = [5]string{3: "Chris", 4:Ron"}
只有索引3和4被赋予实际的值其他元素都被设置为空的字符串所以输出结果为 只有索引 3 4 被赋予实际的值其他元素都被设置为空的字符串所以输出结果为
Person at 0 is Person at 0 is
Person at 1 is Person at 1 is
@@ -167,7 +168,7 @@ Example 7.3 [array_literals.go](examples/chapter_7/array_literals.go)
Person at 3 is Chris Person at 3 is Chris
Person at 4 is Ron Person at 4 is Ron
在这里数组长度同样可以写成`...`或者直接忽略 在这里数组长度同样可以写成 `...` 或者直接忽略
你可以取任意数组常量的地址来作为指向新实例的指针 你可以取任意数组常量的地址来作为指向新实例的指针
@@ -196,9 +197,10 @@ Example 7.4 [pointer_array2.go](examples/chapter_7/pointer_array2.go)
var vec Vector3D var vec Vector3D
## 7.1.3 多维数组 ## 7.1.3 多维数组
数组通常是1维的但是可以用来组装成多维数组例如[3][5]int[2][2][2]float64
内部数组总是长度相同Go语言的多维数组是矩形式的唯一的例外是分片slice的数组参见7.2.5 数组通常是1维但是可以用来组装成多维数组例如`[3][5]int``[2][2][2]float64`
内部数组总是长度相同的Go 语言的多维数组是矩形式的唯一的例外是切片的数组参见第 7.2.5 )。
Example 7.5 [multidim_array.go](examples/chapter_7/multidim_array.go) Example 7.5 [multidim_array.go](examples/chapter_7/multidim_array.go)
@@ -220,9 +222,11 @@ Example 7.5 [multidim_array.go](examples/chapter_7/multidim_array.go)
} }
## 7.1.4 将数组传递给函数 ## 7.1.4 将数组传递给函数
把第一个大数组传递给函数会消耗很多内存有两种方法可以避免这种现象 把第一个大数组传递给函数会消耗很多内存有两种方法可以避免这种现象
- 传递数组的指针 - 传递数组的指针
- 使用数组的分片slice - 使用数组的切片
接下来的例子阐明了第一种方法 接下来的例子阐明了第一种方法
@@ -248,9 +252,10 @@ Example 7.6 [array_sum.go](examples/chapter_7/array_sum.go)
输出结果 输出结果
The sum of the array is: 24.600000 The sum of the array is: 24.600000
但这在Go中并不常用通常使用分片slice。(参考[7](07.2.md) 但这在 Go 中并不常用通常使用切片。(参考 [ 7 ](07.2.md)
## 链接
##链接
- [目录](directory.md) - [目录](directory.md)
- 上一节[数组与](07.0.md) - 上一节[数组与](07.0.md)
- 下一节[分片slices](07.2.md) - 下一节[切片](07.2.md)

View File

@@ -1,4 +1,7 @@
#7.2 # 7.2
164
## 7.2.1 概念 ## 7.2.1 概念
slice是对数组一个连续片段的引用该数组我们称之为相关数组通常是匿名的所以slice是一个引用类型因此更类似于C/C++中的数组类型或者Python中的list类型。这个片段可以是整个数组或者是由起始和终止索引标识的一些项的子集。需要注意的是终止索引标识的项不包括在slice内。Slice提供了一个相关数组的动态窗口。 slice是对数组一个连续片段的引用该数组我们称之为相关数组通常是匿名的所以slice是一个引用类型因此更类似于C/C++中的数组类型或者Python中的list类型。这个片段可以是整个数组或者是由起始和终止索引标识的一些项的子集。需要注意的是终止索引标识的项不包括在slice内。Slice提供了一个相关数组的动态窗口。

View File

@@ -60,6 +60,7 @@
- 6.12 [通过内存缓存来提升性能](06.12.md) - 6.12 [通过内存缓存来提升性能](06.12.md)
- 第7章[数组与切片](07.0.md) - 第7章[数组与切片](07.0.md)
- 7.1 [声明和初始化](07.1.md) - 7.1 [声明和初始化](07.1.md)
- 7.2 [切片](07.2.md)
- 第8章Maps - 第8章Maps
- 第9章package - 第9章package
- 第10章结构struct与方法method - 第10章结构struct与方法method