go语言内存使用 golang内存管理( 二 )


另外要注意,不同硬件平台占用的大小和对齐值都可能是不一样的 。因此本文的值不是唯一的,调试的时候需按本机的实际情况考虑
输出结果:
在 Go 中可以调用unsafe.Alignof来返回相应类型的对齐系数 。通过观察输出结果,可得知基本都是2^n ,最大也不会超过 8 。这是因为我手提(64 位)编译器默认对齐系数是 8 , 因此最大值不会超过这个数
在上小节中,提到了结构体中的成员变量要做字节对齐 。那么想当然身为最终结果的结构体,也是需要做字节对齐的
接下来我们一起分析一下 , “它” 到底经历了些什么,影响了 “预期” 结果
在每个成员变量进行对齐后,根据规则 2,整个结构体本身也要进行字节对齐 , 因为可发现它可能并不是2^n,不是偶数倍 。显然不符合对齐的规则
根据规则 2,可得出对齐值为 8 。现在的偏移量为 25 , 不是 8 的整倍数 。因此确定偏移量为 32 。对结构体进行对齐
Part1 内存布局:axxx|bbbb|cxxx|xxxx|dddd|dddd|exxx|xxxx
通过本节的分析,可得知先前的 “推算” 为什么错误?
是因为实际内存管理并非 “一个萝卜一个坑” 的思想 。而是一块一块 。通过空间换时间(效率)的思想来完成这块读取、写入 。另外也需要兼顾不同平台的内存操作情况
在上一小节,可得知根据成员变量的类型不同,其结构体的内存会产生对齐等动作 。那假设字段顺序不同,会不会有什么变化呢?我们一起来试试吧 :-)
输出结果:
通过结果可以惊喜的发现,只是 “简单” 对成员变量的字段顺序进行改变 , 就改变了结构体占用大小
接下来我们一起剖析一下Part2  , 看看它的内部到底和上一位之间有什么区别,才导致了这样的结果?
符合规则 2 , 不需要额外对齐
Part2 内存布局:ecax|bbbb|dddd|dddd
通过对比Part1和Part2的内存布局,你会发现两者有很大的不同 。如下:
仔细一看,Part1存在许多 Padding 。显然它占据了不少空间,那么 Padding 是怎么出现的呢?
通过本文的介绍,可得知是由于不同类型导致需要进行字节对齐,以此保证内存的访问边界
那么也不难理解,为什么 调整结构体内成员变量的字段顺序 就能达到缩小结构体占用大小的疑问了 , 是因为巧妙地减少了 Padding 的存在 。让它们更 “紧凑” 了 。这一点对于加深 Go 的内存布局印象和大对象的优化非常有帮
GO语言学习系列八——GO函数(func)的声明与使用 GO是编译性语言,所以函数的顺序是无关紧要的,为了方便阅读,建议入口函数 main 写在最前面,其余函数按照功能需要进行排列
GO的函数 不支持嵌套 , 重载和默认参数
GO的函数 支持 无需声明变量,可变长度,多返回值,匿名,闭包等
GO的函数用 func 来声明,且左大括号 { 不能另起一行
一个简单的示例:
输出为:
参数:可以传0个或多个值来供自己用
返回:通过用 return来进行返回
输出为:
上面就是一个典型的多参数传递与多返回值
对例子的说明:
按值传递:是对某个变量进行复制,不能更改原变量的值
引用传递:相当于按指针传递,可以同时改变原来的值,并且消耗的内存会更少,只有4或8个字节的消耗
在上例中,返回值 (d int, e int, f int) { 是进行了命名,如果不想命名可以写成 (int,int,int){ ,返回的结果都是一样的,但要注意:
当返回了多个值,我们某些变量不想要 , 或实际用不到,我们可以使用 _ 来补位,例如上例的返回我们可以写成 d,_,f := test(a,b,c),我们不想要中间的返回值,可以以这种形式来舍弃掉

推荐阅读