// Width describes the number of bytes of storage
// an instance of a type occupies
//
// Width is a property of a type
//
// As every value in a Go program has a type,
// the width of the value is defined by its type
// and is always a multiple of **8 bits**.
// [tip] width ~ 8* bits
// Discover the width of any value,
// and thus the width of its type
// using the unsafe.Sizeof() function
var s string // occupies 16 bits
var c complex128 // occupies 128 bits
fmt.Println(unsafe.Sizeof(s)) // prints 8
fmt.Println(unsafe.Sizeof(c)) // prints 16
var a [3]uint32
fmt.Println(unsafe.Sizeof(a)) // prints 12
// Each type has another property, its alignment.
// Alignments are always powers of two.
//
// The alignment of a basic type is usually equal
// to its width
//
// [tip] if basic type then width == alignment
// The alignment of a struct is the maximum
// alignment of any field
// the alignment of an array is the alignment
// of the array element.
// The maximum alignment of any value is
// therefore the maximum alignment of any
// basic type.
//
// Even on 32-bit systems this is often 8 bytes,
// i.e. 8*8 bits ~ 64 bits because atomic operations
// on 64-bit values typically require 64-bit alignment.
//
// So the MAX possible alignment is 64 bits
// To be concrete, a struct containing 3 int32
// fields has alignment 4 but width 12.
// It is true that a value’s width is always a
// multiple of its alignment. One implication
// is that there is no padding between array elements.
type S struct {
a uint16 // width == alignment == 2
}
var s S
fmt.Println(unsafe.Sizeof(s)) // prints 2
type S struct {
a uint16
b uint32
}
var s S
fmt.Println(unsafe.Sizeof(s)) // prints 8, not 6
type S struct {
a uint32 // width == alignment == 4
b uint32
c uint32
}
func main() {
var a [3]uint32
var s S
fmt.Println(unsafe.Sizeof(a)) // prints 12
fmt.Println(unsafe.Sizeof(s)) // prints 12
}