Ответ
В Go для создания индекса (структуры для ускорения поиска данных в памяти) можно использовать несколько подходов, выбор которых зависит от задачи.
-
map
(Хеш-таблица): Самый распространенный и универсальный способ. Обеспечивает доступ к элементу по ключу в среднем заO(1)
.- Применение: Индексация по уникальному идентификатору (ID, email).
// Индекс пользователей по ID userIndexByID := make(map[int]User) userIndexByID[101] = User{ID: 101, Name: "Alice"}
- Применение: Индексация по уникальному идентификатору (ID, email).
-
Инвертированный индекс (
map[KeyType][]ValueID
): Классическая структура для полнотекстового поиска или поиска по тегам. Ключом является терм (слово, тег), а значением — срез идентификаторов документов, где он встречается.- Применение: Поиск постов по тегам.
// Индекс постов по тегам postsByTag := make(map[string][]int) postsByTag["golang"] = append(postsByTag["golang"], 1, 5, 12) postsByTag["backend"] = append(postsByTag["backend"], 5, 18)
- Применение: Поиск постов по тегам.
-
Сортированный срез + Бинарный поиск: Если данные можно отсортировать и они нечасто меняются, можно хранить их в отсортированном срезе и использовать функцию
sort.Search()
для поиска заO(log n)
.- Применение: Поиск в большом, статичном, отсортированном наборе данных.
-
Деревья (B-Tree, Radix Tree): Для более сложных сценариев, требующих упорядоченного обхода или поиска по префиксу. В стандартной библиотеке их нет, нужно использовать сторонние реализации.
- Применение: Автодополнение (Radix Tree), поиск по диапазону значений (B-Tree).
- Библиотека:
github.com/google/btree
.
-
Битовый набор (Bitset): Эффективен для индексации по набору булевых флагов. Каждый бит в целом числе или массиве чисел представляет наличие или отсутствие определенного свойства.
- Применение: Фильтрация пользователей по набору прав доступа (активен, премиум-пользователь и т.д.).