Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 Контент вільний від AI. Цей пост на 100% написаний людиною, як і все на моєму блозі. Насолоджуйтесь!

17.08.2024

Модуль unique в Golang 1.23: глобально-унікальні символи

Не встиг я подати ідею про заміну повторюваних рядків на глобально-унікальні символи (interning), як вийшов Go 1.23, де зʼявився модуль unique, який буквально те й робить. Приємна несподіванка!

Метод unique.Make підтримує не тільки рядки, а й будь-який порівнюваний тип, та замінює значення на глобально унікальні вказівники. Рядки-літерали в Go і так є константами, хіба що кожна копія має власний 16-байтовий заголовок. А от якщо доводиться отримувати багато повторюваних рядків ззовні, модуль unique стане до нагоди.

Наприклад, ми завантажуємо з бази фічафлаґи для поточного користувача. Кожний виклик утворює рядки наново та залишає за собою купу сміття. Якщо зробити їх типом unique.Handle[string], то ловимо двох зайців: фічафлаґи займають менше памʼяті, але до того ж тепер їхнє порівняння зводиться до порівняння вказівників. Виходить практично те ж саме, що замінити фічафлаґи на чисельні константи (доволі очевидна оптимізація), тільки повністю автоматично.

Може виникнути питання, чи безпечно брати рядки ззовні та глобалізувати — чи не призведе це до роздуття памʼяті від переповнення словника значень? Я перевірив, та виходить, що ні: модуль unique автоматично очищає невживані значення, тобто роздуття буде не більше, як без глобалізації. А можливо, й менше.

До речі, для того використовуються слабкі вказівники — тип weak.Pointer. То є вказівники, які не впливають на збирання сміття. Тобто все, що робить функція очищення — це чекає, поки значення звільнить прибиральник, після чого видаляє вивільнені значення зі словника.