C语言中,可以使用sizeof()计算变量或类型占用的内存大小。在Go语言中,也提供了类似的功能, 不过只能查看变量占用空间大小。具体使用举例如下。
package main
import (
"fmt"
"unsafe"
)
type Man struct {
Name string
Age int
}
func main() {
m := Man{Name:"John", Age:20}
fmt.Println("man size:", unsafe.Sizeof(m))
fmt.Println("name size:", unsafe.Sizeof(m.Name))
fmt.Println("age size:", unsafe.Sizeof(m.Age))
}
output:
man size: 24
name size: 16
age size: 8
Go 编译器是否会对结构体类型做填充以保证字段对齐
至少对于标准 Go 编译器和 gccgo, 答案是肯定的. 填充是操作系统和编译器相关的.
比如:
type T1 struct { a int8 // 7 bytes padded on AMD64 OS and pad 3 bytes padded on i386 OS here b int64 c int16 // 6 bytes padded on AMD64 OS and pad 2 bytes padded on i386 OS here } type T2 struct { a int8 // 1 byte padded on both AMD64 and i386 OS here c int16 // 4 bytes padded on AMD64 OS here. No padding on i386 OS b int64 } |
T1.b
内存中的地址值在 AMD64 系统必须的是 8 字节对齐的, i386 系统是 4 字节对齐的. 这就是为什么 T1.a
在 AMD64 系统被填充 7 字节, 在 i386 系统被填充 3 字节.
Go 规范对类型对齐做一些保证. 规则之一是一个结构体类型的对齐是它字段类型最大的那个的对齐. 所以 T1
也是 AMD64 系统 8 字节对齐, i386 系统 4 字节对齐(和 T1.b
类型一样, int64
), 并且标准的 Go 编译器将确保类型值的大小是该类型的对齐保证的倍数, 这就是为什么 T1.c
在 AMD64 系统被填充 6 字节, 在 i386 系统被填充 2 字节.
一个结构体中的字段顺序会影响填充, 并且填充会影响后续结构体的大小. 在 AMD64 系统, T1
的大小是 24, 但 T2
的大小是 16.
Go 编译器不会重排结构体字段来减小结构体大小. 这样做会引起一些不可预知的结果. 然而, 程序员可以通过手动重排字段来减少填充.
来源:oschina
链接:https://my.oschina.net/u/105637/blog/3061720