MST

星途 面试题库

面试题:Go中数组与切片在内存分配上的区别

请详细阐述Go语言中数组与切片在内存分配机制上有何不同,包括它们初始化时内存的占用方式以及后续元素增减时内存的变化情况。
38.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

数组内存分配机制

  1. 初始化时内存占用
    • Go语言中数组的长度是固定的,一旦声明,其长度就不可改变。当数组被初始化时,会在内存中分配一块连续的内存空间,用来存储数组的所有元素。例如,var arr [5]int声明了一个长度为5的整数数组,系统会一次性分配能够容纳5个int类型元素的连续内存空间。这个内存空间的大小是固定的,由数组的长度和元素类型共同决定。如果元素类型是int,在64位系统上每个int占8字节,那么这个数组将占用5 * 8 = 40字节的内存。
  2. 元素增减时内存变化:由于数组长度固定,不存在元素增减的情况。如果尝试访问超出数组长度的索引,会导致运行时错误(越界错误)。所以数组内存一旦分配,在其生命周期内不会因为所谓的“元素增减”而改变内存大小。

切片内存分配机制

  1. 初始化时内存占用
    • 切片是基于数组的动态数据结构,它本身是一个结构体,包含三个字段:指向底层数组的指针、切片的长度(len)和切片的容量(cap)。当通过make函数或字面量初始化切片时,会先分配一个底层数组,然后切片指向这个底层数组。例如,s := make([]int, 5, 10)会创建一个长度为5、容量为10的int类型切片。这里会先分配一个能够容纳10个int类型元素的底层数组(在64位系统上占用10 * 8 = 80字节内存),然后切片s指向这个底层数组的前5个元素,其长度为5,容量为10。如果使用字面量初始化,如ss := []int{1, 2, 3},会创建一个长度和容量都为3的切片,同时分配一个能容纳3个int元素的底层数组(占用3 * 8 = 24字节内存)。
  2. 元素增减时内存变化
    • 增加元素:当向切片中添加元素(使用append函数),如果当前切片的长度小于容量(len < cap),则直接在底层数组未使用的空间中添加新元素,不会重新分配内存。例如,上述容量为10长度为5的切片s,当添加元素时,只要总元素个数不超过10,就会在底层数组剩余空间添加。但是,当添加元素后导致切片长度超过容量(len > cap)时,Go语言会重新分配内存。通常会分配一个更大的底层数组,一般新容量是原容量的2倍(如果原容量小于1024),如果原容量大于等于1024,则新容量会增加原容量的1/4。然后将原切片的所有元素复制到新的底层数组中,再将新元素添加进去。
    • 减少元素:切片本身并没有直接减少元素后释放底层数组内存的机制。例如通过切片操作(如s = s[:3])缩短切片长度,底层数组依然存在,占用的内存并不会立即释放。只有当没有任何切片指向这个底层数组时,垃圾回收器才会回收该底层数组占用的内存。