Padding & Alignment in Go
Memory layout is a crucial aspect of software performance, especially in languages like Go that manage memory efficiently under the hood. Understanding padding and alignment helps optimize struct memory usage, avoid unexpected memory bloat, and improve cache efficiency. In this article, we’ll dive deep into Go’s memory alignment, struct padding, and best practices.
What is Alignment?
Alignment refers to the requirement that primitive data types should be stored at memory addresses that are multiples of their size. For example:
A
uint32(4 bytes) should be stored at an address that is a multiple of 4.A
uint64(8 bytes) should be stored at an address that is a multiple of 8.
This ensures optimal CPU access and prevents misaligned memory access, which can lead to performance penalties on certain architectures.
What is Padding?
Padding is the extra memory added to a struct to satisfy alignment requirements. The Go compiler automatically inserts padding bytes to align struct fields properly. Improper struct ordering can lead to unnecessary memory waste.
Example: Understanding Padding
Consider the following struct:
package main
import (
"fmt"
"unsafe"
)
type Example struct {
A int8 // 1 byte
B int64 // 8 bytes (needs 7 bytes of padding after A)
C int32 // 4 bytes (needs 4 bytes of padding after C)
}
func main() {
var ex Example
fmt.Printf("Size of struct: %d bytes\n", unsafe.Sizeof(ex))
}Output:
Size of struct: 24 bytesMemory Layout of Example
Even though the raw field sizes add up to 13 bytes, the struct consumes 24 bytes due to padding!
Optimizing Struct Layout
Reordering fields can reduce unnecessary padding and make memory usage more efficient:
type Optimized struct {
B int64 // 8 bytes
C int32 // 4 bytes
A int8 // 1 byte (only 3 bytes padding needed)
}
Now, the layout looks like:
By simply reordering, we reduce the struct size from 24 bytes to 16 bytes, a 33% improvement.
Go’s unsafe.Alignof and unsafe.Sizeof
Go provides the unsafe package to inspect memory alignment:
package main
import (
"fmt"
"unsafe"
)
type Optimized struct {
B int64 // 8 bytes
C int32 // 4 bytes
A int8 // 1 byte (only 3 bytes padding needed)
}
func main() {
fmt.Printf("Alignof(int8): %d\n", unsafe.Alignof(int8(0)))
fmt.Printf("Alignof(int64): %d\n", unsafe.Alignof(int64(0)))
fmt.Printf("Alignof(struct): %d\n", unsafe.Alignof(Optimized{}))
}
Output:
Alignof(int8): 1
Alignof(int64): 8
Alignof(struct): 8Key Takeaways
Understand padding – Go automatically inserts padding to maintain alignment.
Optimize struct layout – Arrange fields from largest to smallest to minimize padding.
Use
unsafe.Sizeofandunsafe.Alignof– Inspect memory usage and alignment.Consider cache performance – Efficient memory layout improves CPU cache utilization.
By mastering alignment and padding, you can write more memory-efficient Go programs and avoid unnecessary memory overhead.


