聊一聊堆、栈与Go语言的指针

堆、栈与指针

前言

堆、栈在计算机领域是亘古不变的热门话题,归根结底它们和编程语言无关,都是操作系统层面的内存划分,后面尝试简单地拆开这几个概念,谈谈我对它们的理解。

每个函数中每个值在栈中都是独占的,不能在其他栈中被访问。每个方法片(function frame)都有一个自己的独享栈,这个栈的生命周期随着方法开始结束诞生与消逝,在方法结束时候会被释放掉,较之于堆,栈的优势是比较轻量级,随用随弃,存活期跟随着函数。

通俗的讲,假如说栈是各个函数的一栋私人住宅,堆就是一个大型的人民广场,它可以被共享。堆作为一个全局访问块,它的空间由GC(拆迁大队)管理。

The heap is not self cleaning like stacks, so there is a bigger cost to using this memory. Primarily, the costs are associated with the garbage collector (GC), which must get involved to keep this area clean.

翻译过来,区别于栈在函数调用结束时候就释放掉,堆不会自动释放,堆空间的释放主要来自于垃圾回收操作。

GC(Garbage collection)

垃圾回收, 垃圾回收具有多种策略,一般来说,每一个存在于堆中,但不再被指针所引用的变量,都会被回收掉。“These allocations put pressure on the GC because every value on the heap that is no longer referenced by a pointer, needs to be removed.”由于垃圾回收涉及内存操作,往往需要考虑许多因素,所幸经过漫长演变,前人种树,有些编程语言垃圾回收策略已经足够强大(Java,Go),我们大部分时候不需要去干涉内存清理,把这部分工作交给底层调度器。

分配到堆内存有个弊端是它会为下一次GC增加压力,好处是可以被其他栈所共享,下列情景编译器会倾向于将它放在堆中存储:

  • 尝试申请一个较大的结构体/数组
  • 变量在一定的时间内还会被使用
  • 编译期间不能确认大小的变量申请

指针

指针,本质上和其他类型一样,只不过它的值是内存地址(引用),我的理解是内存块的门牌号。有句经常被提及的话:

什么时候该使用指针取决于什么时候要分享它。
Pointers serve one purpose, to share a value with a function so the function can read and write to that value even though the value does not exist directly inside its own frame.

指针是为了让变量在不同函数方法块(栈区间)之间分享,并且提供变量读写操作。


结合上述的理解,指针指的是内存地址,堆是共享模块,指针是为了共享同一块内存片。在Go语言中,所有传参都是值传递,指针也是通过传递指针的值。

程序实例 指针共享

主函数
func main() {
   
	var v int = 1
	fmt.Printf("# Main frame: Value of v:\t\t %v, address: %p\n", v, &v)
	PassValue(v, &v)
	fmt.Printf("# Main frame: Value of v:\t\t %v, address: %p\n", v, &v)
}
子函数
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值