Go语言中的数组

简介: 在 Go 语言中,数组是一种固定长度的、相同类型元素的序列。数组声明时长度已确定,不可改变,支持多种初始化方式,如使用 `var` 关键字、短变量声明、省略号 `...` 推断长度等。数组内存布局连续,可通过索引高效访问。遍历数组常用 `for` 循环和 `range` 关键字。

基本概念

在 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

相关文章
|
7月前
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
7月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
1月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
1月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
2月前
|
JSON 前端开发 Go
Go语言实战:创建一个简单的 HTTP 服务器
本篇是《Go语言101实战》系列之一,讲解如何使用Go构建基础HTTP服务器。涵盖Go语言并发优势、HTTP服务搭建、路由处理、日志记录及测试方法,助你掌握高性能Web服务开发核心技能。
|
2月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
227 0
|
3月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
4月前
|
分布式计算 Go C++
初探Go语言RPC编程手法
总的来说,Go语言的RPC编程是一种强大的工具,让分布式计算变得简单如同本地计算。如果你还没有试过,不妨挑战一下这个新的编程领域,你可能会发现新的世界。
108 10
|
3月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
129 1
|
4月前
|
Go 索引
Go语言数组的定义与操作 - 《Go语言实战指南》
本文介绍了 Go 语言中的数组(Array)相关知识,包括定义、初始化方式(默认、显式、指定索引及自动推导长度)、访问与修改、遍历方法(for 循环和 for range)、值类型特性(复制行为)、多维数组支持以及其与切片的区别。数组是定长且同类型的集合,适合性能敏感场景,但实际开发中更常用动态的切片(slice)。
145 11