第五章:Go语言值类型和引用类型

golang-gopher.png

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 表示避免程序内联

你可能感兴趣的:(第五章:Go语言值类型和引用类型)