W3Cschool
恭喜您成為首批注冊用戶
獲得88經驗值獎勵
原文鏈接:https://gopl-zh.github.io/ch13/ch13-01.html
unsafe.Sizeof函數(shù)返回操作數(shù)在內存中的字節(jié)大小,參數(shù)可以是任意類型的表達式,但是它并不會對表達式進行求值。一個Sizeof函數(shù)調用是一個對應uintptr類型的常量表達式,因此返回的結果可以用作數(shù)組類型的長度大小,或者用作計算其他的常量。
import "unsafe"
fmt.Println(unsafe.Sizeof(float64(0))) // "8"
Sizeof函數(shù)返回的大小只包括數(shù)據結構中固定的部分,例如字符串對應結構體中的指針和字符串長度部分,但是并不包含指針指向的字符串的內容。Go語言中非聚合類型通常有一個固定的大小,盡管在不同工具鏈下生成的實際大小可能會有所不同。考慮到可移植性,引用類型或包含引用類型的大小在32位平臺上是4個字節(jié),在64位平臺上是8個字節(jié)。
計算機在加載和保存數(shù)據時,如果內存地址合理地對齊的將會更有效率。例如2字節(jié)大小的int16類型的變量地址應該是偶數(shù),一個4字節(jié)大小的rune類型變量的地址應該是4的倍數(shù),一個8字節(jié)大小的float64、uint64或64-bit指針類型變量的地址應該是8字節(jié)對齊的。但是對于再大的地址對齊倍數(shù)則是不需要的,即使是complex128等較大的數(shù)據類型最多也只是8字節(jié)對齊。
由于地址對齊這個因素,一個聚合類型(結構體或數(shù)組)的大小至少是所有字段或元素大小的總和,或者更大因為可能存在內存空洞。內存空洞是編譯器自動添加的沒有被使用的內存空間,用于保證后面每個字段或元素的地址相對于結構或數(shù)組的開始地址能夠合理地對齊(譯注:內存空洞可能會存在一些隨機數(shù)據,可能會對用unsafe包直接操作內存的處理產生影響)。
類型 | 大小 |
---|---|
bool
|
1個字節(jié) |
intN, uintN, floatN, complexN
|
N/8個字節(jié)(例如float64是8個字節(jié)) |
int, uint, uintptr
|
1個機器字 |
*T
|
1個機器字 |
string
|
2個機器字(data、len) |
[]T
|
3個機器字(data、len、cap) |
map
|
1個機器字 |
func
|
1個機器字 |
chan
|
1個機器字 |
interface
|
2個機器字(type、value) |
Go語言的規(guī)范并沒有要求一個字段的聲明順序和內存中的順序是一致的,所以理論上一個編譯器可以隨意地重新排列每個字段的內存位置,雖然在寫作本書的時候編譯器還沒有這么做。下面的三個結構體雖然有著相同的字段,但是第一種寫法比另外的兩個需要多50%的內存。
// 64-bit 32-bit
struct{ bool; float64; int16 } // 3 words 4words
struct{ float64; int16; bool } // 2 words 3words
struct{ bool; int16; float64 } // 2 words 3words
關于內存地址對齊算法的細節(jié)超出了本書的范圍,也不是每一個結構體都需要擔心這個問題,不過有效的包裝可以使數(shù)據結構更加緊湊(譯注:未來的Go語言編譯器應該會默認優(yōu)化結構體的順序,當然應該也能夠指定具體的內存布局,相同討論請參考 Issue10014 ),內存使用率和性能都可能會受益。
unsafe.Alignof
函數(shù)返回對應參數(shù)的類型需要對齊的倍數(shù)。和 Sizeof 類似, Alignof 也是返回一個常量表達式,對應一個常量。通常情況下布爾和數(shù)字類型需要對齊到它們本身的大?。ㄗ疃?個字節(jié)),其它的類型對齊到機器字大小。
unsafe.Offsetof
函數(shù)的參數(shù)必須是一個字段 x.f
,然后返回 f
字段相對于 x
起始地址的偏移量,包括可能的空洞。
圖 13.1 顯示了一個結構體變量 x 以及其在32位和64位機器上的典型的內存?;疑珔^(qū)域是空洞。
var x struct {
a bool
b int16
c []int
}
下面顯示了對x和它的三個字段調用unsafe包相關函數(shù)的計算結果:
32位系統(tǒng):
Sizeof(x) = 16 Alignof(x) = 4
Sizeof(x.a) = 1 Alignof(x.a) = 1 Offsetof(x.a) = 0
Sizeof(x.b) = 2 Alignof(x.b) = 2 Offsetof(x.b) = 2
Sizeof(x.c) = 12 Alignof(x.c) = 4 Offsetof(x.c) = 4
64位系統(tǒng):
Sizeof(x) = 32 Alignof(x) = 8
Sizeof(x.a) = 1 Alignof(x.a) = 1 Offsetof(x.a) = 0
Sizeof(x.b) = 2 Alignof(x.b) = 2 Offsetof(x.b) = 2
Sizeof(x.c) = 24 Alignof(x.c) = 8 Offsetof(x.c) = 8
雖然這幾個函數(shù)在不安全的unsafe包,但是這幾個函數(shù)調用并不是真的不安全,特別在需要優(yōu)化內存空間時它們返回的結果對于理解原生的內存布局很有幫助。
![]() | ![]() |
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: