Go语言数组详解
在 Go 语言中,数组是一种固定长度的、由相同类型元素组成的序列。一旦声明,数组的长度便无法改变。数组的成员可以通过索引进行修改。
数组声明
数组的声明语法如下:
var arrayName [arrayLength]dataType
其中,arrayLength 必须是编译时常量,且是数组类型的一部分。这意味着具有不同长度的数组是不同的类型。
var arr1 [3]int // 声明一个长度为3的int类型数组
var arr2 [4]int // 声明一个长度为4的int类型数组
// arr1 = arr2 // 错误![3]int 和 [4]int 是不同类型
数组元素可以通过索引访问,索引从 0 开始。访问越界(索引超出 0 到 len(array)-1 的范围)将导致程序 panic。
数组初始化
数组可以通过多种方式进行初始化:
方式一:显式初始化
在声明时提供元素值列表。
func main() {
var defaultArray [3]int // 数组元素会被初始化为对应类型的零值
var initializedArray = [3]int{1, 2} // 使用指定的值初始化,未指定的部分为零值
var stringArray = [3]string{"A", "B", "C"} // 初始化字符串数组
fmt.Println(defaultArray) // 输出: [0 0 0]
fmt.Println(initializedArray) // 输出: [1 2 0]
fmt.Println(stringArray) // 输出: [A B C]
}
方式二:自动推断长度
使用 ... 关键字,让编译器根据初始值的数量自动推断数组的长度。
func main() {
var autoLenArray = [...]int{10, 20} // 编译器推断长度为 2
var autoStringArray = [...]string{"X", "Y", "Z"} // 编译器推断长度为 3
fmt.Println(autoLenArray) // 输出: [10 20]
fmt.Printf("autoLenArray 的类型: %T\n", autoLenArray) // 输出: autoLenArray 的类型: [2]int
fmt.Println(autoStringArray) // 输出: [X Y Z]
fmt.Printf("autoStringArray 的类型: %T\n", autoStringArray) // 输出: autoStringArray 的类型: [3]string
}
方式三:指定索引初始化
可以为特定索引的元素赋值,未指定的索引将使用零值。
func main() {
sparseArray := [...]int{1: 5, 3: 10} // 索引 1 的值为 5,索引 3 的值为 10
fmt.Println(sparseArray) // 输出: [0 5 0 10]
fmt.Printf("sparseArray 的类型: %T\n", sparseArray) // 输出: sparseArray 的类型: [4]int
}
数组遍历
可以使用 for 循环或 for range 循环遍历数组。
func main() {
myArray := [...]string{"Apple", "Banana", "Cherry"}
// 使用 for 循环遍历
fmt.Println("使用 for 循环:")
for i := 0; i < len(myArray); i++ {
fmt.Println(myArray[i])
}
// 使用 for range 遍历
fmt.Println("使用 for range:")
for index, value := range myArray {
fmt.Printf("索引: %d, 值: %s\n", index, value)
}
}
多维数组
Go 支持多维数组,最常见的是二维数组。
定义二维数组
func main() {
// 定义一个 3x2 的二维字符串数组
matrix := [3][2]string{
{"Row1Col1", "Row1Col2"},
{"Row2Col1", "Row2Col2"},
{"Row3Col1", "Row3Col2"},
}
fmt.Println(matrix) // 输出: [[Row1Col1 Row1Col2] [Row2Col1 Row2Col2] [Row3Col1 Row3Col2]]
fmt.Println(matrix[2][1]) // 访问元素: Row3Col2
}
注意: 在多维数组声明中,只有最外层维度可以使用 ... 让编译器自动推断长度。
// 合法的写法
validMatrix := [...][2]string{
{"A", "B"},
{"C", "D"},
{"E", "F"},
}
// 不合法的写法 (内层维度不能使用 ...)
// invalidMatrix := [3][...]string{ ... }
数组是值类型
数组在 Go 中是值类型。这意味着当数组被赋值或作为参数传递给函数时,会创建数组的副本。修改副本不会影响原始数组。
// 函数修改一维数组副本
func modifyArray(arr [3]int) {
arr[0] = 100 // 修改的是传入的副本
}
// 函数修改二维数组副本
func modifyMatrix(mat [3][2]int) {
mat[2][0] = 100 // 修改的是传入的副本
}
func main() {
originalArr := [3]int{10, 20, 30}
modifyArray(originalArr)
fmt.Println("修改一维数组后:", originalArr) // 输出: 修改一维数组后: [10 20 30]
originalMat := [3][2]int{
{1, 1},
{1, 1},
{1, 1},
}
modifyMatrix(originalMat)
fmt.Println("修改二维数组后:", originalMat) // 输出: 修改二维数组后: [[1 1] [1 1] [1 1]]
}
数组支持 == 和 != 比较运算符,前提是数组的元素类型也支持这些运算符。由于数组内存总是被初始化,比较是有效的。
[n]*T 表示一个包含 n 个 T 类型指针的数组。*[n]T 表示一个指向包含 n 个 T 类型元素的数组的指针。