mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-11-13 17:36:12 +08:00
@@ -5,7 +5,7 @@
|
||||
|
||||
**注意事项** 如果我们想让数组元素类型为任意类型的话可以使用空接口作为类型(参考 [第 11 章](11.9.md))。当使用值时我们必须先做一个类型判断(参考 [第 11 章](11.3.md))。
|
||||
|
||||
数组元素可以通过 **索引**(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。(数组以 0 开始在所有类 C 语言中是相似的)。元素的数目(也称为长度或者数组大小)必须是固定的并且在声明该数组时就给出(编译时需要知道数组长度以便分配内存);数组长度最大为 2GB。
|
||||
数组元素可以通过 **索引**(位置)来读取(或者修改),索引从 `0` 开始,第一个元素索引为 `0`,第二个索引为 `1`,以此类推(数组以 0 开始在所有类 C 语言中是相似的)。元素的数目(也称为长度或者数组大小)必须是固定的并且在声明该数组时就给出(编译时需要知道数组长度以便分配内存);数组长度最大为 2GB。
|
||||
|
||||
声明的格式是:
|
||||
|
||||
@@ -23,21 +23,21 @@ var arr1 [5]int
|
||||
|
||||
每个元素是一个整型值,当声明数组时所有的元素都会被自动初始化为默认值 0。
|
||||
|
||||
arr1 的长度是 5,索引范围从 0 到 `len(arr1)-1`。
|
||||
`arr1` 的长度是 5,索引范围从 `0` 到 `len(arr1)-1`。
|
||||
|
||||
第一个元素是 `arr1[0]`,第三个元素是 `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
|
||||
|
||||
由于索引的存在,遍历数组的方法自然就是使用 for 结构:
|
||||
由于索引的存在,遍历数组的方法自然就是使用 `for` 结构:
|
||||
|
||||
- 通过 for 初始化数组项
|
||||
- 通过 for 打印数组元素
|
||||
- 通过 for 依次处理元素
|
||||
- 通过 `for` 初始化数组项
|
||||
- 通过 `for` 打印数组元素
|
||||
- 通过 `for` 依次处理元素
|
||||
|
||||
示例 7.1 [for_arrays.go](examples/chapter_7/for_arrays.go)
|
||||
|
||||
@@ -66,7 +66,7 @@ func main() {
|
||||
Array at index 3 is 6
|
||||
Array at index 4 is 8
|
||||
|
||||
for 循环中的条件非常重要:`i < len(arr1)`,如果写成 `i <= len(arr1)` 的话会产生越界错误。
|
||||
`for` 循环中的条件非常重要:`i < len(arr1)`,如果写成 `i <= len(arr1)` 的话会产生越界错误。
|
||||
|
||||
IDIOM:
|
||||
|
||||
@@ -86,7 +86,7 @@ for i,_:= range arr1 {
|
||||
}
|
||||
```
|
||||
|
||||
在这里i也是数组的索引。当然这两种 for 结构对于切片(slices)(参考 [第 7 章](07.2.md))来说也同样适用。
|
||||
在这里 `i` 也是数组的索引。当然这两种 `for` 结构对于切片(`slices`)(参考 [第 7 章](07.2.md))来说也同样适用。
|
||||
|
||||
**问题 7.1** 下面代码段的输出是什么?
|
||||
|
||||
@@ -99,7 +99,7 @@ for i := range a {
|
||||
|
||||
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`。
|
||||
|
||||
这样的结果就是当把一个数组赋值给另一个时,需要再做一次数组内存的拷贝操作。例如:
|
||||
|
||||
@@ -108,11 +108,11 @@ arr2 := *arr1
|
||||
arr2[2] = 100
|
||||
```
|
||||
|
||||
这样两个数组就有了不同的值,在赋值后修改 arr2 不会对 arr1 生效。
|
||||
这样两个数组就有了不同的值,在赋值后修改 `arr2` 不会对 `arr1` 生效。
|
||||
|
||||
所以在函数中数组作为参数传入时,如 `func1(arr2)`,会产生一次数组拷贝,func1 方法不会修改原始的数组 arr2。
|
||||
所以在函数中数组作为参数传入时,如 `func1(arr2)`,会产生一次数组拷贝,`func1()` 方法不会修改原始的数组 `arr2`。
|
||||
|
||||
如果你想修改原数组,那么 arr2 必须通过&操作符以引用方式传过来,例如 func1(&arr2),下面是一个例子
|
||||
如果你想修改原数组,那么 `arr2` 必须通过 `&` 操作符以引用方式传过来,例如 `func1(&arr2`,下面是一个例子:
|
||||
|
||||
示例 7.2 [pointer_array.go](examples/chapter_7/pointer_array.go):
|
||||
|
||||
@@ -128,21 +128,27 @@ func main() {
|
||||
fp(&ar) // passes a pointer to ar
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
输出结果:
|
||||
|
||||
[0 0 0]
|
||||
&[0 0 0]
|
||||
|
||||
另一种方法就是生成数组切片并将其传递给函数(详见第 7.1.4 节)。
|
||||
另一种方法就是生成数组切片并将其传递给函数(详见[第 7.1.4 节](07.1.md))。
|
||||
|
||||
**练习**
|
||||
|
||||
练习7.1:array_value.go: 证明当数组赋值时,发生了数组内存拷贝。
|
||||
练习7.1:[array_value.go](examples\chapter_7\array_value.go):
|
||||
|
||||
练习7.2:for_array.go: 写一个循环并用下标给数组赋值(从 0 到 15)并且将数组打印在屏幕上。
|
||||
证明当数组赋值时,发生了数组内存拷贝。
|
||||
|
||||
练习7.3:fibonacci_array.go: 在第 6.6 节我们看到了一个递归计算 Fibonacci 数值的方法。但是通过数组我们可以更快的计算出 Fibonacci 数。完成该方法并打印出前 50 个 Fibonacci 数字。
|
||||
练习7.2:[for_array.go](examples\chapter_7\for_array.go):
|
||||
|
||||
写一个循环并用下标给数组赋值(从 0 到 15)并且将数组打印在屏幕上。
|
||||
|
||||
练习7.3:[fibonacci_array.go](examples\chapter_7\fibonacci_array.go):
|
||||
|
||||
在[第 6.6 节](06.6.md) 我们看到了一个递归计算 Fibonacci 数值的方法。但是通过数组我们可以更快的计算出 Fibonacci 数。完成该方法并打印出前 50 个 Fibonacci 数字。
|
||||
|
||||
## 7.1.2 数组常量
|
||||
|
||||
@@ -173,7 +179,7 @@ func main() {
|
||||
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`。
|
||||
|
||||
第二种变化:
|
||||
|
||||
@@ -217,10 +223,12 @@ func main() {
|
||||
```
|
||||
|
||||
输出结果:
|
||||
|
||||
&[0 0 0]
|
||||
&[1 1 1]
|
||||
&[2 4 8]
|
||||
|
||||
```
|
||||
&[0 0 0]
|
||||
&[1 1 1]
|
||||
&[2 4 8]
|
||||
```
|
||||
|
||||
几何点(或者数学向量)是一个使用数组的经典例子。为了简化代码通常使用一个别名:
|
||||
|
||||
@@ -233,7 +241,7 @@ var vec Vector3D
|
||||
|
||||
数组通常是一维的,但是可以用来组装成多维数组,例如:`[3][5]int`,`[2][2][2]float64`。
|
||||
|
||||
内部数组总是长度相同的。Go 语言的多维数组是矩形式的(唯一的例外是切片的数组,参见第 7.2.5 节)。
|
||||
内部数组总是长度相同的。Go 语言的多维数组是矩形式的(唯一的例外是切片的数组,参见[第 7.2.5 节](07.2.md)。
|
||||
|
||||
示例 7.5 [multidim_array.go](examples/chapter_7/multidim_array.go)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user