首页 > 编程笔记

Go语言数组的定义和使用(非常详细)

数组是Go语言复合数据类型的基础,了解Go语言的数据结构,一般从数组开始学习。理解了数组的工作原理,学习切片、映射及列表才会更加容易。

数组的声明

Go语言数组是具有相同类型的一组已经编号且长度固定的数据项序列,这个序列可以是有序的也可以是无序的,组成数组的各个变量称为数组的元素。

数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1,以此类推。

数组元素的索引如图1所示。

Go语言数组元素的索引
图1:数组元素的索引

数组元素的类型可以是任意的原始类型,如 int、string 或者自定义类型。数组长度必须是一个非负整数的常量(或常量表达式),数组长度也是数组类型的一部分,所以,[20]int 和 [100]int 不是同一种类型。

Go语言数组的声明需要指定元素的类型及元素的个数,语法格式如下:

var 数组变量名 [元素数量]Type

对格式的说明:
举几个例子:
//声明一个包含5个元素的整型数组
var array [5]int
//声明一个包含3个元素的字符串数组
var team [3]string
数组一旦声明,它存储的数据类型和数组长度就都不能修改了。所以,如果需要存储更多的元素,必须先创建一个更长的数组,然后把原来数组中的值复制到新数组中。

数组的特点可以总结为以下几点:

数组的初始化

Go语言在声明变量时,都是使用相应类型的零值来初始化变量的,数组也一样。数组初始化时,其每个元素都被初始化为对应类型的零值。例如,上面的整型数组中,每个元素都被初始化为 0(整型的零值)。

数组的初始化有以下几种情况:

1) 使用数组字面量可以快速创建并初始化数组,数组字面量可以声明数组中元素的数量,并指定每个元素的值,例如:
//声明一个包含3个元素的整型数组
//用具体值初始化每个元素
a := [3]int {1,2,3}

2) 当数组的长度不确定时,可以使用来代替数组的长度,Go语言会根据初始化时数组元素的数量来确定该数组的长度,例如:
//声明一个整型数组
//用具体值初始化每个元素
//长度由初始化的值来确定
a := […]int {1,2,3}

3) 当知道数组的总长度时,还可以给特定的下标指定具体的值。通过索引值进行初始化,没有初始化元素时使用类型默认值,例如:
//声明一个包含3个元素的整型数组
//用具体值初始化索引为1和2的元素
//其余元素保持类型默认值
a := [3]int {1:1,2:3}

4) 当不确定数组的总长度时,同样也可以给特定的下标指定具体的值。通过索引值进行初始化,数组长度由最后一个索引值确定,没有指定索引的元素被初始化为类型的零值,例如:
//声明一个整型数组
//用具体值初始化索引为1和2的元素
//长度由最后一个索引值来确定
//其余元素保持零值
a := […]int {1:1,2:3}

数组的使用

与其他编程语言一样,Go语言的数组可以通过数组下标(索引位置)来访问或修改数组的元素。

1) 访问数组元素

数组的每个元素都可以通过索引下标来访问,索引下标的范围是从 0 开始,第一个元素索引为 0,第二个元素索引为 1,以此类推。元素的数目(长度或者数组大小)必须是固定的并且在声明数组时就指定的,数组长度最大为 2GB。

请看下面的Go语言代码:
package main
import "fmt"
func main() {
   var n [10]int  /*n 是一个长度为 10 的数组*/
   var i,j int
   /*为数组 n 初始化元素*/
   for i = 0; i < 10; i++ {
      n[i] = i + 100  /*设置元素为 i + 100*/
   }
   /*输出每个数组元素的值*/
   for j = 0; j < 10; j++ {
      fmt.Printf("元素[%d] = %d\n", j, n[j] )
   }
}
运行结果如图2所示。

Go语言访问数组元素
图2:访问数组元素

2) 修改数组元素

数组是效率很高的数据结构,因为数组在内存分配中是连续的,要访问数组中的某个单独元素,需要使用[]运算符,例如:
//声明一个包含5个元素的整型数组
//用具体值初始化每个元素
a := [5]int {1,2,3,4,5}
//修改索引为2的元素的值
a[2] = 8

