Go语言Slice的一道骚题
大家好我是一根甜苦瓜,今天我们来聊一道go语言中slice的面试题,加深一下对slice的理解
题目来自于雨痕大佬的《Go学习笔记》第四版,P43页
func TestDemo(t *testing.T) {slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}s1 := slice[2:5] s2 := s1[2:6:7] s2 = append(s2, 100)s2 = append(s2, 200)s1[2] = 20 t.Log(s1) t.Log(s2) t.Log(slice)
}
暂停5分钟,大家可以人脑编译一下,看看结果回事什么
时间到,公布答案
=== RUN TestDemouser_repo_test.go:21: [2 3 20]user_repo_test.go:22: [4 5 6 7 100 200]user_repo_test.go:23: [0 1 2 3 20 5 6 7 100 9]
--- PASS: TestDemo (0.00s)
PASS
是不是脑瓜子嗡嗡的呀?下面来图解这道题
先来看初始化 slice
和 s1
和 s2
这三行代码:
● 第 22
行将 slice
初始化为一个数组,元素是 0-9
这没有什么好说的。
● 第 23
行,是在 slice
的基础上创建的 s1
,选择下标范围 [2,5)
的元素来创建。左闭右开。容量为 3
,cap 为 8
● 第 24
行,s2
在 s1
的基础上创建,下标范围是 s1
的 [2,6)
,cap
容量到了 7
号下标,容量为 4
,cap
为 5
所以最终的三个对象的内存布局如下图:
接下来看代码s2 = append(s2, 100)
,由于 s2
的 cap
为 5
,此时尚有一个空间可以插入,所以直接 append
。但是由于共用了底层数组 s1
和 slice
,所以最终,他们三个变量都会被影响,最终结果如下:
接下来看代码s2 = append(s2, 200)
,此时 s2
的 len
和 cap
都为 5
,那么在s2
上继续添加元素显然不够用了,需要扩容,扩容是新开辟了空间,将老数据复制过去,所以s2
和老数组并无瓜葛了。这里是直接翻倍扩容(关于扩容大家可以去百度一下)。至此三个变量的内容如下。
最后再看这行代码 s1[2] = 20
这个就很简单了,此时 s1
还是和老数组有瓜葛的,所以一改全改但是不会影响到新开辟的 s2
。最终三个数组/切片的情况就是下面这个图。
这里需要注意的是,由于打印 S1
的时候并不会把 len
以外的数据打印出来,所以最终输出结果是: