Skip to content

Instantly share code, notes, and snippets.

@nitishfy
Last active June 7, 2024 11:09
Show Gist options
  • Save nitishfy/3a35d3fd5912c42de98611672bc69935 to your computer and use it in GitHub Desktop.
Save nitishfy/3a35d3fd5912c42de98611672bc69935 to your computer and use it in GitHub Desktop.
Time To Live (TTL) Cache
package main
import (
"fmt"
"sync"
"time"
)
type Cache[K comparable, V any] struct {
data map[K]item[V]
mutex sync.Mutex
}
type item[V any] struct {
val V
expiryTime time.Time
}
// NewCache creates a new cache with a default time to live as 5 minutes
func NewCache[K comparable, V any]() *Cache[K, V] {
c := &Cache[K, V]{
data: make(map[K]item[V]),
}
// spin a goroutine to delete the items in the map every 5 minutes
go func() {
for range time.Tick(5 * time.Minute) {
c.mutex.Lock()
// range over map to check if any item has expired
for key, val := range c.data {
if val.isExpired() {
delete(c.data, key)
}
}
c.mutex.Unlock()
}
}()
return c
}
// isExpired checks if the item present in the cache has been expired
func (i *item[V]) isExpired() bool {
return time.Now().After(i.expiryTime)
}
// Set sets the value in the cache with key-value and time duration
func (c *Cache[K, V]) Set(key K, value V, ttl time.Duration) {
c.mutex.Lock()
defer c.mutex.Unlock()
item := item[V]{
val: value,
expiryTime: time.Now().Add(ttl),
}
c.data[key] = item
}
// Get gets the value of the key
func (c *Cache[K, V]) Get(key K) (V, bool) {
c.mutex.Lock()
defer c.mutex.Unlock()
item, found := c.data[key]
if !found {
var zeroValue V
return zeroValue, false
}
// check if item is expired
if item.isExpired() {
delete(c.data, key)
var zeroValue V
return zeroValue, false
}
return item.val, true
}
// Remove removes the item from the cache
func (c *Cache[K, V]) Remove(key K) {
c.mutex.Lock()
defer c.mutex.Unlock()
delete(c.data, key)
}
// Pop removes the item from the cache with value returned
func (c *Cache[K, V]) Pop(key K) (V, bool) {
c.mutex.Lock()
defer c.mutex.Unlock()
item, found := c.data[key]
if !found {
var zeroValue V
return zeroValue, false
}
delete(c.data, key)
if item.isExpired() {
var zeroValue V
return zeroValue, false
}
return item.val, true
}
func main() {
cache := NewCache[string, string]()
cache.Set("name", "nitish", 5*time.Second)
time.Sleep(6 * time.Second) // Ensure the item expires
val, found := cache.Get("name")
if !found {
fmt.Printf("item not found\n")
return
}
fmt.Println(val)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment