[奔跑的 Go] 教程八、深入学习 Go 语言数组(Array)

Golang

数组是一个容纳相同数据类型的容器。 Go 中的数组的长度是固定的,无法因为数据的增加而自动扩展。

☛ 什么是数组

数组是具有 相同数据类型的 集合。例如,整型数组或字符串数数组。由于 Go 是静态类型语言,因此 不允许在数组中混合不同类型的数据

在 Go 中,数组的长度是固定的。一旦定义,数组的长度就不能增加或减少。这个问题可以通过 切片来解决

数组是一种复合数据类型,它由 整型字符串布尔 等原始数据类型组成。

☛ 如何定义一个数组?

数组本身是一种数据类型。这种类型定义的形式类似这样 [n]T ,其中 n是数组中元素的数量, T 是一种数据类型类似 int 或 string之类的。

因此要定义一个变量为一个容量为 3int型数组,可按照以下语法

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 == stringapple == orange 一样,这是无效和无意义的。 因此,与其他编程语言不同,这些不同数据类型的数组是不能相互比较的。

然而 [6] int 可以与 [3] int 进行比较,即使它们的数组元素不匹配,但是因为它们具有相同的数据类型。

对于与第二个数组是相同条件是:两个数组应该是相同的类型,其中必须包含相同的元素,并且所有元素必须是相同的顺序。 在这种情况下,用 == 比较 将返回的结果是 true。 如果这些条件中的一个或多个不匹配,则返回 false

Go 首先匹配数据类型,然后根据数组的索引来比较两个数组的每个元素是否相同(包括元素的值以及顺序是否相同)。

我们可以看看下面的这段代码。

https://play.golang.org/p/U933frU9Gql

四个数组 a, bc  和 d , 都具有相同的数据类型  [3]int。首先比较的是数组 ab ,由于数组 ab 都包含相同个数的元素,但是数组的顺序不一致,这个结果将会返回 false 。其次比较的是  a == c,由于数组 c  包含的元素和数组 a 完全不相同,这种情况将会返回 false

但是在第三次比较的情况下,由于数组 ad 包含相同顺序的相同元素,因此a == d 将返回 true 。 因此上面的程序打印结果如下。

☛数组迭代

要遍历数组,可以使用' for '循环。

https://play.golang.org/p/v5oGN2qQbgN

在上面的例子中,由于数组中的索引index总是小于len(a),所以我们可以使用简单的for循环打印数组中的每个元素。

但是我们不提倡这种数组的遍历方式,因为我们需要使用index来获取数组的元素。不过不用担心,Go提供了range操作符,它返回for循环中数组的每个元素的 indexvalue

https://play.golang.org/p/XY9pONQaYng

range操作符返回与他关联的一个元素的indexvalue,直到数组中的所有元素都取完。如果您对索引不感兴趣,我们可以将它分配给空白标识符。

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 {
        ...
    }
}

值传递

intstring 类型一样,将数组传递给函数,属于值传递。函数只是接收它的副本。因此,在函数内部对数组的改变,不会影响原始数组的值。

我为什么要强调这一点,因为,当后面学到 slice 的时候,你会发现就不是这个情况了。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/rungo/the-anatomy-of-...

译文地址:https://learnku.com/go/t/28520

本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!