Реализуйте потокобезопасный кэш «ключ-значение». Профиль нагрузки —
read-heavy: примерно 95% операций это чтения (Get) и лишь 5% — записи
(Set / Delete). Реализация должна быть оптимизирована под такой сценарий.
type Cache struct {
// ...
}
func NewCache() *Cache
func (c *Cache) Set(key string, value interface{})
func (c *Cache) Get(key string) (interface{}, bool)
func (c *Cache) Delete(key string)
Set сохраняет значение по ключу.
Get возвращает значение и true, если ключ есть; иначе nil, false.
Delete удаляет ключ (повторное удаление безопасно).
Тест дёргает Set/Get/Delete из множества горутин одновременно под
-race и проверяет функциональную корректность.
На что смотрит интервьюер:
- Использование
sync.RWMutex: Get берёт RLock (читатели не блокируют
друг друга), Set/Delete берут Lock. Это даёт параллельные чтения и
выигрыш на read-heavy профиле по сравнению с обычным sync.Mutex.
- Нет гонок под
-race, корректная инициализация map в NewCache.
- Кандидат понимает, почему
RWMutex уместен именно при 95% чтений и в чём
его минусы при высокой доле записей.