概述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 切片的内部实现是这样的包含了三个字段. 其中各字段含义如下:
- 数组首地址指针: 指向底层数组的首地址(这个是真正的数组)
- 数组长度: 数组当前已经使用的长度
- 数组容量: 数组已分配内存的总长度, 比
推荐阅读
- 醋溜双色豆腐的做法
- 乳腺肿瘤手术冰冻切片诊断准确率高吗
- 如果你不懂得怎么购买地漏,就该好好学习了,不要等到踩坑就晚了
- 户外服装怎么选?了解这几样避免踩坑
- 同样是面粉,8607和1355区别很大!建议弄懂后再买不踩坑,涨知识
- 买瓷砖水太深!过来人总结5条经验,非常实用,学会了能少踩坑
- |“这就是没有实力,强出头的下场!”这也太现实了吧
- 中科大和国科大谁的实力更强?
- 翡翠|2021年翡翠踩坑经历分享
- 中铁局哪个局实力最大?