面试题答案
一键面试- 内存层面关系:
- 在Go语言中,切片是一种引用类型。当将切片作为参数传递给函数时,传递的是切片的一个副本,这个副本包含指向底层数组的指针、切片的长度和容量。
- 原始切片和函数参数切片共享底层数组。
- 可能出现的现象:
- 现象一:原始切片和函数参数切片同步变化
- 当函数内追加元素后,若未超过原切片的容量,原始切片和函数参数切片都会反映出追加后的变化。因为它们共享底层数组,追加元素只是在底层数组上进行操作。
- 例如:
- 现象一:原始切片和函数参数切片同步变化
package main
import "fmt"
func appendElement(s []int) {
s = append(s, 10)
}
func main() {
original := []int{1, 2, 3}
appendElement(original)
fmt.Println(original)
}
- 在上述代码中,`original`切片作为参数传递给`appendElement`函数,函数内追加元素`10`后,由于未超过原切片容量,`original`切片也会包含`10`,输出`[1 2 3 10]`。
- 现象二:原始切片和函数参数切片不同步变化
- 当函数内追加元素后,超过了原切片的容量,Go语言会重新分配内存,创建一个新的底层数组。此时,函数参数切片操作的是新的底层数组,而原始切片仍指向旧的底层数组,两者不再同步。
- 例如:
package main
import "fmt"
func appendElement(s []int) {
for i := 0; i < 10; i++ {
s = append(s, i)
}
}
func main() {
original := make([]int, 0, 5)
appendElement(original)
fmt.Println(original)
}
- 在这段代码中,`original`切片初始容量为5,`appendElement`函数中追加了10个元素,超过了原容量。此时,函数内的`append`操作会重新分配内存创建新的底层数组,`original`切片不受影响,输出`[]`。
3. 原因:
- Go语言切片的这种行为源于其设计理念,为了在传递切片时减少内存开销,采用了引用类型传递方式(传递切片头信息副本)。当容量不足时重新分配内存创建新底层数组,是为了保证切片的动态扩展性,避免频繁的内存重分配对性能的影响。