数组是咱们开发者常用的数据结构,本节将针对Golang源码介绍数组。首先在咱们定义数组时,数组类型、长度都已经肯定了。而底层计算机则是为数组分配一块连续的内存来保存数组元素。咱们能够快速的经过数组下标索引访问数组元素。一维数组以下图所示:数组
在Golang中,咱们定义数组:数据结构
var array [10]int
接下来,将结合源码介绍Golang数组。code
数组在建立时能够直接初始化blog
var array = [4]int{1,2,3,4} // 显式指定长度 var array = [...]int{1,2,3,4} // 须要在代码编译期间,由源代码肯定
这两种方式是最后的结果是相同的,第二种方式会由编译器编译代码时转换成上一种方式。
第一种方式会直接调用下列代码建立数组索引
// NewArray returns a new fixed-length array Type. 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 }
其中,Type表明数组元素类型,bound表明数组长度。而且数组的位置是在堆或者栈也肯定了。内存
而第二种方式则会调用下列代码进行建立element
// NewDDDArray returns a new [...]T array Type. func NewDDDArray(elem *Type) *Type { t := New(TARRAY) t.Extra = &Array{Elem: elem, Bound: -1} t.SetNotInHeap(elem.NotInHeap()) return t }
其中,-1只是一个占位符。具体数组长度是在类型检查阶段经过遍历数组元素进行肯定的。开发
数组是一段连续的内存空间,经过下标咱们就能够快速访问,若是访问越界,会报错。在Golang中,越界错误会在编译期间就会经过类型检查被发现。编译器
case OINDEX: case TSTRING, TARRAY, TSLICE: ... if n.Right.Type != nil && !n.Right.Type.IsInteger() { yyerror("non-integer %s index %v", why, n.Right) break } if !n.Bounded() && Isconst(n.Right, CTINT) { x := n.Right.Int64() if x < 0 { yyerror("invalid %s index %v (index must be non-negative)", why, n.Right) } else if t.IsArray() && x >= t.NumElem() { yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.NumElem()) ... }
若是访问越界就会直接报错。源码
这些错误在咱们开发过程当中使用常量访问数组就会直接报错。