关于 Slice 扩展的进一步思考

来源:3-3 切片的操作

ZYCGary

2023-08-01

在 Slice 的多次扩展中(s3,s4,s5),在超出 capacity 时在底层会创建一个更长的 array,那么这个创建新 array 的动作是在每次超出时都执行,还是只执行一次?超出 capacity 创建的 slice 是新的 array 的 view, 还是原始 array 的 view?
我测试了一下代码:

arr := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
s1 := arr[2:6]
s2 := s1[3:5]

s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)

fmt.Println("s3, s4, s5 = ", s3, s4, s5)
fmt.Println("arr = ", arr)

结果是:

s3, s4, s5 =  [6 7 10] [6 7 10 11] [6 7 10 11 12]
arr4 =  [1 2 3 4 5 6 7 10]

在这段代码中,底层是创建了 1 个更长的 array 还是 2 个?s3,s4,s5 分别是哪个 array 的 view 呢?

写回答

1回答

weixin_慕莱坞8275679

2023-08-31

  1. s1 := arr[2:6],s1截取的是原始arr,s1=[3,4,5,6]

  2. s2 := s1[3:5]:s2截取s1,s1长度不足,最后一位扩展到底层arr的6下标处  s2=[6,7],此时,len(s2)=2, cap(s2)=3 (只剩底层的6,7,8了,前面的1,2,3,4,5已经被舍弃了,Slice只能向后扩展)s2=[6,7]

  3. s3 := append(s2, 10):s2对应的是原始数组中的6,7,原始arr长度还足够,因此原始数组的最后一位直接改为10,此次没有创建新的arr; s3=[6,7,10]

  4. s4 := append(s3, 11):s3对应原始数组的6,7,10,此时cap=3,继续追加,原始数组长度不足,此时创建一个新的数组,cap的扩容规则是2倍,因此对应的cap=6,将s3 copy进去,再追加一个11 s4=[6,7,10,11],此时len(s4)=4, cap=6

  5. s5 := append(s4, 12):再次追加,上一步创建的cap=6,长度足够,直接追加一位,s5=[6,7,10,11,12],此时len(s5)=5, cap=6

所以,只有s4 := append(s3, 11)创建了更长的arr


0
0

Google资深工程师深度讲解Go语言 由浅入深掌握Go语言

语法+分布式爬虫实战 为转型工程师量身打造

5995 学习 · 1909 问题

查看课程