golang 每日一庫之磁盤鍵值存儲 diskv
diskv
你有沒有想過,在某些時候,內存不是萬能的——比如你要存的東西多得像個大水庫,又或者你就想放心大膽地關掉程序然後下班回家。
而這時你需要一個靠譜的、基於磁盤的鍵值存儲庫。
所以你用 sqlite 嗎?筆者第一想法就是 sqlite.
來,認識一下主角:diskv,一個簡單、強大、零依賴、沒有數據庫暴脾氣的 Go 鍵值存儲庫。
它的核心理念很簡單:用磁盤做字典,鍵是路徑,值是文件內容。
設計哲學
diskv 的名字是 “disk + kv”,直白得就像 Go 語言本身。它的目標很明確:
-
簡單易用:
把鍵映射成磁盤路徑,把值寫成文件。
-
結構清晰:
支持目錄分層來避免單個目錄下文件爆炸。
-
無額外依賴:
不依賴數據庫,不依賴 SQLite,不依賴 RocksDB,不依賴你凌晨修不好的 Redis。
-
純 Go 實現:
Go 項目想引個庫?那必須是 native Go,diskv 完美契合。
介紹
1. 存儲結構
每個 key 會被轉換爲一個磁盤路徑,然後你寫進去的 value 就直接保存成那個路徑對應的文件。
比如,key = "foo-bar",value = "hello":
d.Write("foo-bar", []byte("hello"))
會寫入路徑類似於:
/your-base-dir/f/o/o-bar
你沒看錯,這個 f/o/o-bar 是它通過默認分區函數生成的路徑——把 key 的前幾個字符拆成路徑分級,防止某個目錄裏全是幾百萬個文件。
2. 使用示例
import (
"github.com/peterbourgon/diskv"
)
func main() {
d := diskv.New(diskv.Options{
BasePath: "my-diskv-data",
Transform: diskv.IdentityTransform,
CacheSizeMax: 1024 * 1024,
})
key := "greeting"
value := []byte("hello world")
err := d.Write(key, value)
if err != nil {
panic(err)
}
readValue, err := d.Read(key)
fmt.Println(string(readValue)) // hello world
}
是不是比自己手擼 os.OpenFile+filepath.Join+panic(err) 來得輕鬆優雅得多?
- 常用 API
可定製化
diskv 支持定製以下內容:
-
Transform: key -> path 的轉換方式。
-
InverseTransform: path -> key 的逆轉換方式。
-
Compression: 你可以自定義壓縮方式(比如 value 寫進去前 gzip 一下)。
-
Logger: 如果你想知道它幹了什麼,可以指定一個日誌輸出器。
-
CacheSizeMax: 它還有個小緩存,不然每次都去磁盤裏讀也太沒效率了。
使用場景
-
CLI 工具的配置緩存,比如你的命令行記住上次的狀態。
-
臨時數據持久化,程序意外掛掉也不怕。
-
離線 / 嵌入式場景:沒有數據庫?沒問題。
-
存日誌、短文檔、圖片(?)——只要是 byte slice,統統都可以寫進去!
不適用的場景
diskv 雖然穩定可靠,但它不是萬能鑰匙:
-
併發寫太猛?它不是事務型數據庫,不適合重併發複雜操作。
-
查詢 key 的前綴還行,但你要複雜的查詢和排序?別想了,用數據庫去吧。
-
內存緩存能力有限——不是 Redis,不求秒迴響應。
總結
你可以把 diskv 看作是你家 “會把東西分類擺放” 的存儲小助手:
-
它不會花裏胡哨,但特別實用;
-
它的 API 樸實無華,但清晰直接;
-
它是你 Go 項目裏輕量級持久化的靠譜選擇。
這個庫其實挺實用的,特別是在寫很小的外包項目時。
當然你也有別的選擇,比如 sqlite。
但是這個庫是不是也給了你啓發,哦,原來還可以這樣。
標題:golang 每日一庫之磁盤鍵值存儲 diskv
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/07/14/1752456464335.html
聯繫:scotttu@163.com
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/J8hgdxVz_LRvNheXMGBOfA