跳到主要内容

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 语言中,数组的相等性判断有以下规则:

长度和类型必须相同

只有当两个数组的长度和元素类型都相同时,才能使用 == 运算符比较它们。否则,编译器会报错。

逐元素比较

使用 == 运算符比较数组时,会逐元素比较对应位置的元素。只有所有元素都相等时,数组才被认为是相等的。

元素类型必须可比较

数组元素的类型必须是可比较的类型。例如,基本类型(如 intfloat64string)和指针类型都是可比较的,但切片、映射等类型不可比较。

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]

注意事项

  • 在需要固定长度的情况下,使用数组可以获得性能上的优势。
  • 当需要灵活处理元素数量时,应优先考虑使用切片。
  • 理解数组是值类型,有助于避免在函数传参时出现意外的副本。