MST
星途 面试题库

面试题:Go语言切片动态数组的内存分配机制

在Go语言中,切片是一种动态数组,阐述一下切片在进行append操作时,其底层内存是如何分配和扩容的?
17.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

切片 append 操作底层内存分配与扩容原理

  1. 初始分配
    • 当创建一个空切片时,例如 s := make([]int, 0),此时切片的容量(cap)为0 。如果执行 s = append(s, 1),Go 运行时会为切片分配内存。它会根据需要分配一个能容纳至少一个元素的内存块,这个内存块的大小通常会比当前所需的稍大,以减少后续频繁的内存分配。
  2. 扩容规则
    • 当切片的容量不足以容纳新添加的元素时,就会发生扩容。
    • 如果当前切片的容量小于1024 ,那么扩容时新的容量会翻倍。例如,一个切片当前容量为5 ,执行 append 操作导致容量不足,那么新的容量会变为10 。
    • 如果当前切片的容量大于或等于1024 ,那么扩容时新的容量会增加当前容量的1/4 。例如,一个切片当前容量为1024 ,执行 append 操作导致容量不足,那么新的容量会变为1024 + 1024/4 = 1280 。
  3. 内存重新分配
    • 扩容时,Go 运行时会在堆上重新分配一块更大的内存块,这块新内存块的大小由上述扩容规则决定。
    • 然后将原切片中的所有元素复制到新的内存块中,接着在新内存块的末尾添加新的元素。
    • 最后,更新切片的指针,使其指向新的内存块,同时更新切片的容量和长度。

例如:

package main

import "fmt"

func main() {
    s := make([]int, 0, 5)
    for i := 0; i < 10; i++ {
        s = append(s, i)
        fmt.Printf("Length: %d, Capacity: %d\n", len(s), cap(s))
    }
}

在上述代码中,初始切片 s 的容量为5 ,随着 append 操作的进行,容量会按照上述规则进行扩容,并输出每次 append 后的长度和容量。