数组的值也可以是指针。例如,声明一个所有元素都是指针的数组,然后使用*运算符访问元素指针所指向的值。

请看下面的Go语言示例:
//声明一个包含5个元素的整型数组
//用整型指针初始化索引为0和1的数组元素
a := [5]*int {0: new(int), 1: new(int)}
//为索引为0和1的元素赋值
*a[0] = 1
*a[1] = 2
在Go语言中,数组是一个类型值,也就是说,数组可以像函数一样用在赋值操作中,变量名代表整个数组,因此,同样类型的数组可以赋值给另一个数组,例如:
//声明一个包含5个元素的字符串数组
var a1 [5]string
//声明第二个包含5个元素的字符串数组
//用颜色初始化数组
a2 := [5]string{ " red ", "blue ", "green ", "yellow ", "pink "}
//把a2的值赋值给a1
a1 = a2
赋值之后,两个数组的值完全一样。

数组作为变量类型,包括数组长度和每个元素的类型两个部分。只有这两部分都相同的数组才是类型相同的数组,才能相互赋值,例如:
//声明一个包含4个元素的字符串数组
var a1 [4]string
//声明第二个包含5个元素的字符串数组
//用颜色初始化数组
a2 := [5]string{ " red ", "blue ", "green ", "yellow ", "pink "}
//将a2赋值给a1
a1 = a2
此时会出现错误:

cannot use a2 (type [5]string) as type [4]string in assignment

与之前的参数传递一样,如果赋值数组指针,只会赋值指针的值,而不会赋值指针所指向的值,例如:
//声明第一个包含3个元素的指向字符串的指针数组
var a1 [3]*string
//声明第二个包含3个元素的指向字符串的指针数组
//使用字符串指针初始化数组
a2 := [3]*string { new(string), new(string), new(string)}
//使用颜色为每个元素赋值
*a2[0] = "red"
*a2[1] = "blue"
*a2[2] = "green"
//将a2赋值给a1
a1 = a2
赋值操作之后,两个数组指向同一组字符串。

多维数组

数组本身只有一个维度,但是可以组合多个数组来创建多维数组。

Go语言中允许使用多维数组,因为数组属于值类型,所以,多维数组的所有维度都会在创建时自动初始化零值,多维数组尤其适合管理具有父子关系或者与坐标系相关联的数据。

声明多维数组的语法格式如下:

var array_name [size1][size2]…[sizen] array_type

其中,array_name 为数组的名字,array_type 为数组的类型,size1、size2…sizen 为数组每一维度的长度。

二维数组是最简单的多维数组,二维数组本质上是由多个一维数组组成的。

例如,声明一个二维数组:
//声明一个二维整型数组,两个维度的长度分别是 4 和 2
var array [4][2]int
//使用数组字面量来声明并初始化一个二维整型数组
array = [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}}
//声明并初始化数组中索引为 1 和 3 的元素
array = [4][2]int{1: {20, 21}, 3: {40, 41}}
//声明并初始化数组中指定的元素
array = [4][2]int{1: {0: 20}, 3: {1: 41}}
此时为了访问单个元素,需要组合使用[]运算符,例如:
//声明一个 2×2 的二维整型数组
var array [2][2]int
//设置每个元素的整型值
array[0][0] = 10
array[0][1] = 20
array[1][0] = 30
array[1][1] = 40
与一维数组相同,只要类型一致,就可以将多维数组互相赋值。多维数组的类型包括两个部分,即每一维度的长度和存储在元素中数据的类型。

请看下面的Go语言代码:
//声明两个二维整型数组
var array1 [2][2]int
var array2 [2][2]int
//为array2的每个元素赋值
array2[0][0] = 10
array2[0][1] = 20
array2[1][0] = 30
array2[1][1] = 40
//将 array2 的值赋值给array1
array1 = array2
实际上,数组中的每个元素都是一个单独的值,所以,可以独立复制某个维度,例如:
//将 array1 的索引为 1 的维度复制到一个同类型的新数组中
var array3 [2]int = array1[1]
//将数组中指定的整型值复制到新的整型变量中
var value int = array1[1][0]

推荐阅读