gocookbook icon indicating copy to clipboard operation
gocookbook copied to clipboard

数组的上限推导和越界检查

Open kevinyan815 opened this issue 4 years ago • 0 comments

什么是数组

数组是由相同类型元素的集合组成的数据结构,计算机会为数组分配一块连续的内存来保存其中的元素,我们可以利用数组中元素的索引快速访问特定元素。Go语言中我们会使用如下所示的方式来表示数组类型:

[10]int
[200]interface{}

Go语言数组在初始化之后大小就无法改变,存储元素类型相同、但是大小不同的数组类型在Go语言看来也是完全不同的,只有两个条件都相同才是同一类型。

func NewArray(elem *Type, bound int64) *Type {
	if bound < 0 {
		Fatalf("NewArray: invalid bound %v", bound)
	}
	t := New(TARRAY)
	t.Extra = &Array{Elem: elem, Bound: bound}
	t.SetNotInHeap(elem.NotInHeap())
	return t
}

编译期间的数组类型Array是由上述的 NewArray 函数生成的,该类型包含两个字段,分别是元素类型Elem和数组的大小Bound,这两个字段共同构成了数组类型,而当前数组是否应该在堆栈中初始化也在编译期就确定了。

初始化

数组在Go语言里有两种不同的创建方式,一种是显式的指定数组大小,另一种是使用 [...]T 声明数组,Go语言会在编译期间通过源代码推导数组的大小:

arr1 := [3]int{1, 2, 3}
arr2 := [...]int{1, 2, 3}

上述两种声明方式在运行期间得到的结果是完全相同的,后一种声明方式在编译期间就会被转换成前一种,这也就是编译器对数组大小的推导。

访问越界

无论是在栈上还是静态存储区,数组在内存中都是一连串的内存空间,如果我们不知道数组中元素的数量,访问时可能发生越界;

数组访问越界是非常严重的错误,Go语言可以在编译期间的静态类型检查阶段判断简单的数组越界:

  1. 访问数组的索引是非整数时,报错 “non-integer array index %v”;
  2. 访问数组的索引是负数时,报错 “invalid array index %v (index must be non-negative)";
  3. 访问数组的索引越界时,报错 “invalid array index %v (out of bounds for %d-element array)";

数组和字符串的一些简单越界错误都会在编译期间发现,例如:直接使用整数或者常量访问数组;但是如果使用变量去访问数组或者字符串时,编译器就无法提前发现错误,需要Go语言运行时阻止不合法的访问,比如:

// 编译错误
arr[4]: invalid array index 4 (out of bounds for 3-element array)
// 运行时错误
arr[i]: panic: runtime error: index out of range [4] with length 3

Go语言运行时在发现数组、切片和字符串的越界操作会由运行时的runtime.panicIndexruntime.goPanicIndex 触发程序的运行时错误并导致崩溃退出。

所有内容摘录自:https://draveness.me/golang/docs/part2-foundation/ch03-datastructure/golang-array/

kevinyan815 avatar Dec 24 '20 11:12 kevinyan815