candycache/README.md

235 lines
8.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# :candy: Candy Cache :candy:
**CandyCache** — это простой и эффективный кэш на языке Go, который позволяет хранить данные с ограниченным временем жизни (**TTL**).
# Установка
Для использования CandyCache в вашем проекте, установите его, используя ```go get git.hikan.ru/serr/candycache```, далее просто добавьте ```git.hikan.ru/serr/candycache``` в блок импорта.
# Основные возможности
- Автоматическая очистка устаревших элементов и возможность ее отключения.
- Кэшем можно управлять вручную.
- Конкурентный доступ к данным возможен благодаря мьютексам.
- Кэш может хранить данные любых типов.
- Можно создавать и загружать дампы.
# Использование
## Создание кэша
### С автоматической очисткой
Для создания нового экземпляра кэша используйте функцию **Cacher**, передавая интервал очистки в наносекундах.
Если требуется указать интервал в секундах/минутах/часах и т.д. - используйте множители из пакета **time**:
```go
cache := candycache.Cacher(10 * time.Minute) // Очистка каждые 10 минут
```
### Без автоматической очистки
Если автоматичская очистка не нужна - просто передайте параметром любое отрицательное число:
```go
cache := candycache.Cacher(-1) // Кэш не будет очищаться автоматически
```
## Добавление элемента
Для добавления элемента в кэш используйте метод **Set**:
```go
cache.Set("key", "value", 5 * time.Minute) // Элемент будет считаться устаревшим через 5 минут
```
В случае, если по указанном ключу уже что-то хранится, оно будет заменено на новый элемент.
## Получение элемента
Для получения элемента из кэша используйте метод **Get**:
```go
value, err := cache.Get("key") // Получение значения по ключу "key"
```
Если элемент найден, то в переменную **value** будет записано значение, а в **err** - **nil**. Если элемент не найден, то в **err** будет записано **key not found**, а значением вернется **nil**.
## Удаление элемента
Для удаления элемента по ключу используйте метод **Delete**:
```go
err := cache.Delete("key1")
if err != nil {
fmt.Println("Ошибка:", err) // Не найдено записи по ключу
}
```
Элемент будет удален, не смотря на то, устаревший он или нет.
## Массовое удаление элементов
### Удаление устаревших элементов
Для удаления устаревших элементов используйте метод **Cleanup**:
```go
cache.Cleanup() // Перебирает все элементы кэша, удаляет устаревшие
```
### Удаление всех элементов кэша
Для полной очистки кэша используйте метод **Flush**:
```go
cache.Flush() // Удаляет все элементы кэша, не смотря на то, устаревшие они или нет
```
## Получение информации о кэше
### Получение списка элементов
Для получения списка всех элементов в кэше используйте метод **List**:
```go
items := cache.List() // Список всех элементов кэша
for _, item := range items {
fmt.Printf("Ключ: %s, Значение: %v, Момент устаревания: %d\n", item.Key, item.Item.Data(), item.Item.DestroyTimestamp())
}
```
Получить список устаревших элементов можно так
```go
items := ExpiredList()
```
### Получение количества элементов
Для получения количества элементов в кэше используйте метод **Count**:
```go
count := cache.Count() // Количество элементов в кэше
```
### Получение размера кэша
Для получения размера всего кэша в байтах используйте метод **Size**:
```go
size := cache.Size() // Размер кэша в байтах
```
Данный метод возвращает корректное значение, если в кэше элементы представлены этими типами данных:
```go
bool
int, int8, int16, int32, int64
uint, uint8, uint16, uint32, uint64, uintptr
float32, float64
complex64, complex128
array, slice, string
map, struct, func
```
**И композициями этих типов**.
В противном случае значение может быть не точным.
## Работа с дампами
В модуле присутствуют методы **Save** и **Load**, позволяющие создавать и загружать дампы. Эти методы удовлетворяют интерфейсам **io.Writer** и **io.Reader** соответственно, т.е. их можно использовать и для работы с файлами, и для работы с буфферами.
### Сценарий 1
```go
type Person struct {
Name string
Age int
Hobbies []string
}
cache := candycache.Cacher(10 * time.Minute) // Создаем кэш с интервалом очистки 10 минут
cache.Set("key1", "string", 5*time.Minute)
cache.Set("key2", 2, 10*time.Minute)
cache.Set("key7", -2.1231, 10*time.Minute)
cache.Set("key3", []string{"string1", "string2"}, 10*time.Minute)
cache.Set("key4", map[string]int{"a": 1, "b": 2}, 10*time.Minute)
cache.Set("key5", Person{Name: "Alice", Age: 30, Hobbies: []string{"reading", "swimming"}}, 10*time.Minute)
cache.Set("key6", []Person{
{Name: "Bob", Age: 25, Hobbies: []string{"coding", "gaming"}},
{Name: "Charlie", Age: 35, Hobbies: []string{"hiking", "photography"}},
}, 10*time.Minute)
file, err := os.Create("cache_dump.json")
if err != nil {
log.Fatal("error creating file: ", err)
}
if err := cache.Save(file); err != nil { // Сохранение кэша в файл
log.Fatal("error saving cache: ", err)
}
file.Close()
cache.Flush() // Удаление всех элементов из кэша
file, err = os.Open("cache_dump.json")
if err != nil {
log.Fatal("error opening file: ", err)
}
if err := cache.Load(file); err != nil { // Загрузка кэша из файла
fmt.Println("error load cache:", err)
}
list := cache.List() // Получаю список элементов кэша
for _, i := range list {
fmt.Println(i.Key, i.Item.Data(), i.Item.DestroyTimestamp())
}
```
### Сценарий 2
```go
type Person struct {
Name string
Age int
Hobbies []string
}
cache := candycache.Cacher(10 * time.Minute) // Создаем кэш с интервалом очистки 10 минут
cache.Set("key1", "string", 5*time.Minute)
cache.Set("key2", 2, 10*time.Minute)
cache.Set("key7", -2.1231, 10*time.Minute)
cache.Set("key3", []string{"string1", "string2"}, 10*time.Minute)
cache.Set("key4", map[string]int{"a": 1, "b": 2}, 10*time.Minute)
cache.Set("key5", Person{Name: "Alice", Age: 30, Hobbies: []string{"reading", "swimming"}}, 10*time.Minute)
cache.Set("key6", []Person{
{Name: "Bob", Age: 25, Hobbies: []string{"coding", "gaming"}},
{Name: "Charlie", Age: 35, Hobbies: []string{"hiking", "photography"}},
}, 10*time.Minute)
var buffer bytes.Buffer
if err := cache.Save(&buffer); err != nil { // Сохранение бэкапа
log.Fatal("error saving cache: ", err)
}
cache.Set("key1", "lost", -1)
cache.Set("key2", "lost", -1)
cache.Set("key3", "lost", -1)
cache.Set("key4", "lost", -1)
cache.Set("key5", "lost", -1)
cache.Set("key6", "lost", -1)
cache.Set("key7", "lost", -1)
if err := cache.Load(&buffer); err != nil { // Восстановление бэкапа
log.Fatal("error loading cache: ", err)
}
list := cache.List() // Получаю список элементов кэша
for _, i := range list {
fmt.Println(i.Key, i.Item.Data(), i.Item.DestroyTimestamp())
}
```