代码拉取完成,页面将自动刷新
/*
* 大量同类数据,每一条对应一个文件。
* 多用于记录数量频繁变动、单条记录不可变的数据。
* 例如用于重试的失败网络请求等。
*/
package filedb
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync"
)
type List[T any] struct {
Dirpath string // 文件目录
Prefix string // 文件前缀,和每一条数据ID直接拼接
Perm os.FileMode // 文件权限,默认0644
BatchCount int // 读取文件列表时批量数量,默认为1000
lock sync.RWMutex // 读写锁
}
// 新建一个文件存储
func NewList[T any](dirpath string, prefix string) *List[T] {
t := new(List[T])
t.Dirpath = dirpath
t.Prefix = prefix
t.Perm = 0644
t.BatchCount = 1000
t.lock = sync.RWMutex{}
return t
}
// 读取ID列表,不包含Prefix
func (t *List[T]) GetAllId() (idList []string, err error) {
t.lock.RLock()
defer t.lock.RUnlock()
dirFile, err := os.Open(t.Dirpath)
if err != nil {
return
}
defer dirFile.Close()
for {
files, e := dirFile.Readdir(t.BatchCount)
if e != nil {
if e != io.EOF {
err = e
}
return
}
for _, item := range files {
filename := item.Name()
if strings.HasPrefix(filename, t.Prefix) {
idList = append(idList, filename[len(t.Prefix):])
}
}
}
}
// 读取单个数据内容
func (t *List[T]) GetItem(dataId string) (data T, err error) {
t.lock.RLock()
defer t.lock.RUnlock()
fp := t.fullFilepath(dataId)
content, err := os.ReadFile(fp)
if err != nil {
return
}
if err = json.Unmarshal(content, &data); err != nil {
return
}
return
}
// 写入新的数据内容
func (t *List[T]) AddItem(dataId string, data T) (err error) {
_, isExist, err := t.IsExist(dataId)
if err != nil {
return
}
if isExist {
err = fmt.Errorf("数据%s已存在", dataId)
return
}
t.lock.Lock()
defer t.lock.Unlock()
content, err := json.Marshal(data)
if err != nil {
return
}
fp := t.fullFilepath(dataId)
if err = os.WriteFile(fp, content, t.Perm); err != nil {
return
}
return
}
// 删除数据内容
func (t *List[T]) RemoveItem(dataId string) (err error) {
t.lock.Lock()
defer t.lock.Unlock()
fp := t.fullFilepath(dataId)
if err = os.RemoveAll(fp); err != nil {
return
}
return
}
// 判断数据ID是否已经存在
func (t *List[T]) IsExist(dataId string) (isFile bool, isExist bool, err error) {
fp := t.fullFilepath(dataId)
info, e := os.Stat(fp)
if e != nil {
if os.IsNotExist(e) {
isExist = false
} else {
err = e
}
return
}
isExist = true
isFile = !info.IsDir()
return
}
// 文件路径拼接
func (t *List[T]) fullFilepath(dataId string) string {
return filepath.Join(t.Dirpath, t.Prefix+dataId)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。