面试题答案
一键面试堆和栈在变量存储方面的不同
- 分配方式:
- 栈:栈上的变量分配和释放非常高效,遵循后进先出(LIFO)原则。当一个函数调用时,其局部变量在栈上被分配空间,函数返回时,这些变量所占用的栈空间被自动释放。
- 堆:堆上的内存分配相对复杂,需要通过垃圾回收(GC)机制来管理内存的释放。Go语言的垃圾回收器会定期扫描堆内存,回收不再被引用的对象所占用的空间。
- 内存管理:
- 栈:由编译器自动管理,不需要程序员手动干预内存的分配和释放,因此栈上变量的生命周期与函数调用紧密相关。
- 堆:由于垃圾回收机制的存在,堆上变量的生命周期由垃圾回收器决定,只要变量还被引用,垃圾回收器就不会回收其占用的内存。
变量存储位置示例
- 存储在堆上的变量:
- 一般来说,通过
new
关键字或者make
关键字创建的对象会存储在堆上。例如:
package main import "fmt" func main() { // 使用new创建一个指向int类型的指针,该指针指向的int值存储在堆上 var numPtr *int = new(int) *numPtr = 10 fmt.Println(*numPtr) // 使用make创建一个切片,切片底层的数据结构存储在堆上 slice := make([]int, 0, 10) slice = append(slice, 1, 2, 3) fmt.Println(slice) }
- 一般来说,通过
- 存储在栈上的变量:
- 函数内部的局部变量,如果其大小在编译时可以确定,并且没有被逃逸分析判定为需要在堆上分配,那么这些变量会存储在栈上。例如:
package main import "fmt" func add(a, b int) int { // 局部变量sum存储在栈上 sum := a + b return sum } func main() { result := add(3, 5) fmt.Println(result) }
在add
函数中,sum
变量是局部变量,其大小在编译时已知,并且没有逃逸出函数,因此存储在栈上。