我正在研究Go语言,它看起来非常有前途。 我正在尝试弄清楚如何获取go结构体的大小,例如:
type Coord3d struct {
X, Y, Z int64
}
当然我知道它是24字节,但我想通过编程的方式来获取它。
你有任何想法如何实现这个吗?
除此之外,我想解释一下如何使用一些简单的规则轻松计算任何结构体的大小,以及如何使用有用的service验证您的直觉。该大小不包括x可能引用的任何内存。例如,如果x是一个切片,则Sizeof返回切片描述符的大小,而不是切片引用的内存的大小。
结构体的大小取决于其类型和结构体中字段的顺序(因为会使用不同的填充)。这意味着具有相同字段的两个结构体可能具有不同的大小。
例如,此结构体将具有大小为32
struct {
a bool
b string
c bool
}
稍作修改后,其大小为24(仅因字段更紧凑的排序而导致25%的差异)
struct {
a bool
c bool
b string
}
如您所见,在第二个示例中,我们删除了一个填充并移动了一个字段以利用先前的填充。对齐方式可以是1、2、4或8。填充是用来填充变量以填充对齐方式的空间(基本上是浪费空间)。掌握填充、对齐和字节大小的知识后,您可以快速找出如何改进您的结构体(但仍然有必要使用该服务验证您的直觉)。
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)
...
}
注意:提问者误解了。在 Coord3d 结构体示例中,unsafe.Sizeof 确实返回 24。请参见下面的评论。
unsafe.Sizeof
,但它没有起作用。” - Chris Lutzbinary.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)
}
binary.Size
和 unsafe.Sizeof
完全不同,并且存在于完全不同的原因。这与 OP 所要求的完全不同。 - Dave Cvar t T; s := binary.Size(t); fmt.Println(s)
- Komu这可能会有所变化,但据我所知,存在一个与结构对齐相关的编译器错误(bug260.go)。最终结果是打包结构可能不会产生预期的结果。这是针对编译器6g版本5383 release.2010-04-27 release的情况。它可能不会影响您的结果,但这是需要注意的事项。
更新:截至2010-05-04发布,go测试套件中仅剩下上述提到的bug260.go这个错误。
Hotei
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))
}
/*
returns the size of any type of object in bytes
*/
func getRealSizeOf(v interface{}) (int, error) {
b := new(bytes.Buffer)
if err := gob.NewEncoder(b).Encode(v); err != nil {
return 0, err
}
return b.Len(), nil
}
sync.Mutex
,它的排序是怎样的? - hewiefreeman