Начав изучать Go в течение последних шести месяцев, будучи одним из основных строительных блоков приложения Go, я обнаружил, что много использую структуры. Это побудило меня глубоко погрузиться в то, что такое структуры, как они представлены в памяти и как получить от структур максимальную отдачу.

Это мое понимание именно этого.

Что такое структура?

Структуры на самом базовом уровне - это просто набор свойств, сгруппированных в один тип.

Это позволяет аккуратно инкапсулировать все данные, относящиеся к одной сущности, в одно определение облегченного типа, после чего поведение может быть реализовано путем определения функций в типе структуры. В приведенном ниже примере была создана функция для изменения частного поля имени пользователя структуры User, выполняя некоторую проверку обновленного значения.

Использование структуры

Расширение предыдущего примера структуры User. Экземпляр структуры можно создать и использовать, как в приведенном ниже примере.

Любые поля, пропущенные при создании экземпляра структуры, принимают нулевое значение типа этого поля. Например. если возраст был опущен при создании пользователя, значение по умолчанию - 0.

После создания экземпляра структуры любые доступные функции, определенные в типе структуры, могут быть вызваны для переменной, которой эта структура была назначена.

Структурные теги

Go предоставляет необязательные строковые литералы теги структуры, которые можно использовать для добавления метаданных в поле структуры. Теги особенно полезны, когда дело доходит до маршалинга и демаршалинга данных из таких форматов, как JSON, XML или YAML.

Чтобы расширить тот же пример структуры User, что и в предыдущих разделах, в приведенном ниже примере добавляются структурные теги JSON и отменяется маршалинг документа JSON, содержащего данные пользователя, непосредственно в структуру User.

То же самое можно сделать для документа JSON, содержащего массив пользователей, просто изменив переменную users на массив User.

Эта страница поддерживает хороший список хорошо известных структурных тегов для маршаллинга / демаршаллинга из разных форматов.

Представление памяти

Когда дело доходит до выделения памяти для структур, они всегда выделяются непрерывными, выровненными по байтам блоками памяти, а поля выделяются и сохраняются в том порядке, в котором они определены.

Концепция байтового выравнивания в этом контексте означает, что смежные блоки памяти выравниваются со смещениями, равными размеру слова платформы (4 байта в 32-битной, 8 байтов в 64-битной системе ). Рассмотрим следующий пример структуры, в которой есть три поля разного размера, в 64-битной среде блоки памяти будут выровнены с 8-байтовыми смещениями.

Это приводит к тому, что первый блок из 8 байтов полностью занят a (8 байтов). В следующем блоке памяти (смещение на 8 байтов от начального адреса памяти структуры) первые 2 байта заняты b, следующий 1 байт занят c, тогда оставшиеся 5 байтов являются пустым блоком байтов.

Оптимизация памяти

Учитывая, как выделяется память для структур, как показано в предыдущем разделе, в зависимости от порядка, в котором поля определены в структуре, это может быть довольно неэффективным из-за количества требуемых байтов заполнения. Однако можно оптимизировать использование памяти структурой, определяя поля в сознательном порядке, чтобы максимально использовать каждый блок памяти, уменьшая потребность в избыточных байтах заполнения.

В следующем примере представлена ​​структура Post, представляющая сообщение в блоге. В первой итерации, прежде чем предпринимать шаги по оптимизации использования памяти, общая память объединенных полей составляет 35 байтов, однако общий размер структуры равен 48 байтам из-за байтов заполнения.

Теперь, если поля структуры переупорядочены, чтобы минимизировать байты заполнения, результирующий размер структуры составит всего 40 байтов.

В современных системах, где ограничения памяти обычно не являются проблемой, выгода, получаемая от микрооптимизации, подобной этой, освобождения 8 байтов памяти, невелика. Однако способность понять на этом уровне, как структура распределяет память и как, при необходимости, применять такую ​​оптимизацию, неоценима.

Примеры кода из этого поста доступны по приведенным ниже ссылкам в Go Playground.

Примеры общей структуры: https://play.golang.org/p/MNfgRWM7X1h
Оптимизация памяти: https://play.golang.org / p / XJw0-s1d9bm