栈(stack)是系统自动分配空间,定义一个char a,系统会自动在栈上为其开辟空间
堆(heap)则是程序员根据需要自己申请的空间,如malloc(10), 开辟十个字节的空间
内存分配图
虚拟内存,栈区,堆区,全局区,代码区
栈在内存中是从高地址向下分配的,并且连续的,遵循先进后出原则,系统在分配的时候已经确定好了
栈的大小空间。
栈上面的空间是自动回收的,所以栈上面的数据生命周期在函数结束后就被释放掉了。
堆分配是从低地址向高地址分配的,每次分配的内存大小可能不一致,导致了空间是不连续的,
这也是产生内存碎片的原因,由于是程序分配,所以效率相对慢些。
而且堆上的数据只要程序不释放空间,就一直可以访问到,不过一旦忘记释放就会造成内存泄漏了。
由于堆是非连续空间分配,内存分配速度要更慢一点。所以使用逃逸分析可以尽量把变量内存分配到栈上。
由于golang只对堆进行gc, 通过逃逸分析,编译器自动分配内存,将那些不需要分配到堆上的内存分配
到栈上,堆上的变量少了不但同时减少GC的压力,还减轻了内存分配的开销。
- make 和new 函数的变量内存分配
go语言中的值类型有:整型、浮点,字符串,数组,bool,struct,声明的变量直接存储值, 分配栈区
的内存空间,在函数调用完毕后自动释放。(函数类型属于值类型)
go语言的引用类型有:channel,map,slice,指针,这些类型的变量存储的是一个地址(可理解为指针),指针指向内存中真正存储数据的首地址,分配堆上的内存空间,通过gc回收。‘
每一个进程都存在独立的堆区和栈区