MST

星途 面试题库

面试题:Go语言切片共享底层数组对内存布局的影响

假设有两个切片s1和s2共享同一个底层数组,对s1进行操作(如删除元素、添加元素)后,会如何影响s2的内存布局和实际可用元素?请从底层内存角度详细分析。
22.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 删除元素场景
    • 底层内存角度
      • Go语言中切片删除元素通常使用append函数来模拟删除操作。例如,若要删除切片s1中的第i个元素,可以使用s1 = append(s1[:i], s1[i + 1:]...)
      • 由于s1s2共享底层数组,当对s1进行删除操作时,实际上是改变了s1在底层数组中的起始位置和长度。假设底层数组为arr,原本s1arr[j]开始,长度为n,删除元素后,s1可能从arr[k]开始(k可能等于j或者不等于j,取决于删除的位置),长度变为mm < n)。
    • 对s2的影响
      • 内存布局:如果删除操作没有导致底层数组扩容或重新分配内存(即删除后len(s1) + cap(s1) - 1仍小于等于底层数组容量),那么s2的内存布局不会改变,因为底层数组没有改变。但是如果删除操作导致了底层数组重新分配内存(例如删除大量元素后,剩余元素很少,触发了内存优化机制重新分配一个更小的底层数组),那么s2指向的底层数组就会改变,其内存布局也会相应改变。
      • 实际可用元素:如果没有重新分配底层数组,s2的实际可用元素数量不变,只是s1删除元素对应的位置对于s2来说可能处于“无效”状态(因为s1删除元素改变了其逻辑上的长度)。如果底层数组重新分配,s2的实际可用元素可能会因为新的底层数组大小和内容改变而改变。
  2. 添加元素场景
    • 底层内存角度
      • 使用append函数向s1添加元素时,如果当前s1的容量(cap(s1))足够,那么直接在底层数组的空闲位置添加元素,s1的长度(len(s1))增加,起始位置不变。如果当前容量不足,Go会重新分配一个新的底层数组,新数组的大小通常是原数组容量的两倍(如果原容量小于1024),然后将原数组内容复制到新数组,再在新数组的空闲位置添加元素。
    • 对s2的影响
      • 内存布局:如果添加元素没有导致底层数组扩容,s2的内存布局不变,因为底层数组未变。但如果导致了底层数组扩容并重新分配内存,s2指向的底层数组会改变,内存布局也会改变。
      • 实际可用元素:若未扩容,s2实际可用元素不变。若扩容,s2的实际可用元素可能会因为新的底层数组大小和内容改变而改变,例如新的底层数组可能在原数组基础上增加了新元素,这些新元素对于s2来说也可能是可用的(取决于s2的起始位置和长度)。