Как поля структуры (struct) в Go располагаются в памяти и как это можно оптимизировать?

Ответ

Поля структуры в Go располагаются в памяти последовательно, но с учётом выравнивания данных (data alignment). Компилятор может добавлять неиспользуемые байты (padding) между полями, чтобы адрес каждого поля был кратен его размеру (или размеру машинного слова, например, 4 или 8 байт). Это необходимо для ускорения доступа к данным на уровне процессора.

Из-за этого порядок полей в структуре напрямую влияет на её итоговый размер в памяти.

Пример неоптимального расположения (64-битная архитектура):

// Размер: 24 байта
type BadStruct struct {
    a bool    // 1 байт
    // 7 байт padding для выравнивания следующего поля
    b int64   // 8 байт
    c int32   // 4 байта
    // 4 байта padding для выравнивания всей структуры до 8 байт
}

Пример оптимального расположения:

Чтобы минимизировать размер, поля следует объявлять в порядке убывания их размера.

// Размер: 16 байт
type GoodStruct struct {
    b int64   // 8 байт
    c int32   // 4 байта
    a bool    // 1 байт
    // 3 байта padding для выравнивания всей структуры до 8 байт
}

Вывод:

  1. Проверка размера: Используйте unsafe.Sizeof() для определения размера переменной или структуры в байтах.
  2. Оптимизация: Для экономии памяти всегда располагайте поля структуры от самых больших (например, int64, string, slice) к самым маленьким (например, int8, bool).
  3. Инструменты: Существуют утилиты, например golang.org/x/tools/go/analysis/passes/fieldalignment, которые помогают автоматически находить структуры с неоптимальным порядком полей. Их можно интегрировать в CI/CD или использовать через go vet.