unified key-value storage for go.
keys are normalized: colons become slashes, uppercase becomes lowercase, so
user:aliceandUSER/Aliceboth end up asuser/alice.
you can plug in different backends through a common interface:
- memory — everything stays in ram, gone when the program exits
- fs — each key is a file on disk, metadata lives in sidecar json files
- dlht — backed by a concurrent hash map
- http — talks to a remote storage server over http
import "codeberg.org/ungo/storage"
import "codeberg.org/ungo/storage/drivers/memory"
s := storage.New(memory.New())
// store and retrieve typed values (json in/out)
s.SetItem(ctx, "users/1", User{Name: "alice"})
var u User
s.GetItem(ctx, "users/1", &u)
// or store raw bytes
s.SetRaw(ctx, "images/icon.png", pngBytes)
data, _ := s.GetRaw(ctx, "images/icon.png")you can mount multiple backends under key prefixes. lookups go through mounts in reverse order (last mount wins):
s := storage.New(memory.New())
s.Mount("files", fs.New("./data"))
s.Mount("cache", memory.New())
s.SetRaw(ctx, "files/doc.txt", content) // goes to fs driver
s.SetRaw(ctx, "cache/temp.json", data) // goes to memory driver
s.SetRaw(ctx, "settings.json", cfg) // goes to root memory driverbackends that support it can notify you of changes in real time:
events, _ := s.Watch(ctx, "")
for e := range events {
// e.event is "update" or "remove", e.key is the changed key
}export and re-import all data for backups or migration:
snap, _ := s.Snapshot(ctx, "")
fresh := storage.New(memory.New())
fresh.Hydrate(ctx, snap)the server package exposes a storage over http with rest endpoints and real-time updates via server-sent events:
s := storage.New(memory.New())
srv := server.New(s, server.Options{})
http.ListenAndServe(":8080", srv.Handler())then use the http driver from any client:
client := storage.New(httpdriver.New(httpdriver.Options{
Base: "http://localhost:8080",
}))| driver | import path | description |
|---|---|---|
| memory | drivers/memory |
in-memory map, fast, ephemeral |
| fs | drivers/fs |
filesystem-backed, persistent |
| dlht | drivers/dlht |
concurrent hash map backend |
| http | drivers/http |
remote storage via http |
you can implement custom drivers using the Driver interface anyways.
see _examples/ for runnable code.