Go中的sizeof结构

时间:2010-01-21 23:18:03

标签: struct go sizeof

我正在看看Go,看起来很有前途。 我试图弄清楚如何获得一个go结构的大小,为 像

这样的例子
type Coord3d struct {
    X, Y, Z int64
}

当然我知道它是24个字节,但我想以编程方式知道它。

你有什么想法怎么做?

6 个答案:

答案 0 :(得分:32)

import unsafe "unsafe"

/* Structure describing an inotify event.  */
type INotifyInfo struct {
    Wd     int32  // Watch descriptor
    Mask   uint32 // Watch mask
    Cookie uint32 // Cookie to synchronize two events
    Len    uint32 // Length (including NULs) of name
}

func doSomething() {
    var info INotifyInfo
    const infoSize = unsafe.Sizeof(info)
    ...
}

注意: OP错了。 unsafe.Sizeof在示例Coord3d结构上返回24。见下面的评论。

答案 1 :(得分:24)

Roger已经展示了如何使用SizeOf包中的unsafe方法。请确保在依赖函数返回的值之前阅读此内容:

  

大小不包括x可能引用的任何内存。对于   例如,如果x是切片,则Sizeof返回切片的大小   描述符,而不是切片引用的内存大小。

除此之外,我想解释一下如何使用几个简单的规则轻松计算任何结构的大小。然后如何使用有用的service验证您的直觉。

大小取决于它所包含的类型以及结构中字段的顺序(因为将使用不同的填充)。这意味着具有相同字段的两个结构可以具有不同的大小。

例如,此结构的大小为32

struct {
    a bool
    b string
    c bool
}

略有修改将大小为24 25%差异仅仅因为字段的排序更紧凑)

struct {
    a bool
    c bool
    b string
}

enter image description here enter image description here

从图片中可以看出,在第二个示例中,我们删除了其中一个填充并移动了一个字段以利用之前的填充。对齐可以是1,2,4或8.填充是用于填充变量以填充对齐的空间(基本上是浪费的空间)。

了解这条规则并记住:

  • bool,int8 / uint8取1块
  • int16,uint16 - 2 chunks
  • int32,uint32,float32 - 4 chunks
  • int64,uint64,float64,pointer - 8 chunks
  • string - 16个块(8个块的2个对齐)
  • 任何切片需要24个块(8个块的3个对齐)。所以[]bool[][][]string是相同的(不要忘记重读我在开头添加的引文)
  • 长度为n的数组需要n *类型的块。

有了填充,对齐和块的知识,你可以快速找出如何改进你的结构(但仍然有意义verify your intuition using the service)。

答案 2 :(得分:6)

binary.TotalSize也是一个选项,但请注意,它与unsafe.Sizeof之间的行为略有不同:binary.TotalSize包含切片内容的大小,而unsafe.Sizeof只返回顶层的大小描述。以下是如何使用TotalSize的示例。

package main

import (
    "encoding/binary"
    "fmt"
    "reflect"
)

type T struct {
    a uint32
    b int8
}

func main() {
    var t T
    r := reflect.ValueOf(t)
    s := binary.TotalSize(r)

    fmt.Println(s)
}

答案 3 :(得分:1)

请参阅binary包。特别是TotalSize方法

答案 4 :(得分:1)

这可能会有所变化,但最后我看到有一个与结构对齐有关的杰出编译器错误(bug260.go)。最终结果是包装结构可能不会产生预期的结果。那是针对编译器6g版本5383 release.2010-04-27发布的。它可能不会影响您的结果,但需要注意这一点。

更新:go测试套件中唯一的bug是bug260.go,如上所述,截至2010-05-04发布。

布袋

答案 5 :(得分:1)

为了不产生初始化结构的开销,使用指向Coord3d的指针会更快:

package main

import (
    "fmt"
    "unsafe"
)

type Coord3d struct {
    X, Y, Z int64
}

func main() {
    var dummy *Coord3d
    fmt.Printf("sizeof(Coord3d) = %d\n", unsafe.Sizeof(*dummy))
}