目錄

Golang Struct Padding

Golang Struct Padding

Go 編譯器可能會在結構值的某些字段之後填充一些 byte。 這謝填充的byte將會被算進此結構的大小。 因此,結構類型的大小可能不是其所有字段大小的簡單總和。

Go compilers may pad some bytes after certain fields of struct values. The padded bytes are counted for struct sizes. So the size of a struct type may be not a simple sum of the sizes of all its fields.

Example

1
2
3
4
5
6
7
type T1 struct {
   a int8
   // 7 bytes are padded here
   b int64
   c int16
   // 6 bytes are padded here.
}

a 為 1 byte, b 為 8 bytes, 所以 a 後面需要 7 bytes 去對齊. 同理 c 之後需要 6 bytes 去對齊. 所以此 struct 總共用了 24 bytes

-------a
bbbbbbbb
------cc

如果把順序對調如下:

1
2
3
4
5
6
7
type T2 struct {
   a int8
   // 1 bytes are padded here
   c int16
   // 4 bytes are padded here.
   b int64
}

總共用了 16 bytes

----cc-a
bbbbbbbb

unsafe.Sizeof

可以使用 unsafe.Sizeof function 取得 value/type sizes. For example: https://go.dev/play/p/EepGQTDVK42

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
	"fmt"
	"unsafe"
)

type T1 struct {
	a int8
	// 7 bytes are padded here
	b int64
	c int16
	// 6 bytes are padded here.
}
type T2 struct {
	a int8
	// 1 bytes are padded here
	c int16
	// 4 bytes are padded here.
	b int64
}

func main() {
	fmt.Println(unsafe.Sizeof(T1{})) // 24
	fmt.Println(unsafe.Sizeof(T2{})) //16
}

在實際應用中,一般情況下,我們應該讓相關字段相鄰以獲得良好的可讀性, 並在真正需要時才以最節省內存的方式對字段進行排序。 我們可以將padding bytes視為內存浪費的一種形式, 是程序性能、代碼可讀性和內存節省之間的權衡結果。