Google выпустила новое API для Protocol Buffers в Go
Команда Go представила новое API для работы с Protocol Buffers, получившее название Opaque API. Это важное обновление, которое должно сделать работу с protobuf более эффективной и безопасной.
До сих пор в Go использовалось так называемое Open Struct API, где все поля структур были доступны напрямую. Например, так:
type LogEntry struct {
BackendServer *string
RequestSize *uint32
IPAddress *string
}
С новым Opaque API все поля становятся приватными, а доступ к ним осуществляется через методы:
type LogEntry struct {
xxx_hidden_BackendServer *string
xxx_hidden_RequestSize uint32
xxx_hidden_IPAddress *string
// …внутренние поля опущены
}
// Доступ через методы
func (l *LogEntry) GetBackendServer() string
func (l *LogEntry) HasBackendServer() bool
func (l *LogEntry) SetBackendServer(string)
func (l *LogEntry) ClearBackendServer()
//...
Зачем это сделано?
Новый подход значительно экономит память. Вместо использования указателей для хранения информации о наличии значения в поле (presence), теперь используются битовые поля. В некоторых случаях это позволяет сократить количество аллокаций памяти почти на 60%. (речь идет про элементарные типы, такие как целые числа, булевы и т.д)
Появилась возможность реализовать ленивое декодирование сообщений. Теперь вложенные сообщения декодируются только при первом обращении к ним, а не при общей десериализации. Для некоторых приложений это дает колоссальный прирост производительности и уменьшает аллокации
Новое API предотвращает некоторые ошибки. Например, раньше было легко случайно сравнить указатели вместо значений при работе с enum:
/*
message LogEntry {
enum DeviceType {
DESKTOP = 0;
MOBILE = 1;
VR = 2;
};
DeviceType device_type = 1;
}
*/
// Неправильно и незаметно:
if cv.DeviceType == logpb.LogEntry_DESKTOP.Enum()
// Правильно:
if cv.GetDeviceType() == logpb.LogEntry_DESKTOP
С новым API такая ошибка просто невозможна, так как прямого доступа к полям нет.
Еще одно улучшение касается работы с reflection. Раньше разработчики могли случайно использовать стандартный пакет reflect вместо специального protobuf-reflection, что приводило к неожиданным результатам. Теперь такие ошибки исключены.
Google предлагает постепенный путь миграции через "гибридное" API, которое поддерживает оба способа работы. Для новых проектов рекомендуется сразу использовать Opaque API. В 2024 году оно станет стандартным подходом в новой версии Protocol Buffers (Edition 2024).
Старое API никуда не исчезнет – принцип обратной совместимости.
Для перехода на новое API Google предоставляет инструмент open2opaque, который помогает автоматически переписывать код. Внутри самого Google большинство protobuf-файлов уже переведено на новое API, и оно активно используется на проде.
cross-пост из tg-канала Cross Join