Go语言数据的使用可以分为
值类型
和引用类型
值类型包括 : 所有
整型
,所有浮点型
,bool型
,string型
,数组
和struct类型
值类型的特点是变量直接存储值,内存通常在 栈(stack) 中分配
引用类型包括:
指针
,slice
,map
,chan
,interface
引用类型的特点,变量存储的是一个地址,这个地址对应的空间才真正存储的数据,内存分配通常在 堆(heap) 上分配,当没有任何变量引用这个地址的时候,该地址对应的数据空间会被GC回收
栈(stack) : 栈是一种拥有特殊规则的线性表数据结构,只允许线性表的一端放入数据,之后再这一端取出数据,按照后进先出(lifo)的顺序.
- 往找中放入元素的过程叫做入钱。入校会增加枝的元素数量,最后放入的元素总是位
于枝的顶部,最先放入的元素总是位于拢的底部。
从校中取出元素时,只能从枝顶部取出 。 取出元素后,拢的数量会变少 。最先放入的
元素总是最后被取出,最后放入的元素总是最先被取出。不允许从枝底获取数据,也不允
许对找成员(除战顶外的成员)进行任何查看和修改操作 。*堆(heap) : 堆也是一种数据结构
- 堆在内存分配中类似于往一个房间里摆放各种家具,家具的尺寸有大有小。分配内存
时,需要找一块足够装下家具的空间再摆放家具。经过反复摆放和腾空家具后,房间里的
空间会变得乱七八糟,此时再往空间里摆放家具会存在虽然有足够的空间,但各空间分布
在不同的区域,无法有一段连续的空间来摆放家具的问题。此时 ,内存分配器就需要对这
些空间进行调整优化
堆分配内存和技分配内存相比,堆适合不可预知大小的内存分配 。 但是为此付出的代
价是分配速度较慢 ,而且会形成 内 存碎片
问题来了,堆栈各有优点,在编译的时候该如何进行内存分配呢?
Go语言将内存如何分配整合到编译器中了,Go语言这个内存分配 过程称之为 变量逃逸分析 编译器在分析代码特征和生命周期,决定使堆还是栈进行内存分配,开发者自己不需要纠结这个问题
package main
import "fmt"
func demo(n int) int {
var c int
c = n
return c
}
func void() {
}
func main(){
var i int
void()
fmt.Println(i,demo(9))
}
$ go run -gcflags "-m -l" main.go
# command-line-arguments
.\main.go:17:13: i escapes to heap
.\main.go:17:20: demo(9) escapes to heap
.\main.go:17:13: main ... argument does not escape
0 9
解释 :
-gcflags
编译参数
"-m -l"
-m
表示进行内存分配分析-l
表示避免程序内联