为什么Go结构体不同初始化方式的内存大小不一样?

606 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

前言

今天发现一个有意思的事情,Go语言中同一结构体不同的初始化方式得到的对象占用内存大小居然不一样,why?今天来分享一下 struct不同方式的初始化,内存有什么不同。感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

初始化方式

struct初始化有三种方式,分别是var声明、new声明和直接初始化。首先我们先定义一个结构体:

type Test struct {
	a int8 // 1
	b int32 // 4
	c int64 // 8
}

通过 var 声明

使用 var,和声明普通变量的方式一致即可完成结构体的实例化,基本实例化格式如下:

var t Test
fmt.Println(t, unsafe.Sizeof(t)) //{0 0 0} 16

使用 new 声明

使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针:var t *T = new(T)

t2 := new(Test)
fmt.Println(t2, unsafe.Sizeof(t2)) // &{0 0 0} 8

直接初始化

使用结构体零值初始化结构体值对象,基本实例化格式如下:

t3 := Test{} //分配内存,并初始化
fmt.Println(t3, unsafe.Sizeof(t3)) //{0 0 0} 16

几种初始化方式之间的区别

通过上文我们已经了解了三种初始化结构体的方式,分别为:

  1. 使用 var t T ,会给 t 分配内存,并零值化内存,但是这个时候的 t 的类型是 T;
  2. 使用 new 关键字 t := new(T),变量 t 则是一个指向 T 的指针;
  3. 直接初始化,会给 t 分配内存,并零值化内存, t 的类型是 T;

通过输出我们可以看到三种方式返回的类型和占用的内存大小不一致,为什么值不同呢?我们通过其内存布局来看一下这三种方式的区别。

var声明

使用var声明时,会直接在内存中开辟一块空间,来存储结构体的零值,大致的内存布局结构如下:

new初始化

使用new初始化时,会返回该结构体的指针,该指针指向的是结构体的零值,如果初始化了值,对应字段的值会进行初始化。

直接初始化

直接初始化,其实和var声明是一样的内存结构体,无非就是在初始化时,字段进行了初始化。

小结

通过本文,我们知道了Go 语言中struct初始化有三种方式,分别是var声明、new声明和直接初始化。

通过 var t T声明会给t分配内存,并零值化内存,t 返回类型是 T;使用 new 关键字 t := new(T),变量 t 则是一个指向 T 的指针;直接初始化,会给 t 分配内存,并零值化内存, t 的类型是 T。