A CLI tool that visualizes the memory layout of Go structs, shows wasted bytes from padding, and automatically outputs an optimally packed version using the greedy sort-by-alignment algorithm.
- Parses any Go struct definition you paste into it
- Renders a color-coded byte grid of the current layout
- Field bytes are colored (one color per field)
- Internal (avoidable) padding is red
- Trailing (unavoidable) padding is gray
- Applies the optimal field ordering (largest alignment first) and renders the optimized layout
- Prints the ready-to-use optimized struct definition
Go (like C) inserts padding bytes between struct fields to keep each field aligned to its natural boundary. The order of your fields determines how much padding is inserted. Sorting fields from largest to smallest alignment eliminates all internal padding — this is provably optimal because all Go alignments are powers of two.
- Go 1.21 or later
- A terminal with ANSI color support (any modern terminal)
go install github.com/UcGeorge/structviz@latestOr clone and run locally:
git clone https://github.com/UcGeorge/structviz
cd structviz
go build -o structviz .Run the tool, paste your struct, then press Ctrl+D (macOS/Linux) or Ctrl+Z (Windows):
structvizOr pipe directly:
cat mystruct.go | structvizecho 'type Request struct {
Active bool
ID int64
Code int32
Name string
Flag bool
Count int16
}' | structvizAll three forms are accepted:
// Full type declaration (recommended)
type MyStruct struct {
...
}
// Bare struct keyword
struct {
...
}
// Just the body
{
...
}All built-in Go types:
| Types | Size | Alignment |
|---|---|---|
bool, byte, int8, uint8 |
1 | 1 |
int16, uint16 |
2 | 2 |
int32, uint32, float32, rune |
4 | 4 |
int, uint, uintptr, int64, uint64, float64, complex64 |
8 | 8 |
string, complex128, error |
16 | 8 |
[]T (slice header) |
24 | 8 |
*T, map[K]V, chan T, func(...) |
8 | 8 |
interface{} |
16 | 8 |
[N]T (array) |
N × sizeof(T) | align(T) |
anonymous struct{...} |
computed recursively | — |
External package types (e.g. time.Time, sync.Mutex) are not supported — use only built-in types or inline the fields manually.
Each row of the grid is exactly alignment bytes wide, where alignment is the largest field alignment in the struct. This mirrors how memory is actually laid out relative to the struct's own alignment requirement.
0 1 2 3 4 5 6 7
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
0: │Name │ │ │ │ │ │ │ │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
8: │Name │ │ │ │ │ │ │ │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
16: │ID │ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
- Colored cells — one field, one color; the first byte shows the field name
- Red cells (▒) — internal padding; bytes wasted because of misaligned field order
- Gray cells (░) — trailing padding; unavoidable, determined by the largest alignment
Sorting fields by alignment descending is always optimal (not just heuristic) because:
- All Go alignment values are powers of 2
- After placing a field with alignment A, the current offset is always already a multiple of any smaller alignment B (since A is a multiple of B)
- This means no internal padding ever occurs
- The only remaining padding is the trailing alignment padding, which is a fixed lower bound regardless of field order
ORIGINAL: Request
────────────────────────────────────────────────────────────
size: 48 bytes alignment: 8 internal padding: 12 bytes trailing padding: 4 bytes total waste: 16 bytes
OPTIMIZED: Request
────────────────────────────────────────────────────────────
size: 32 bytes alignment: 8 internal padding: 0 bytes trailing padding: 0 bytes total waste: 0 bytes
Saved 16 bytes (33% reduction)
type Request struct {
Name string
ID int64
Code int32
Count int16
Active bool
Flag bool
}