Go语言之数组

简介: 数组,是用来存储集合数据的。这种场景非常多,我们编码的过程中,都少不了要读取或者存储数据。当然除了数组之外,我们还有切片、Map映射等数据结构可以帮我们存储数据,但是数组是它们的基础。内部实现要想更清晰地了解数组,我们先得了解它的内部实现。

数组,是用来存储集合数据的。这种场景非常多,我们编码的过程中,都少不了要读取或者存储数据。当然除了数组之外,我们还有切片、Map映射等数据结构可以帮我们存储数据,但是数组是它们的基础。


内部实现


要想更清晰地了解数组,我们先得了解它的内部实现。数组是长度固定的数据类型,必须存储一段相同类型的元素,而且这些元素是连续的。我们这里强调固定长度,可以说这是和切片最明显的区别。


数组存储的类型可以是内置类型,比如整型或者字符串;也可以是自定义的数据结构。因为是连续的,所以索引比较好计算,所以我们可以很快地索引数组中的任何数据。


这里的索引,一直都是0、1、2、3这样的,因为其元素类型相同。我们也可以使用反射,获取类型占用大小,进行移位,获取相应的元素。这部分在说到反射的时候,我们再讲。


声明和初始化


数组的声明和初始化,和其他类型差不多。声明的原则是:


  1. 指明存储数据的类型。

  2. 存储元素的数量,也就是数组长度。


var array [5]int


以上我们声明了一个数组array,但是我们还没有对他进行初始化,这时候数组array里面的值,是对应元素类型的零值。也就是说,现在这个数组是 5 个 0 ,这和我们Java不一样,Java里是null。


数组一旦声明后,其元素类型和大小都不能变了,如果还需要存储更多的元素怎么办?那么只能通过创建一个新的数组,然后把原来数组的数据复制过去。


刚刚声明的数组已经被默认的元素类型零值初始化了,如果我们再次进行初始化怎么做呢,可以采用如下办法:


var array [5]int
array = [5]int{1,2,3,4,5}


这两步比较繁琐,Go为我们提供了:=操作符,可以让我们在创建数组的时候直接初始化。


array:=[5]int{1,2,3,4,5}


这种简短变量声明的方式不仅适用于数组,还适用于任何数据类型,这也是Go语言中常用的方式。


有时候我们更懒,连数组的长度都不想指定。不过没有关系,使用…代替就好了,Go会自动推导出数组的长度。


array:=[...]int{1,2,3,4,5}


假如我们只想给索引为 1 和 3 的数组初始化相应的值,其他都为 0 怎么做呢,直接的办法有:


array:=[5]int{0,1,0,4,0}


还有一种更好的办法,上面讲默认初始化为零值,那么我们就可以利用这个特性,只初始化索引 1 和 3 的值:


array:=[5]int{1:1,3:4}


使用数组


数组的访问非常简单,通过索引即可,操作符为[]。因为内存是连续的,所以索引访问的效率非常高。


array:=[5]int{1:1,3:4}
fmt.Printf("%d",array[1])


修改数组中的一个元素也很简单:


array:=[5]int{1:1,3:4}
fmt.Printf("%d\n",array[1])
array[1] = 3
fmt.Printf("%d\n",array[1])


如果我们要循环打印数组中的所有值,一个传统的就是常用的for循环:


func main() {
    array := [5]int{1: 1, 3: 4}

    for i := 0; i < 5; i++ {
        fmt.Printf("索引:%d,值:%d\n", i, array[i])
    }
}


不过大部分时候,我们都是使用for rang循环:


func main() {
    array := [5]int{1: 1, 3: 4}

    for i, v := range array {
        fmt.Printf("索引:%d,值:%d\n", i, v)
    }
}


这两段示例代码,输出的结果是一样的。


同样类型的数组是可以相互赋值的,不同类型的不行,会编译错误。那么什么是同样类型的数组呢?Go语言规定,必须是长度一样,并且每个元素的类型也一样的数组,才是同样类型的数组。


array := [5]int{1: 1, 3: 4}
var array1 [5]int = array //success
var array2 [4]int = array1 //error


指针数组和数组本身差不多,只不过元素类型是指针。


array := [5]*int{1: new(int), 3:new(int)}


这样就创建了一个指针数组,并且为索引 1 和 3 都创建了内存空间,其他索引是指针的零值nil,这时候我们要修改指针变量的值也很简单,如下即可:


array := [5]*int{1: new(int), 3:new(int)}
*array[1] = 1


以上需要注意的是,只可以给索引 1 和 3 赋值,因为只有它们分配了内存,才可以赋值。如果我们给索引 0 赋值,运行的时候,会提示无效内存或者是一个nil指针引用。


panic: runtime error: invalid memory address or nil pointer dereference


要解决这个问题,我们要先给索引 0 分配内存,然后再进行赋值修改。


array := [5]*int{1: new(int), 3:new(int)}
array[0] =new(int)
*array[0] = 2
fmt.Println(*array[0])


函数间传递数组


在函数间传递变量时,总是以值的方式。如果变量是个数组,那么就会整个复制,并传递给函数。如果数组非常大,比如长度 100 多万,那么这对内存是一个很大的开销。


func main() {
    array := [5]int{1: 2, 3:4}
    modify(array)
    fmt.Println(array)
}

func modify(a [5]int){
    a[1] =3
    fmt.Println(a)
}


通过上面的例子,可以看到,数组是复制的,原来的数组没有修改。我们这里是 5 个长度的数组还好,如果有几百万怎么办,有一种办法是传递数组的指针,这样,复制的大小只是一个数组类型的指针大小。


func main() {
    array := [5]int{1: 2, 3:4}
    modify(&array)
    fmt.Println(array)
}

func modify(a *[5]int){
    a[1] =3
    fmt.Println(*a)
}


这是传递数组的指针的例子,会发现数组被修改了。所以这种情况虽然节省了复制的内存,但是要谨慎使用,因为一不小心,就会修改原数组,导致不必要的问题。


这里注意,数组的指针和指针数组是两个概念,数组的指针是*[5]int指针数组是[5]*int,注意*的位置。


针对函数间传递数组的问题,比如复制问题,比如大小僵化问题,都有更好的解决办法,这个就是切片,它更灵活


目录
相关文章
|
10天前
|
数据采集 人工智能 安全
|
6天前
|
机器学习/深度学习 人工智能 前端开发
构建AI智能体:七十、小树成林,聚沙成塔:随机森林与大模型的协同进化
随机森林是一种基于决策树的集成学习算法,通过构建多棵决策树并结合它们的预测结果来提高准确性和稳定性。其核心思想包括两个随机性:Bootstrap采样(每棵树使用不同的训练子集)和特征随机选择(每棵树分裂时只考虑部分特征)。这种方法能有效处理大规模高维数据,避免过拟合,并评估特征重要性。随机森林的超参数如树的数量、最大深度等可通过网格搜索优化。该算法兼具强大预测能力和工程化优势,是机器学习中的常用基础模型。
321 164
|
5天前
|
机器学习/深度学习 自然语言处理 机器人
阿里云百炼大模型赋能|打造企业级电话智能体与智能呼叫中心完整方案
畅信达基于阿里云百炼大模型推出MVB2000V5智能呼叫中心方案,融合LLM与MRCP+WebSocket技术,实现语音识别率超95%、低延迟交互。通过电话智能体与座席助手协同,自动化处理80%咨询,降本增效显著,适配金融、电商、医疗等多行业场景。
324 155
|
6天前
|
编解码 人工智能 自然语言处理
⚽阿里云百炼通义万相 2.6 视频生成玩法手册
通义万相Wan 2.6是全球首个支持角色扮演的AI视频生成模型,可基于参考视频形象与音色生成多角色合拍、多镜头叙事的15秒长视频,实现声画同步、智能分镜,适用于影视创作、营销展示等场景。
383 4
|
13天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
920 7