What does this print on a 64-bit platform, and why?
package main
import (
"fmt"
"unsafe"
)
type A struct {
a bool
b int64
c bool
}
type B struct {
b int64
a bool
c bool
}
func main() {
fmt.Println(unsafe.Sizeof(A{}), unsafe.Sizeof(B{}))
fmt.Println(unsafe.Offsetof(A{}.b), unsafe.Alignof(A{}))
}
Output:
24 16
8 8
Each field is aligned to its own alignment requirement, and the struct's alignment is that of its most-aligned field (8, for int64). In A, a takes byte 0, then 7 bytes of padding so that b starts at offset 8. c is at 16, followed by 7 more bytes of tail padding, which keeps elements of []A aligned. That gives 24. In B the two bools share one 8-byte word: 8 + 1 + 1 + 6 padding = 16.
Rule of thumb: order fields from largest alignment to smallest. The fieldalignment analyzer from golang.org/x/tools reports structs that could be smaller. This matters in large slices, where saving 33% on each element adds up, and for cache-line use. Go does not reorder fields for you, because the declared layout is visible through unsafe, reflection and cgo.
More on Memory, GC & Runtime Internals
- Q346How do you measure and assert allocation counts?
- Q347When does converting between
stringand[]byteNOT allocate? - Q349Explain 64-bit atomic alignment and false sharing. How do you lay out hot concurrent counters?
- Q350What are zero-sized types' memory semantics? What do these print?
- Q351What are the rules for valid
unsafe.Pointerusage? - Q352Why is keeping a pointer as
uintptrdangerous even if the object is still referenced elsewhere?