Go-数组原理

1.概述
数组是Go语言中的基本类型之一,通常可以用以下方式来表示一个数组。

Go语言的数组与Java一样,在初始化的时候就需要指定数组的大小,并且确认之后就无法修改。

编译期间通过NewArray函数初始化,两个参数elem和bound分别表示元素类型以及数组的大小。

2.初始化
Go语言有两种不同的初始化方式,分别是显式的指定数组大小,另外一种是[…]声明数组,

数组大小
显式指定在类型检查阶段数组大小就会被提取出来,然后通过newArray方法创建数组。而[…]方式编译器会在cmd/compile/internal/gc.typecheckcomplit函数中,通过遍历的方式对数组的大小进行推导。因此,这种方式会比显式指定要多一点工作量。

语句转换
对字面量的初始化编译器做了两种不同的优化

当元素个数小于等于4个,会直接将数组中的元素放在栈上。
当元素个数大于4个,会将元素放在静态区并在运行时取出。
假设代码需要初始化 [5]int{1, 2, 3, 4, 5},那么我们可以将上述过程理解成以下的伪代码:

至于编译器为什么要这么优化,等后面看了内存管理之后来填坑。

3.访问和赋值
无论在栈上还是在静态存储区,数组在内存中都是连续的内存空间。我们可以通过数组开头的指针,元素的数量,以及元素所占的空间大小来表示数组。

访问
数组越界是比较严重的错误,Go会在编译期间检查静态类型来判断数组越界,主要有3类错误

访问数组的索引是非整数时,报错 “non-integer array index %v”;
访问数组的索引是负数时,报错 “invalid array index %v (index must be non-negative)";
访问数组的索引越界时,报错 “invalid array index %v (out of bounds for %d-element array)";
对于简单的错误,比如直接使用整数类型或者常量访问数组,是能够直接检查出来的

整数类型访问,直接报错                                                                                                                              常量访问越界,也直接报错

而对于变量的访问数组或者字符串时,编译器就不能提前发现错误了。当在运行时发现错误程序就会崩溃退出。

对于无法判断数组下标是否越界的时候,编译器会在中间代码中插入IsInBounds,来检查是否越界,如果越界,则触发程序崩溃的PanicBounds指令。例如elem = arr[i],中间码则如下

将arr[i]改成arr[2]之后,则不需要IsInBounds来判断了,因为在编译器就能直接发现错误了。此时生成的中间码如下

赋值
赋值的过程:首先确认目标数组的地址,在通过PtrIndex获取目标元素的地址,最后使用Store指令将数据存入地址中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值