[奔跑的 Go] 教程八、深入学习 Go 语言数组(Array)
数组是一个容纳相同数据类型的容器。 Go 中的数组的长度是固定的,无法因为数据的增加而自动扩展。
☛ 什么是数组
数组是具有 相同数据类型的 集合。例如,整型数组或字符串数数组。由于 Go 是静态类型语言,因此 不允许在数组中混合不同类型的数据。
在 Go 中,数组的长度是固定的。一旦定义,数组的长度就不能增加或减少。这个问题可以通过 切片来解决。
数组是一种复合数据类型,它由
整型
,字符串
,布尔
等原始数据类型组成。
☛ 如何定义一个数组?
数组本身是一种数据类型。这种类型定义的形式类似这样 [n]T
,其中 n
是数组中元素的数量, T
是一种数据类型类似 int
或 string
之类的。
因此要定义一个变量为一个容量为 3
的int
型数组,可按照以下语法
package main
import "fmt"
func main() {
var a [3]int
fmt.Println(a)
}
以上程序中, a
是一个具有3 个整型元素的数组,但是我们还没给其中任何一个元素赋值。猜下Println
语句会打印什么,空数组会是什么值?
由于我们没有为a
分配任何值,我们只是定义了数组而不是数组元素的值。 因此它的数据类型的值为零。 对于int
,如果为0
则为零值,因此Println
语句将打印3个零的数组。
[0 0 0]
☛ 值的分配
我们可以通过数组元素的索引,分别为数组中每个的元素赋值。在 Go 中,数组第一个元素的索引值从 “0” 开始,因此,最后一个元素的索引值是 “n-1”,其中 “n” 是数组的长度。
要访问数组中的元素,可以使用 a [index]
语法,其中 a
是一个数组变量。所以我们先来看一下我们之前的例子并稍微修改一下。
https://play.golang.org/p/_4DMJ3iRqRF
在上面的程序中,我们使用 a [index]
语法为数组中的 3 个元素赋值。
☛ 初始值
如果数组很大,在定义时分别为每个元素赋值是非常困难的。因此,Go 提供了 简写语法,用于定义具有初始值的数组或具有预定义值的数组元素。语法格式如下
var a [n]T = [n]T{V1,V2,...,Vn}
在前面的例子中,如果数组元素的值为 “1,2,3”,可以这样定义
var a [3]int = [3]int{1, 2, 3}
还可以省略左侧的类型,Go 可以从数组的定义中推断出数据类型。
var a = [3]int{1, 2, 3}
还可以删除 var
,直接使用简写语法 :=
a := [3]int{1, 2, 3}
并不是一定要为数组中的每个元素都赋值。在上面的例子中,我们可以只为前两个元素赋值,第三个元素保持零值。
https://play.golang.org/p/J4x7X8Vg73G
☛ 多行初始值
你可以在多行上定义具有初始值的数组,但是由于这些值需要逗号分隔,所以要确保在最后一个元素的末尾添加逗号。为什么要这样呢, 深入阅读下去。
https://play.golang.org/p/IcwpC-fQQBj
仔细看,我们在数组的最后一个元素末尾使用了逗号(,)。这个逗号是必要的,如果它不存在,Go就会添加一个分号(;),这将导致程序崩溃。
☛ 数组长度的自动申明
有时候,我们在输入数组的元素的时候,并不知道数组的长度是多少。因此 Go 提供了 ...
运算符代替 [n] T
数组类型语法中的 n
。Go 编译器将会自行查找和计算出数组的长度。但是这种操作只能在定义具有初始值的数组时,才能使用此运算符。
https://play.golang.org/p/UKl32kgngnF
上面的程序将打印相同的结果,因为 Go 编译器会统计数组的元素个数为「4」
☛ 求取数组的长度
Go提供一个内置的函数len
,用于计算许多数据类型的长度,在这里我们可以用它来计算数组的长度
https://play.golang.org/p/wV9edsKhuh4
☛ 数组的比较
正如我们之前在数组定义中讨论的那样,数组本身就是一种数据类型。 [3] int
与 [4] int
是两个不同的数组,与 [4] string
更是不同的两个数组。这就像比较int == string
或 apple == orange
一样,这是无效和无意义的。 因此,与其他编程语言不同,这些不同数据类型的数组是不能相互比较的。
然而 [6] int
可以与 [3] int
进行比较,即使它们的数组元素不匹配,但是因为它们具有相同的数据类型。
对于与第二个数组是相同条件是:两个数组应该是相同的类型,其中必须包含相同的元素,并且所有元素必须是相同的顺序。 在这种情况下,用 ==
比较 将返回的结果是 true
。 如果这些条件中的一个或多个不匹配,则返回 false
。
Go 首先匹配数据类型,然后根据数组的索引来比较两个数组的每个元素是否相同(包括元素的值以及顺序是否相同)。
我们可以看看下面的这段代码。
https://play.golang.org/p/U933frU9Gql
四个数组 a
, b
,c
和 d
, 都具有相同的数据类型 [3]int
。首先比较的是数组 a
和 b
,由于数组 a
和 b
都包含相同个数的元素,但是数组的顺序不一致,这个结果将会返回 false
。其次比较的是 a == c
,由于数组 c
包含的元素和数组 a
完全不相同,这种情况将会返回 false
。
但是在第三次比较的情况下,由于数组 a
和 d
包含相同顺序的相同元素,因此a == d
将返回 true
。 因此上面的程序打印结果如下。
☛数组迭代
要遍历数组,可以使用' for '循环。
https://play.golang.org/p/v5oGN2qQbgN
在上面的例子中,由于数组中的索引index
总是小于len(a)
,所以我们可以使用简单的for
循环打印数组中的每个元素。
但是我们不提倡这种数组的遍历方式,因为我们需要使用index
来获取数组的元素。不过不用担心,Go提供了range
操作符,它返回for
循环中数组的每个元素的 index
和value
。
https://play.golang.org/p/XY9pONQaYng
range
操作符返回与他关联的一个元素的index
和value
,直到数组中的所有元素都取完。如果您对索引不感兴趣,我们可以将它分配给空白标识符。
https://play.golang.org/p/z0_v0CKquXU
☛ 多维数组
当数组的元素是数组时,我们把它称为多维数组。从数组的定义来看,数组是相同类型的数据集合,数组本身也是一种数据类型,多维数组里的元素也必须是相同的数据类型。
多维数组的格式是 [n] [m] T
,其中 n
是数组中元素的数量,m
是内层数组中元素的数量。从技术上讲,我们可以说这个数组包含 n
个 [m] T
类型的元素。
https://play.golang.org/p/7Hfeb30HD-H
既然我们可以使用 ...
运算符来猜测数组的大小,那么,上面的程序也可以写成如下形式:
https://play.golang.org/p/w7oyAb_Acik
Go 还提供了多维数组的简写方式:
https://play.golang.org/p/_ZMipOrWy1R
在上面的程序中,Go 编译器从赋值中已经可以判断数组元素的类型为 [2] int
, 所以也可以将其省略,并用 ...
运算符代替:
a := [...][2]int{{1, 2}, {3, 4}, {5, 6}}
多维数组的遍历与普通数组没有什么不同。只是在遍历多维数组时,得到的值还需要继续进行遍历。因此,你可以看到 for
循环中还嵌套着另一个 for
循环:
for _, child := range parent {
for _, elem := range child {
...
}
}
值传递
像 int
或 string
类型一样,将数组传递给函数,属于值传递。函数只是接收它的副本。因此,在函数内部对数组的改变,不会影响原始数组的值。
我为什么要强调这一点,因为,当后面学到 slice
的时候,你会发现就不是这个情况了。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: