我正在研究 Go,它看起来很有希望。我试图弄清楚如何获得 go 结构的大小,例如
type Coord3d struct {
X, Y, Z int64
}
当然我知道它是 24 字节,但我想以编程方式知道它..
你有什么想法吗?
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。请参阅下面的评论。
Roger 已经展示了如何使用unsafe包中的SizeOf方法。确保在依赖函数返回的值之前阅读此内容:
该大小不包括 x 可能引用的任何内存。例如,如果 x 是一个切片,Sizeof 返回切片描述符的大小,而不是切片引用的内存大小。
除此之外,我还想解释如何使用几个简单的规则轻松计算任何结构的大小。然后如何使用有用的服务来验证您的直觉。
大小取决于它包含的类型和结构中字段的顺序(因为将使用不同的填充)。这意味着具有相同字段的两个结构可以具有不同的大小。
例如这个结构的大小为 32
struct {
a bool
b string
c bool
}
稍作修改将具有24 的大小(仅由于更紧凑的字段排序而导致25%的差异)
struct {
a bool
c bool
b string
}
正如您从图片中看到的,在第二个示例中,我们删除了一个填充并移动了一个字段以利用之前的填充。对齐可以是 1、2、4 或 8。填充是用于填充变量以填充对齐的空间(基本上是浪费的空间)。
知道这条规则并记住:
[]bool
,[][][]string
是一样的(不要忘记重新阅读我在开头添加的引文)n
需要n
* 类型它需要字节。有了填充、对齐和字节大小的知识,您可以快速找出如何改进您的结构(但使用服务验证您的直觉仍然是有意义的)。
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)
}
请参阅二进制包。具体TotalSize
方法
为了不产生初始化结构的开销,使用指向 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))
}
这可能会发生变化,但最后我看到有一个与结构对齐相关的突出编译器错误(bug260.go)。最终结果是打包结构可能不会产生预期的结果。那是针对编译器 6g 版本 5383 发布。2010-04-27 发布。它可能不会影响您的结果,但需要注意。
更新:截至 2010-05-04 版,go 测试套件中剩下的唯一错误是上面提到的 bug260.go。
布亭