finclip-app-manager/vendor/github.com/bluele/gcache/README.md

321 lines
5.2 KiB
Markdown

# GCache
![Test](https://github.com/bluele/gcache/workflows/Test/badge.svg)
[![GoDoc](https://godoc.org/github.com/bluele/gcache?status.svg)](https://pkg.go.dev/github.com/bluele/gcache?tab=doc)
Cache library for golang. It supports expirable Cache, LFU, LRU and ARC.
## Features
* Supports expirable Cache, LFU, LRU and ARC.
* Goroutine safe.
* Supports event handlers which evict, purge, and add entry. (Optional)
* Automatically load cache if it doesn't exists. (Optional)
## Install
```
$ go get github.com/bluele/gcache
```
## Example
### Manually set a key-value pair.
```go
package main
import (
"github.com/bluele/gcache"
"fmt"
)
func main() {
gc := gcache.New(20).
LRU().
Build()
gc.Set("key", "ok")
value, err := gc.Get("key")
if err != nil {
panic(err)
}
fmt.Println("Get:", value)
}
```
```
Get: ok
```
### Manually set a key-value pair, with an expiration time.
```go
package main
import (
"github.com/bluele/gcache"
"fmt"
"time"
)
func main() {
gc := gcache.New(20).
LRU().
Build()
gc.SetWithExpire("key", "ok", time.Second*10)
value, _ := gc.Get("key")
fmt.Println("Get:", value)
// Wait for value to expire
time.Sleep(time.Second*10)
value, err = gc.Get("key")
if err != nil {
panic(err)
}
fmt.Println("Get:", value)
}
```
```
Get: ok
// 10 seconds later, new attempt:
panic: ErrKeyNotFound
```
### Automatically load value
```go
package main
import (
"github.com/bluele/gcache"
"fmt"
)
func main() {
gc := gcache.New(20).
LRU().
LoaderFunc(func(key interface{}) (interface{}, error) {
return "ok", nil
}).
Build()
value, err := gc.Get("key")
if err != nil {
panic(err)
}
fmt.Println("Get:", value)
}
```
```
Get: ok
```
### Automatically load value with expiration
```go
package main
import (
"fmt"
"time"
"github.com/bluele/gcache"
)
func main() {
var evictCounter, loaderCounter, purgeCounter int
gc := gcache.New(20).
LRU().
LoaderExpireFunc(func(key interface{}) (interface{}, *time.Duration, error) {
loaderCounter++
expire := 1 * time.Second
return "ok", &expire, nil
}).
EvictedFunc(func(key, value interface{}) {
evictCounter++
fmt.Println("evicted key:", key)
}).
PurgeVisitorFunc(func(key, value interface{}) {
purgeCounter++
fmt.Println("purged key:", key)
}).
Build()
value, err := gc.Get("key")
if err != nil {
panic(err)
}
fmt.Println("Get:", value)
time.Sleep(1 * time.Second)
value, err = gc.Get("key")
if err != nil {
panic(err)
}
fmt.Println("Get:", value)
gc.Purge()
if loaderCounter != evictCounter+purgeCounter {
panic("bad")
}
}
```
```
Get: ok
evicted key: key
Get: ok
purged key: key
```
## Cache Algorithm
* Least-Frequently Used (LFU)
Discards the least frequently used items first.
```go
func main() {
// size: 10
gc := gcache.New(10).
LFU().
Build()
gc.Set("key", "value")
}
```
* Least Recently Used (LRU)
Discards the least recently used items first.
```go
func main() {
// size: 10
gc := gcache.New(10).
LRU().
Build()
gc.Set("key", "value")
}
```
* Adaptive Replacement Cache (ARC)
Constantly balances between LRU and LFU, to improve the combined result.
detail: http://en.wikipedia.org/wiki/Adaptive_replacement_cache
```go
func main() {
// size: 10
gc := gcache.New(10).
ARC().
Build()
gc.Set("key", "value")
}
```
* SimpleCache (Default)
SimpleCache has no clear priority for evict cache. It depends on key-value map order.
```go
func main() {
// size: 10
gc := gcache.New(10).Build()
gc.Set("key", "value")
v, err := gc.Get("key")
if err != nil {
panic(err)
}
}
```
## Loading Cache
If specified `LoaderFunc`, values are automatically loaded by the cache, and are stored in the cache until either evicted or manually invalidated.
```go
func main() {
gc := gcache.New(10).
LRU().
LoaderFunc(func(key interface{}) (interface{}, error) {
return "value", nil
}).
Build()
v, _ := gc.Get("key")
// output: "value"
fmt.Println(v)
}
```
GCache coordinates cache fills such that only one load in one process of an entire replicated set of processes populates the cache, then multiplexes the loaded value to all callers.
## Expirable cache
```go
func main() {
// LRU cache, size: 10, expiration: after a hour
gc := gcache.New(10).
LRU().
Expiration(time.Hour).
Build()
}
```
## Event handlers
### Evicted handler
Event handler for evict the entry.
```go
func main() {
gc := gcache.New(2).
EvictedFunc(func(key, value interface{}) {
fmt.Println("evicted key:", key)
}).
Build()
for i := 0; i < 3; i++ {
gc.Set(i, i*i)
}
}
```
```
evicted key: 0
```
### Added handler
Event handler for add the entry.
```go
func main() {
gc := gcache.New(2).
AddedFunc(func(key, value interface{}) {
fmt.Println("added key:", key)
}).
Build()
for i := 0; i < 3; i++ {
gc.Set(i, i*i)
}
}
```
```
added key: 0
added key: 1
added key: 2
```
# Author
**Jun Kimura**
* <http://github.com/bluele>
* <junkxdev@gmail.com>