Golang结构体分析

来源:互联网 发布:多益网络加班严重吗 编辑:程序博客网 时间:2024/06/04 19:50

Golang结构体分析

学习golang有一段时间,本人是从c++转学golang的,因此想研究一下golang的结构体是否也像c++一样存在字节对齐的现象。测试代码如下:

// test project main.gopackage mainimport (    "fmt"    "unsafe")type Test struct {    i int    b byte}type Test2 struct {    b2 byte    i2 int}func main() {    var stTest = Test{        i: 1,        b: 'a',    }    var stTest2 = Test2{        b2: 'a',        i2: 1,    }    //获取Test结构体的大小,结果为16    ilen := unsafe.Sizeof(stTest)    fmt.Println("stTest=", stTest, " sizeof=", ilen)    //获取stTest.i的地址    var pI *int = (*int)(unsafe.Pointer(&stTest))    //修改stTest.i的值为3    *pI = int(3)    //获取stTest.b的地址    var pB *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&stTest)) + uintptr(unsafe.Sizeof(int(0)))))    //将stTest.b的值修改为'c'    *pB = byte('c')    fmt.Println("after change stTest=", stTest)    //获取stTest.b在结构体中的偏移量    offset := unsafe.Offsetof(stTest.b)    fmt.Println("stTest.b offset=", offset)    //获取Test2结构体的大小,结果为16    ilen = unsafe.Sizeof(stTest2)    fmt.Println("stTest2=", stTest2, " sizeof=", ilen)    //获取stTest2.b2的地址    var pB2 *byte = (*byte)(unsafe.Pointer(&stTest2))    //重新设置stTest2.b2的值为'c'    *pB2 = byte('c')    //var pI2 *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&stTest2)) + uintptr(unsafe.Sizeof(byte('a')))))    //获取stTest2.i2的地址    var pI2 *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&stTest2)) + unsafe.Offsetof(stTest2.i2)))    //重新设置stTest2.i2的值为3    *pI2 = int(3)    fmt.Println("after change stTest2=", stTest2)    offset = unsafe.Offsetof(stTest2.i2)    fmt.Println("stTest2.i2 offset=", offset)}

最后输出的结果如下:
stTest= {1 97} sizeof= 16
after change stTest= {3 99}
stTest.b offset= 8
stTest2= {97 1} sizeof= 16
after change stTest2= {99 3}
stTest2.i2 offset= 8

ilen := unsafe.Sizeof(stTest)获取的结构体大小是16 说明存在字节对齐的现象8(i大小)+1(b大小)+7字节(补充字节)

var pB *byte = (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(&stTest)) + uintptr(unsafe.Sizeof(int(0)))))
这段代码是存在一定问题的,它的作用是将stTest的地址+stTest.i的大小(注意是大小而不是stTest.b的偏移量),如果结构体中第一个元素存在补位的情况结果就不正确

结构体Test2就是用来测试第一个元素存在补位的情况,如果将注释的那段代码
var pI2 *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&stTest2)) + uintptr(unsafe.Sizeof(byte(‘a’)))))
替换
var pI2 *int = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&stTest2)) + unsafe.Offsetof(stTest2.i2)))
那么stTest2的结果将不能被正确的重置,得到stTest2的结果将是
after change stTest2= {99 0}

通过分析stTest2= {97 1} sizeof= 16和stTest2.i2 offset= 8我们可以得出stTest2.b2占用了8个字节,但是b2是一个byte类型,它的大小是1个字节,这说明了b2后还补了7个字节用于字节对齐

原创粉丝点击