gocookbook
gocookbook copied to clipboard
数组的上限推导和越界检查
什么是数组
数组是由相同类型元素的集合组成的数据结构,计算机会为数组分配一块连续的内存来保存其中的元素,我们可以利用数组中元素的索引快速访问特定元素。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
语言可以在编译期间的静态类型检查阶段判断简单的数组越界:
- 访问数组的索引是非整数时,报错 “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)";
数组和字符串的一些简单越界错误都会在编译期间发现,例如:直接使用整数或者常量访问数组;但是如果使用变量去访问数组或者字符串时,编译器就无法提前发现错误,需要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.panicIndex 和runtime.goPanicIndex 触发程序的运行时错误并导致崩溃退出。
所有内容摘录自:https://draveness.me/golang/docs/part2-foundation/ch03-datastructure/golang-array/