如何得到一個(gè)對(duì)象所占內(nèi)存大?。?/h2>
fmt.Println(unsafe.Sizeof(int64(0))) // "8"
type SizeOfA struct {
A int
}
unsafe.Sizeof(SizeOfA{0}) // 8
type SizeOfC struct {
A byte // 1字節(jié)
C int32 // 4字節(jié)
}
unsafe.Sizeof(SizeOfC{0, 0}) // 8
unsafe.Alignof(SizeOfC{0, 0}) // 4
結(jié)構(gòu)體中A byte占1字節(jié),C int32占4字節(jié). SizeOfC占8字節(jié)
內(nèi)存對(duì)齊:
為何會(huì)有內(nèi)存對(duì)齊?1.并不是所有硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)。2.性能原因 訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要做兩次內(nèi)存訪問(wèn),而對(duì)齊的內(nèi)存只需訪問(wèn)一次。
上面代碼SizeOfC中元素一共5個(gè)字節(jié),而實(shí)際結(jié)構(gòu)體占8字節(jié)
是因?yàn)檫@個(gè)結(jié)構(gòu)體的對(duì)齊倍數(shù)Alignof(SizeOfC) = 4.也就是說(shuō),結(jié)構(gòu)體占的實(shí)際大小必須是4的倍數(shù),也就是8字節(jié)。
type SizeOfD struct {
A byte
B [5]int32
}
unsafe.Sizeof(SizeOfD{}) // 24
unsafe.Alignof(SizeOfD{}) // 4
Alignof返回的對(duì)齊數(shù)是結(jié)構(gòu)體中最大元素所占的內(nèi)存數(shù),不超過(guò)8,如果元素是數(shù)組那么取數(shù)組類(lèi)型所占的內(nèi)存值而不是整個(gè)數(shù)組的值
type SizeOfE struct {
A byte // 1
B int64 // 8
C byte // 1
}
unsafe.Sizeof(SizeOfE{}) // 24
unsafe.Alignof(SizeOfE{}) // 8
SizeOfE中,元素的大小分別為1,8,1,但是實(shí)際結(jié)構(gòu)體占24字節(jié),遠(yuǎn)超元素實(shí)際大小,因?yàn)閮?nèi)存對(duì)齊原因,最開(kāi)始分配的8字節(jié)中包含了1字節(jié)的A,剩余的7字節(jié)不足以放下B,又為B分配了8字節(jié),剩余的C獨(dú)占再分配的8字節(jié)。
type SizeOfE struct {
A byte // 1
C byte // 1
B int64 // 8
}
unsafe.Sizeof(SizeOfE{}) // 16
unsafe.Alignof(SizeOfE{}) // 8
換一種寫(xiě)法,把A,C放到上面,B放到下面。這時(shí)SizeOfE占用的內(nèi)存變?yōu)榱?6字節(jié)。因?yàn)槭紫确峙涞?字節(jié)足以放下A和C,省去了8字節(jié)的空間。
上面一個(gè)結(jié)構(gòu)體中元素的不同順序足以導(dǎo)致內(nèi)存分配的巨大差異。前一種寫(xiě)法產(chǎn)生了很多的內(nèi)存空洞,導(dǎo)致結(jié)構(gòu)體不夠緊湊,造成內(nèi)存浪費(fèi)。
下面我們來(lái)看一下結(jié)構(gòu)體中元素的內(nèi)存布局:
fmt.Println(unsafe.Sizeof(int64(0))) // "8"
type SizeOfA struct {
A int
}
unsafe.Sizeof(SizeOfA{0}) // 8
type SizeOfC struct {
A byte // 1字節(jié)
C int32 // 4字節(jié)
}
unsafe.Sizeof(SizeOfC{0, 0}) // 8
unsafe.Alignof(SizeOfC{0, 0}) // 4
結(jié)構(gòu)體中A byte占1字節(jié),C int32占4字節(jié). SizeOfC占8字節(jié)
為何會(huì)有內(nèi)存對(duì)齊?1.并不是所有硬件平臺(tái)都能訪問(wèn)任意地址上的任意數(shù)據(jù)。2.性能原因 訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要做兩次內(nèi)存訪問(wèn),而對(duì)齊的內(nèi)存只需訪問(wèn)一次。
上面代碼SizeOfC中元素一共5個(gè)字節(jié),而實(shí)際結(jié)構(gòu)體占8字節(jié)
是因?yàn)檫@個(gè)結(jié)構(gòu)體的對(duì)齊倍數(shù)Alignof(SizeOfC) = 4.也就是說(shuō),結(jié)構(gòu)體占的實(shí)際大小必須是4的倍數(shù),也就是8字節(jié)。
type SizeOfD struct {
A byte
B [5]int32
}
unsafe.Sizeof(SizeOfD{}) // 24
unsafe.Alignof(SizeOfD{}) // 4
Alignof返回的對(duì)齊數(shù)是結(jié)構(gòu)體中最大元素所占的內(nèi)存數(shù),不超過(guò)8,如果元素是數(shù)組那么取數(shù)組類(lèi)型所占的內(nèi)存值而不是整個(gè)數(shù)組的值
type SizeOfE struct {
A byte // 1
B int64 // 8
C byte // 1
}
unsafe.Sizeof(SizeOfE{}) // 24
unsafe.Alignof(SizeOfE{}) // 8
SizeOfE中,元素的大小分別為1,8,1,但是實(shí)際結(jié)構(gòu)體占24字節(jié),遠(yuǎn)超元素實(shí)際大小,因?yàn)閮?nèi)存對(duì)齊原因,最開(kāi)始分配的8字節(jié)中包含了1字節(jié)的A,剩余的7字節(jié)不足以放下B,又為B分配了8字節(jié),剩余的C獨(dú)占再分配的8字節(jié)。
type SizeOfE struct {
A byte // 1
C byte // 1
B int64 // 8
}
unsafe.Sizeof(SizeOfE{}) // 16
unsafe.Alignof(SizeOfE{}) // 8
換一種寫(xiě)法,把A,C放到上面,B放到下面。這時(shí)SizeOfE占用的內(nèi)存變?yōu)榱?6字節(jié)。因?yàn)槭紫确峙涞?字節(jié)足以放下A和C,省去了8字節(jié)的空間。
上面一個(gè)結(jié)構(gòu)體中元素的不同順序足以導(dǎo)致內(nèi)存分配的巨大差異。前一種寫(xiě)法產(chǎn)生了很多的內(nèi)存空洞,導(dǎo)致結(jié)構(gòu)體不夠緊湊,造成內(nèi)存浪費(fèi)。
unsafe.Offsetof:返回結(jié)構(gòu)體中元素所在內(nèi)存的偏移量
type SizeOfF struct {
A byte
C int16
B int64
D int32
}
unsafe.Offsetof(SizeOfF{}.A) // 0
unsafe.Offsetof(SizeOfF{}.C) // 2
unsafe.Offsetof(SizeOfF{}.B) // 8
unsafe.Offsetof(SizeOfF{}.D) // 16
下圖為內(nèi)存分布圖:

藍(lán)色區(qū)域是元素實(shí)際所占內(nèi)存,灰色為內(nèi)存空洞。
下面總結(jié)一下go語(yǔ)言中各種類(lèi)型所占內(nèi)存大?。▁64環(huán)境下):
X64下1機(jī)器字節(jié)=8字節(jié)

總結(jié)一下:
從例子中可以看出,結(jié)構(gòu)體中元素不同順序的排列會(huì)導(dǎo)致內(nèi)存分配的極大差異,不好的順序會(huì)產(chǎn)生許多的內(nèi)存空洞,造成大量?jī)?nèi)存浪費(fèi)。
雖然這幾個(gè)函數(shù)都在unsafe包中,但是他們并不是不安全的。在需要優(yōu)化內(nèi)存空間時(shí)這幾個(gè)函數(shù)非常有用。