Go语言基础之数组

数组是同一种数据类型元素的集合。 在Go语言中,数组从声明时就确定,使用时可以修改数组成员,但是数组大小不可变化。 基本语法:

var a [3]int

数组的长度是数组类型的一部分(如ar a [3]int的Type为[3]int)。

1. 介绍

  1. 数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。因为数组的长度是固定的,所以在Go语言中很少直接使用数组。

  2. 数组的每个元素都可以通过索引下标来访问,索引下标的范围是从 0 开始,内置函数 len() 可以返回数组中元素的个数。

  3. 数组在Go中为值类型;(这是和Java非常不同的一点)

  4. 数组之间可以使用==或者!=进行比较,但不可以使用<>

  5. 可以使用new来创建数组,此方法返回一个指向数组的指针

2. 数组定义

默认定义

数组的声明需要存储元素的长度值和存储数据的类型。其表示形式为 [n]Tn 表示数组中元素的长度值,T 代表每个元素的类型,数组的长度在声明的时候一定要给定,而数组一旦声明,其长度和类型都不能改变。

var 数组变量名 [元素数量]Type
  • 数组变量名:数组声明及使用时的变量名。

  • 元素数量:数组的元素数量,可以是一个表达式,但最终通过编译期计算的结果必须是整型数值,元素数量不能含有到运行时才能确认大小的数值。

  • Type:可以是任意基本类型,包括数组本身,类型为数组本身时,可以实现多维数组。

eg:

package main

import (
"fmt"
)

func main() {
var a [3]int //int array with length 3
fmt.Println(a)
}

3. 数组初始化

指定元素

初始化元素通过大括号包裹起来。

var <数组名称> = [<数组长度>]<元素类型>{元素1,元素2,...}

eg:

package main

import (
"fmt"
)

func main() {
a := [3]int{1, 2, 5}
fmt.Println(a)
}

在简略声明中,不需要将数组中所有的元素赋值。

package main

import (
"fmt"
)

func main() {
a := [3]int{10}
fmt.Println(a)
}

在上述程序中的第 8 行 a := [3]int{10} 声明一个长度为 3 的数组,但只提供了一个值 10,剩下的 2 个元素自动赋值为 0。这个程序将输出[10 0 0]

省略号

数组的长度可以使用省略号 ... 代替,这个并不是代表可以省略数组长度的声明,编译器会自动计算数组长度,它的长度值等于当前数组初始化元素的个数。

package main

import (
"fmt"
)

func main() {
a := [...]int{12, 78, 50} // ... makes the compiler determine the length
fmt.Println(a)
}

4. 数组的遍历

遍历数组有以下两种方法:

func main() {
var a = [...]string{"北京", "上海", "深圳"}
// 方法1:for循环遍历
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
// 方法2:for range遍历
for index, value := range a {
fmt.Println(index, value)
}
}

5. 注意

注意Go 中的数组是值类型而不是引用类型。

零值

如果数组的元素没有被赋值,那么每个元素都会被初始化为元素类型对应的零值。

var r [3]int = [3]int{1, 2}
fmt.Println(r[2]) // "0"

省略号

如果在数组长度的位置出现“…”省略号,则表示数组的长度是根据初始化值的个数来计算。

q := [...]int{1, 2, 3}
fmt.Printf("%T\n", q) // "[3]int"

长度决定类型

数组的长度是数组类型的一个组成部分,因此 [3]int 和 [4]int 是两种不同的数组类型,数组的长度必须是常量表达式,因为数组的长度需要在编译阶段确定。

q := [3]int{1, 2, 3}
q = [4]int{1, 2, 3, 4} // 编译错误:无法将 [4]int 赋给 [3]int

区分 指向数组的指针 和 指针数组

package main
import "fmt"
func main() {
//指向数组的指针
var p *[10]int=&a
fmt.Print(p) // &[0,0,0,0,0,0,0,0,0]
//指针数组
x,y :=1,2
a:=[...]*int{&x,&y}
fmt.Print(a) // [0xc0420080c0 0xc0420080c8]
}

比较两个数组是否相等

  1. 使用运算符(==!=)来判断两个数组是否相等,两个数组类型相同(包括数组的长度,数组中元素的类型)且所有元素都是相等的时候数组才是相等的。
  2. 不能比较两个类型不同的数组,否则程序将无法完成编译。
a := [2]int{1, 2}
b := [...]int{1, 2}
c := [2]int{1, 3}
fmt.Println(a == b, a == c, b == c) // "true false false"
d := [3]int{1, 2}
fmt.Println(a == d) // 编译错误:无法比较 [2]int == [3]int

6. 多维数组

介绍

因为数组属于值类型,所以多维数组的所有维度都会在创建时自动初始化零值。

多维数组只有第一层可以使用...来让编译器推导数组长度。

// array_name 为数组的名字
// size1、size2 等等为数组每一维度的长度
// array_type 为数组的类型
var array_name [size1][size2]...[sizen] array_type

二维数组

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

// 声明一个二维整型数组,两个维度的长度分别是 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

同样类型的多维数组赋值

// 声明两个二维整型数组
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]

总结

1.数组是同一类型元素的集合,因此存储的数据类似必须是相同的

2.数组是有固定长度的,因此需要初始化数组时声明长度。

3.长度一样且每个元素的类型和值也一样的数组,才能相等。

4.数组属于值类型的,即将一个数组赋值给另外一个数组的时候,实际上就是将整个数组拷贝一份。

参考感谢
Go基础——数组 · 语雀 (yuque.com)
array 数组、slice 切片、list 列表、map 集合 · 语雀 (yuque.com)
数组 · 语雀 (yuque.com)
数组结构 · 语雀 (yuque.com)