Golang Struct内存偏移

转载自:

https://studygolang.com/articles/13364?fr=sidebar

https://www.cnblogs.com/wdliu/p/9209419.html

 

在我们定义Struct时,如果我们书写StructField的顺序不同,可能会造成申请到的内存空间不同的情况,主要原因时:struct内的field内存分配是以4B为基础的,超过4B时必须独占,而且Struct是一片连续的内存。

type A1 struct {
    a bool
    b uint32
    c bool
    d uint32
    e uint8
    f uint32
    g uint8
}

计算一下A1所需要占用的内存:

  1. 首先第1个4B中放入a,a是bool型,占用1B,剩余3B
  2. 这时看b是uint32,占用4B,剩余3B放不下,所以offset到下一个4B空间,这时我们会发现3B没有放东西,被浪费了
  3. 依次往下,A1要占用28B的空间

根据1,2两个步骤很容易看出,有很多浪费掉空间。

来看优化后的定义顺序:

type A2 struct {
    a bool
    c bool
    e uint8
    g uint8
    b uint32
    d uint32
    f uint32
}
  1. 首先第1个4B中放入a,a是bool型,占用1B,剩余3B
  2. c是bool,占用1B,放入后剩余2B
  3. d是uint8,占用1B,放入后剩余1B
  4. 依次往下

这样会使内存使用率高很多。

内存偏移实例:

package main

import (
    "fmt"
    "reflect"
)

type Student struct {
    Name string
    Age int64
    wight int64
    high int64
    score int64

}

func main() {
     var stu1 = new(Student)
     fmt.Printf("%p\n",&stu1.Name)
     fmt.Printf("%p\n",&stu1.Age)
     fmt.Printf("%p\n",&stu1.wight)
     fmt.Printf("%p\n",&stu1.high)
     fmt.Printf("%p\n",&stu1.score)
    typ := reflect.TypeOf(Student{})
    fmt.Printf("Struct is %d bytes long\n", typ.Size())
    // We can run through the fields in the structure in order
    n := typ.NumField()
    for i := 0; i < n; i++ {
        field := typ.Field(i)
        fmt.Printf("%s at offset %v, size=%d, align=%d\n",
            field.Name, field.Offset, field.Type.Size(),
            field.Type.Align())
        }
}

//结果
0xc42007a180
0xc42007a190
0xc42007a198
0xc42007a1a0
0xc42007a1a8
Struct is 48 bytes long
Name at offset 0, size=16, align=8
Age at offset 16, size=8, align=8
wight at offset 24, size=8, align=8
high at offset 32, size=8, align=8
score at offset 40, size=8, align=8

为什么string是16个字节呢?因为string的结构包含两个域,一个是指向Data的指针,占8个字节,一个是表示string长度的len,占8个字节

你可能感兴趣的:(Golang Struct内存偏移)