golang:数组array底层

数组 array

  • 是相同类型元素组成的集合

  • 初始化后大小无法改变

  • 对于数组类型 必须满足 存储元素类型相同 且 大小相同 才被认为同一类型元素

  • 结构 /go1.15/src/cmd/compile/internal/types/type.go

    // Array contains Type fields specific to array types.
    type Array struct {
      Elem  *Type // element type
      Bound int64 // number of elements; <0 if unknown yet
    }
    
  • 上限推导

    arr1 := [3]int{1,2,3}
    arr2 := [...]int{1,2,3}
    
    • 对于未给定数目的数组,调用 go1.15/src/cmd/compile/internal/gc/typecheck.go typecheckarraylit() 通过 遍历 方式计算数量
      • [...] 初始化方式只是一种语法糖,两种方式完全等价
  • 语句转换

    • 优化: go1.15/src/cmd/compile/internal/gc/sinit.go anylit() -> fixedlit()

    • 当元素 小于等于 4 个,会直接将数组的元素放置在栈上 initKindDynamic

      var arr [3]int
      arr[0] = 1
      arr[1] = 2
      arr[3] = 3
      
    • 当元素 大于 4 个,会将数组元素放到静态区并在运行时取出 initKindStatic

      var arr [5]int
      //调用 staticname() 获取唯一的staticname statictmp_0
      statictmp_0[0] = 1
      statictmp_0[1] = 2
      statictmp_0[2] = 3
      statictmp_0[3] = 4
      statictmp_0[4] = 5
      arr = statictmp_0
      
    • 优化理解:

      • 静态存储区是编译就分配好的空间,在数组数量多的情况下,提前放在静态区减少数组初始化时间,提高性能。
  • 访问和赋值

    • 编译期间的SSA /go1.15/src/cmd/compile/internal/gc/typecheck.go typecheck1()
      • 检查访问数组索引 是否非法 非整数 || 负数 || 越界 -> 只针对字面量可以判断是否合法
    • 运行时检查 panicIndex -> goPanicIndex
      • 当编译时无法判断是否越界时,SSA生成 IsInBounds 越界检查指令,若越界,触发 PanicBounds 指令执行 runtime.panicIndex
      • 判断后 分别走访问 和 赋值指令
    • 理解:
      • 字面量访问下标:无论是数组的寻址还是赋值,都是在编译阶段完成的,没有运行时的参与
      • 无法判断数组下标时:会加入 PanicBounds 指令交给运行时进行判断
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容