MST

星途 面试题库

面试题:Go语言切片扩容机制对性能优化的影响

描述Go语言切片的扩容机制,并且分析在实际开发场景中,如何利用这一机制对切片相关操作进行性能优化。
32.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Go语言切片的扩容机制

  1. 初始创建:当创建一个切片时,例如 make([]int, 0, 10),这里容量(cap)被初始化为10。如果没有指定容量,会默认根据初始元素个数来分配容量。
  2. 扩容时机:当向切片中添加元素(如使用 append 函数),导致元素个数超过当前容量时,就会触发扩容。
  3. 扩容策略
    • 如果当前切片的容量小于1024,新的容量会翻倍。例如,原容量为5,添加元素触发扩容后,新容量变为10。
    • 如果当前切片的容量大于或等于1024,新的容量会增加当前容量的1/4。比如,原容量为1024,扩容后新容量为1024 + 1024/4 = 1280。
    • 扩容后会重新分配内存,将原切片的数据复制到新的内存地址。

性能优化方法

  1. 预分配容量:在实际开发中,如果能够预估切片最终的元素数量,在创建切片时就通过 make 函数指定合适的容量。例如,已知最终会有1000个元素,可以 make([]int, 0, 1000),这样可以避免多次扩容带来的内存重新分配和数据复制开销。
  2. 减少不必要的扩容:避免在循环中频繁添加单个元素导致多次扩容。可以先将元素收集到一个临时切片中,当临时切片满了再批量添加到目标切片。例如:
var targetSlice []int
tempSlice := make([]int, 0, 100)
for i := 0; i < 1000; i++ {
    tempSlice = append(tempSlice, i)
    if len(tempSlice) == cap(tempSlice) {
        targetSlice = append(targetSlice, tempSlice...)
        tempSlice = make([]int, 0, cap(tempSlice))
    }
}
if len(tempSlice) > 0 {
    targetSlice = append(targetSlice, tempSlice...)
}
  1. 复用切片:在函数调用等场景下,如果可能,尽量复用已有的切片,避免重新创建新切片带来的容量分配和数据复制。例如,函数接收一个切片参数,在函数内对切片进行操作,返回时尽量复用该切片而不是创建新的。
func processSlice(slice []int) []int {
    // 对切片进行操作
    return slice
}