MST

星途 面试题库

面试题:Go 中底层类型如何影响切片的 append 行为

在 Go 语言中,切片是基于底层数组实现的。请阐述底层数组类型如何影响 append 操作的具体行为,例如当底层数组容量不足时,append 是如何重新分配内存以及复制数据的,并且举例说明不同类型切片在 append 时的表现差异。
50.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 底层数组类型对append操作行为的影响
    • 容量不足时的内存重新分配
      • 当切片的底层数组容量不足以容纳新添加的元素时,Go语言会重新分配内存。具体来说,会分配一个新的更大的底层数组。新数组的大小通常是原数组容量的两倍(如果原容量小于1024),如果原容量大于或等于1024,则新容量会增加原容量的1/4。
      • 例如,假设有一个切片 s := make([]int, 0, 5),此时底层数组容量为5。当执行 s = append(s, 1, 2, 3, 4, 5, 6) 时,由于要添加6个元素,而原容量为5,容量不足。这时会重新分配内存,新的底层数组容量可能变为10(原容量5小于1024,变为原容量的2倍)。
    • 数据复制
      • 内存重新分配后,Go会将原底层数组中的数据复制到新的底层数组中,然后再将新添加的元素追加到新数组的末尾。接着,切片会指向这个新的底层数组。
      • 以上面的例子,先将原 s 中的数据复制到新的容量为10的底层数组,再把 6 追加到新数组末尾,s 此时指向新的底层数组。
  2. 不同类型切片在append时的表现差异举例
    • 整数类型切片
package main

import (
    "fmt"
)

func main() {
    intSlice := make([]int, 0, 5)
    intSlice = append(intSlice, 1, 2, 3, 4, 5, 6)
    fmt.Println(intSlice)
}

在这个例子中,intSliceint 类型的切片,一开始容量为5,添加6个元素导致容量不足,重新分配内存,最后输出 [1 2 3 4 5 6]

  • 结构体类型切片
package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    personSlice := make([]Person, 0, 2)
    p1 := Person{"Alice", 25}
    p2 := Person{"Bob", 30}
    p3 := Person{"Charlie", 35}
    personSlice = append(personSlice, p1, p2, p3)
    fmt.Println(personSlice)
}

这里 personSlicePerson 结构体类型的切片,初始容量为2,添加3个 Person 结构体实例导致容量不足,重新分配内存,最后输出 [{Alice 25} {Bob 30} {Charlie 35}]。其append行为和整数类型切片类似,都是在容量不足时重新分配内存并复制数据,只是复制的数据是结构体实例。