sizeof

Sizeof是golang中获取指定类型占用字节的函数。比如slice结构占用的字节数为24(8+8+8),注意这里说的是指定类型,和类型的值没有关系。类型决定了变量的长度和存储格式(以下均为64位cpu及64位操作系统下)

/**
     type SliceHeader struct{
      Data uintptr //8
      Len  int //8
      Cap  int //8
    }

string为8+8

type StringHeader struct{
         Data uintptr //8
         Len int  //8
     }

array为size(Type)*len,简单总结如下 。

type                      alignment guarantee
------                    ------
bool, uint8, int8         1
uint16, int16             2
uint32, int32             4
float32, complex64        4
arrays                    depend on element types
structs                   depend on field types
other types               size of a native word

内存对齐及可视化工具

//main.go
package main

type user struct {
    name    string
    age     int
    gender  int
    isBuy   bool
    hobbies []string
}
type sliceCopy struct {
    sInt    []int
    sString []int
}

func main() {

}

依次执行

structlayout -json ./main.go sliceCopy  | structlayout-svg -t "sliceCopy" > sliceCopy.svg
structlayout -json ./main.go user | structlayout-svg -t "user" > user.svg

产出物为两个svg文件

image.png
image.png

如果不想看svg,还可以直接看ascii版本,需要以下命令

bogon:sizeOfCommonType w$ structlayout -json ./main.go user | structlayout-pretty

输出如下:

    +--------+
  0 |        | <- user.name string (size 16, align 8)
    +--------+
    -........-
    +--------+
 15 |        |
    +--------+
 16 |        | <- user.age int (size 8, align 8)
    +--------+
    -........-
    +--------+
 23 |        |
    +--------+
 24 |        | <- user.gender int (size 8, align 8)
    +--------+
    -........-
    +--------+
 31 |        |
    +--------+
 32 |        | <- user.isBuy bool (size 1, align 1)
    +--------+
 33 |        | <- padding (size 7, align 0)
    +--------+
    -........-
    +--------+
 39 |        |
    +--------+
 40 |        | <- user.hobbies []string (size 24, align 8)
    +--------+
    -........-
    +--------+
 63 |        |
    +--------+

所需包

go get -u honnef.co/go/tools
//显示结构体布局
go install honnef.co/go/tools/cmd/structlayout@latest
//重新设计struct字段 减少填充的数量
go install honnef.co/go/tools/cmd/structlayout-optimize@latest
// 用ASCII格式输出
go install honnef.co/go/tools/cmd/structlayout-pretty@latest
 
//第三方可视化
go install github.com/ajstarks/svgo/structlayout-svg@latest

后续思考:

  1. 内存对齐的目的(使我们可以开发出更高效的代码,使得cpu可高效访问内存数据,)
  2. 结构体内存对齐的基本原则(小在前,大在后;空struct放在前面还是后面)
  3. 不同cpu硬件及不同os在32位和64位系统如何兼容和实现原子指令的问题(aotmic包&?)
  4. struct{} zerobase的问题(内嵌的情况下,位置分别在前中后)

牙小木木
1.5k 声望80 粉丝

iamtb.cn