GO 切片实力踩坑

概述GO 语言的切片这两天用了用, 可以支持切割数组的中间部分. 但今天使用中, 出了 bug, 查了半天, 发现是切片的问题, 简单写个 demo 复现当时的情况:
package mainimport "fmt"func main() { a := []int{1, 2, 3, 4, 5} b := a[2:4] b[0] = 9 fmt.Println(a)}你以为输出的是什么? 来, 看结果:
[1 2 9 4 5]
懵没懵?? 这是怎么回事呢?
【GO 切片实力踩坑】(我用个语言怎么老踩坑, 笨的一X)
解惑看这段 GO 代码的输出, 我们在修改b数组第一个元素值的时候, a数组的第三个元素修改了, 这两个有什么联系吗? 仔细看, b数组在切的时候, 切的不就是a数组第三第四的元素吗? 如此看来, b[0] 不正对应 a[2] 吗?
大胆假设: **GO 中对数组进行切割, 并不会切一个新的数组出来, 而是仍然使用原数组, 只是修改下数组的首地址和长度. **
验证:
package mainimport "fmt"func main() { a := []int{1, 2, 3, 4, 5} b := a[2:4] b[0] = 9 fmt.Printf("%pn", &a[2]) fmt.Printf("%pn", &b[0])}打印出来的地址完全一致, 印证了之前的猜想, 果然是一个数组. 同时修改a数组, 也会影响到b数组.
那可不可以对b数组越界访问, 访问a数组的值呢? 不行, GO 会对数组进行越界检查.
查看文档后发现, GO 切片的内部实现是这样的包含了三个字段. 其中各字段含义如下:

  1. 数组首地址指针: 指向底层数组的首地址(这个是真正的数组)
  2. 数组长度: 数组当前已经使用的长度
  3. 数组容量: 数组已分配内存的总长度, 比


      推荐阅读