Pre-release, use with caution.
ttl
is golang package that implements time-to-live container types such that after a given
amount of time, items in the map are deleted.
- The map key can be any comparable data type, via Generics.
- Any data type can be used as a map value, via Generics.
This is a fork of the awesome github.com/jftuga/TtlMap with a few enhancements and creature-comforts:
Map
is a generic, homogeneous map type- Meaning that both key and value are determined by Generics
- Using
any
orinterface{}
as the value type will effectively emulate the original source package
- The package name is simply
ttl
, in case other TTL-enabled types seem like a good idea- For example: a slice implementation
- The syntax is a little more idiomatic
- Methods have been renamed to be more familiar to Go standard library users
Load()
andStore()
instead ofGet()
andSet()
- Code is a little safer for concurrent use (at the time of the fork) and more performant in that
use case
- Use of
sync.RWLock
so that read-heavy applications block less - Use of
atomic.Int64
for the timestamp so that it may be updated without a write lock - Addition of
ttl.Map.Range()
in place of theAll()
method- Modelled after
sync.Map.Range()
- Safe for concurrent access
- Modelled after
- Use of
- Replace internal
time.Tick()
with atime.Ticker
to prevent leakage
This project is licensed under the terms of the MIT License. It derives from previous work, also licensed under the terms of the MIT License.
Full example using many data types
Small example:
package main
import (
"fmt"
"time"
"github.com/glenvan/ttl"
)
func main() {
maxTTL := time.Duration(time.Second * 4) // a key's time to live in seconds
startSize := 3 // initial number of items in map
pruneInterval := time.Duration(time.Second * 1) // search for expired items every 'pruneInterval' seconds
refreshLastAccessOnGet := true // update item's 'lastAccessTime' on a .Get()
// any comparable data type such as int, uint64, pointers and struct types (if all field types are comparable)
// can be used as the key type, not just string
t := ttl.NewMap[string, string](maxTTL, startSize, pruneInterval, refreshLastAccessOnGet)
defer t.Close()
// populate the TtlMap
t.Store("myString", "a b c")
t.Store("int_array", "1, 2, 3")
fmt.Println("TtlMap length:", t.Length())
// display all items in TtlMap
t.Range(func(key string, value string) bool {
fmt.Printf("[%9s] %v\n", key, value)
return true
})
fmt.Println()
sleepTime := maxTTL + pruneInterval
fmt.Printf("Sleeping %v seconds, items should be 'nil' after this time\n", sleepTime)
time.Sleep(sleepTime)
v, ok := t.Load("myString")
fmt.Printf("[%9s] %v (exists: %t)\n", "myString", v, ok)
v, ok = t.Load("int_array")
fmt.Printf("[%9s] %v (exists: %t)\n", "int_array", v, ok)
fmt.Println("TtlMap length:", t.Length())
}
Output:
$ go run small.go
TtlMap length: 2
[ myString] a b c
[int_array] [1 2 3]
Sleeping 5 seconds, items should be 'nil' after this time
[ myString] <nil>
[int_array] <nil>
TtlMap length: 0
New
: initialize aTtlMap
Close
: this stops the goroutine that checks for expired items; use withdefer
Len
: return the number of items in the mapPut
: add a key/valueGet
: get the current value of the given key; returnnil
if the key is not found in the mapGetNoUpdate
: same asGet
, but do not update thelastAccess
expiration time- This ignores the
refreshLastAccessOnGet
parameter
- This ignores the
All
: returns a copy of all items in the mapDelete
: delete an item; returntrue
if the item was deleted,false
if the item was not found in the mapClear
: remove all items from the map
- Searching for expired items runs in O(n) time, where n = number of items in the
TtlMap
.- This inefficiency can be somewhat mitigated by increasing the value of the
pruneInterval
time.
- This inefficiency can be somewhat mitigated by increasing the value of the
- In most cases you want
pruneInterval > maxTTL
; otherwise expired items will stay in the map longer than expected.
- Adopted from: Map with TTL option in Go
- Answer created by: OneOfOne
- /u/skeeto: suggestions for the
New
function @zhayes
on the Go Discord: helping me with Go Generics
This program was completely developed on my own personal time, for my own personal benefit, and on my personally owned equipment.