Go 数组
数组的初始化
字面量初始化
var numbers [3]int = [3]int{1, 2, 3}
fruits := [3]string{"apple", "banana", "cherry"}
在 Go 语言中,我可以使用字面量直接初始化数组。上面的代码中,numbers
是一个长度为 3 的整型数组,fruits
是一个长度为 3 的字符串数组。
索引初始化
chars := [5]string{0: "a", 2: "c", 4: "e"}
使用索引初始化数组,可以指定元素的索引位置。未被初始化的元素将采用零值。
省略长度初始化
values := [...]int{1, 2, 3, 4, 5}
使用 ...
省略数组长度,编译器会根据初始化的元素个数自动推断数组长度。
默认初始化
var flags [3]bool // flags 的所有元素将被初始化为 false
未显式初始化的数组元素将采用元素类型的零值。例如,布尔类型的零值为 false
。
使用其他数组或切片初始化
var source [3]int = [3]int{1, 2, 3}
var target [3]int
for i, v := range source {
target[i] = v
}
通过遍历另一个数组或切片,可以初始化新的数组。
Go 的数组特性
Go 语言的数组是定长且类型固定的,并且是值类型,而非引用类型。这意味着当我将一个数组赋值给另一个数组时,会创建该数组的一个副本,而不是指向原数组的引用。
arrayA := [3]int{1, 2, 3}
arrayB := arrayA
arrayB[0] = 100
fmt.Println(arrayA) // 输出:[1 2 3]
fmt.Println(arrayB) // 输出:[100 2 3]
如上所示,修改 arrayB
并不会影响 arrayA
,因为它们是两个独立的数组。
数组的相等性判断
在 Go 语言中,数组的相等性判断有以下规则:
长度和类型必须相同
只有当两个数组的长度和元素类型都相同时,才能使用 ==
运算符比较它们。否则,编译器会报错。
逐元素比较
使用 ==
运算符比较数组时,会逐元素比较对应位置的元素。只有所有元素都相等时,数组才被认为是相等的。
元素类型必须可比较
数组元素的类型必须是可比较的类型。例如,基本类型(如 int
、float64
、string
)和指针类型都是可比较的,但切片、映射等类型不可比较。
arr1 := [3]int{1, 2, 3}
arr2 := [3]int{1, 2, 3}
arr3 := [3]int{4, 5, 6}
fmt.Println(arr1 == arr2) // 输出:true
fmt.Println(arr1 == arr3) // 输出:false
数组的零值
不同类型的数组,其元素的默认零值如下:
数据类型 | 零值 | 示例 |
---|---|---|
整数 (int ) | 0 | [0, 0, 0] |
浮点数 (float64 ) | 0.0 | [0.0, 0.0, 0.0] |
布尔 (bool ) | false | [false, false, false] |
字符串 (string ) | "" | ["", "", ""] |
指针 (*Type ) | nil | [nil, nil, nil] |
数组 ([N]Type ) | 元素零值 | [[0, 0], [0, 0], [0, 0]] 对于 [3][2]int 类型 |
结构体 (struct ) | 字段零值 | 根据结构体字段类型而定 |
切片 ([]Type ) | nil | [nil, nil, nil] |
映射 (map[KeyType]ValueType ) | nil | [nil, nil, nil] |
通道 (chan Type ) | nil | [nil, nil, nil] |
接口 (interface{} ) | nil | [nil, nil, nil] |
函数 (func(...) ) | nil | [nil, nil, nil] |
二维数组的使用
声明
要声明一个二维数组,需要指定每个维度的长度。
var matrix [3][3]int // 声明一个 3x3 的整型二维数组
初始化
可以在声明时使用花括号 {}
初始化二维数组。
var matrix = [3][3]int{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},
}
访问元素
使用行索引和列索引来访问二维数组的元素。
value := matrix[1][2] // 访问第 2 行第 3 列的元素,值为 6
遍历二维数组
可以使用嵌套的 for
循环来遍历二维数组。
for i := 0; i < len(matrix); i++ {
for j := 0; j < len(matrix[i]); j++ {
fmt.Printf("%d ", matrix[i][j])
}
fmt.Println()
}
数组与切片的区别
虽然数组在 Go 语言中是基础的数据结构,但由于其长度固定,使用起来不够灵活。切片(Slice)提供了动态数组的功能,更加灵活和常用。
- 数组是定长的,长度是类型的一部分。
- 切片是变长的,可以动态增长和收缩。
- 切片是对底层数组的一个视图,可以共享底层数据。
示例:
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // 创建切片,包含 arr 的第 2 到第 4 个元素
fmt.Println(slice) // 输出:[2 3 4]
注意事项
- 在需要固定长度的情况下,使用数组可以获得性能上的优势。
- 当需要灵活处理元素数量时,应优先考虑使用切片。
- 理解数组是值类型,有助于避免在函数传参时出现意外的副本。