Go语言中的数组

代码纪元 后端 2024-10-28

Go语言中的数组

基本概念

在 Go 语言中,数组(Array)是一种固定长度的、相同类型的元素序列。数组的长度在声明时就已经确定,并且不能改变。数组的每个元素可以通过索引访问,索引从 0 开始。

数组的声明和初始化:

在 Go 语言中,数组的声明和初始化有多种方式,以下是几种常见的方式:

1. 声明并初始化数组

方式一:使用 var 关键字声明并初始化csharp

代码解读
复制代码
var arr [5]int = [5]int{1, 2, 3, 4, 5}

方式二:使用短变量声明并初始化go

代码解读
复制代码
arr := [5]int{1, 2, 3, 4, 5}

2. 声明数组但不初始化csharp

代码解读
复制代码
var arr [5]int

这种方式声明的数组,所有元素会被初始化为该类型的零值(例如,int 类型的零值是 0)。

3. 使用省略号 ... 自动推断数组长度go

代码解读
复制代码
arr := [...]int{1, 2, 3, 4, 5}

这种方式会根据初始化列表中的元素个数自动推断数组的长度。

4. 部分初始化数组go

代码解读
复制代码
arr := [5]int{1, 2}

这种方式会初始化前两个元素为 12,其余元素会被初始化为零值。

5. 指定索引初始化数组css

代码解读
复制代码
arr := [5]int{0: 1, 4: 5}

这种方式会初始化索引为 0 的元素为 1,索引为 4 的元素为 5,其余元素会被初始化为零值。

6. 多维数组的声明和初始化less

代码解读
复制代码
var arr [2][3]int arr := [2][3]int{{1, 2, 3}, {4, 5, 6}}

多维数组的声明和初始化与一维数组类似,只是嵌套了更多的维度。

示例代码:go

代码解读
复制代码
package main import "fmt" func main() { // 方式一:使用 var 关键字声明并初始化 var arr1 [5]int = [5]int{1, 2, 3, 4, 5} fmt.Println(arr1) // 方式二:使用短变量声明并初始化 arr2 := [5]int{1, 2, 3, 4, 5} fmt.Println(arr2) // 方式三:声明数组但不初始化 var arr3 [5]int fmt.Println(arr3) // 方式四:使用省略号自动推断数组长度 arr4 := [...]int{1, 2, 3, 4, 5} fmt.Println(arr4) // 方式五:部分初始化数组 arr5 := [5]int{1, 2} fmt.Println(arr5) // 方式六:指定索引初始化数组 arr6 := [5]int{0: 1, 4: 5} fmt.Println(arr6) // 方式七:多维数组的声明和初始化 var arr7 [2][3]int arr8 := [2][3]int{{1, 2, 3}, {4, 5, 6}} fmt.Println(arr7) fmt.Println(arr8) }

数组的内存分析:

在 Go 语言中,数组的内存分配和布局相对简单且直观。数组是一个固定长度的、相同类型的元素序列,其内存布局是连续的。

1. 内存分配

当声明一个数组时,Go 语言会在内存中分配一块连续的内存区域,用于存储数组的元素。数组的长度在声明时就已经确定,并且不能改变。

例如,声明一个包含 5 个整数的数组:csharp

代码解读
复制代码
var arr [5]int

在这个例子中,Go 语言会在内存中分配一块连续的内存区域,大小为 5 * sizeof(int) 字节。假设 int 类型在当前平台上占用 4 个字节,那么这块内存区域的大小就是 5 * 4 = 20 字节。

2. 内存布局

数组的内存布局是线性的,即数组的每个元素在内存中是连续存储的。数组的第一个元素存储在内存的起始位置,第二个元素紧随其后,依此类推。

例如,对于数组 arr := [5]int{1, 2, 3, 4, 5},其内存布局如下:css

代码解读
复制代码
内存地址: | arr[0] | arr[1] | arr[2] | arr[3] | arr[4] | 值: | 1 | 2 | 3 | 4 | 5 |

每个元素的内存地址可以通过数组的基地址(即数组的第一个元素的地址)加上元素的索引和元素类型的大小来计算。

3. 访问数组元素

由于数组的内存布局是连续的,访问数组元素非常高效。通过索引访问数组元素时,Go 语言会直接计算出该元素的内存地址,并从该地址读取或写入数据。

例如,访问数组 arr 的第三个元素:go

代码解读
复制代码
value := arr[2]

Go 语言会计算出 arr[2] 的内存地址为 arr 的基地址加上 2 * sizeof(int) 字节,然后从该地址读取数据。

4. 数组的传递

在 Go 语言中,数组是值类型,这意味着当数组作为参数传递给函数时,会进行一次完整的复制。如果数组很大,这可能会导致性能问题。

例如:go

代码解读
复制代码
func modifyArray(arr [5]int) { arr[0] = 100 } func main() { arr := [5]int{1, 2, 3, 4, 5} modifyArray(arr) fmt.Println(arr) // 输出: [1 2 3 4 5] }

在这个例子中,modifyArray 函数接收的是 arr 的一个副本,因此修改副本不会影响原始数组。

数组的遍历:

在 Go 语言中,遍历数组有多种方式,常用的方法包括使用 for 循环和 range 关键字。以下是几种常见的遍历数组的方法:

1. 使用 for 循环和索引遍历数组

这是最基本的遍历方式,通过索引访问数组的每个元素。go

代码解读
复制代码
package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} for i := 0; i < len(arr); i++ { fmt.Println(arr[i]) } }

2. 使用 range 关键字遍历数组

range 关键字可以方便地遍历数组,它会返回索引和对应的元素值。go

代码解读
复制代码
package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} for index, value := range arr { fmt.Printf("Index: %d, Value: %d\n", index, value) } }

3. 只使用 range 遍历数组的值

如果你只关心数组的值而不关心索引,可以使用 _ 忽略索引。go

代码解读
复制代码
package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} for _, value := range arr { fmt.Println(value) } }

4. 只使用 range 遍历数组的索引

如果你只关心数组的索引而不关心值,可以只使用索引。go

代码解读
复制代码
package main import "fmt" func main() { arr := [5]int{1, 2, 3, 4, 5} for index := range arr { fmt.Println(index) } }

5. 使用 for 循环和 range 遍历多维数组

对于多维数组,可以嵌套使用 for 循环和 range 关键字。css

代码解读
复制代码
package main import "fmt" func main() { arr := [2][3]int{{1, 2, 3}, {4, 5, 6}} for i := 0; i < len(arr); i++ { for j := 0; j < len(arr[i]); j++ { fmt.Printf("arr[%d][%d] = %d\n", i, j, arr[i][j]) } } // 使用 range 遍历多维数组 for i, row := range arr { for j, value := range row { fmt.Printf("arr[%d][%d] = %d\n", i, j, value) } } }


转载来源:https://juejin.cn/post/7428200842228547625

Apipost 私有化火热进行中

评论