增加boltdb工具
parent
4b754a0164
commit
e5186c503d
|
@ -0,0 +1,343 @@
|
||||||
|
package boltdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrBucketInvalid = errors.New("bucket is invalid")
|
||||||
|
ErrKeyInvalid = errors.New("key is invalid")
|
||||||
|
ErrValueInvalid = errors.New("value is invalid")
|
||||||
|
ErrBucketNotFound = errors.New("bucket not found")
|
||||||
|
ErrKeyNotFound = errors.New("key not found")
|
||||||
|
ErrPrefixInvalid = errors.New("prefix is invalid")
|
||||||
|
ErrRangeStartInvalid = errors.New("range start is invalid")
|
||||||
|
ErrRangeEndInvalid = errors.New("range end is invalid")
|
||||||
|
)
|
||||||
|
|
||||||
|
type boltDB struct {
|
||||||
|
db *bolt.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(config ...Config) (db *boltDB) {
|
||||||
|
cfg := configDefault(config...)
|
||||||
|
db = &boltDB{}
|
||||||
|
db.db, _ = bolt.Open(cfg.Name, 0600, &bolt.Options{Timeout: 1 * time.Second})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取数据库地址
|
||||||
|
func (cc *boltDB) Path() (rv string) {
|
||||||
|
return cc.db.Path()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭
|
||||||
|
func (cc *boltDB) Close() (rer error) {
|
||||||
|
return cc.db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 建表
|
||||||
|
func (cc *boltDB) CreateBucket(bucketName ...string) {
|
||||||
|
if bucketName == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cc.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
for _, name := range bucketName {
|
||||||
|
if name != "" {
|
||||||
|
tx.CreateBucketIfNotExists([]byte(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删表
|
||||||
|
func (cc *boltDB) DeleteBucket(bucketName ...string) {
|
||||||
|
if bucketName == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cc.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
for _, name := range bucketName {
|
||||||
|
if name != "" {
|
||||||
|
tx.DeleteBucket([]byte(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
func (cc *boltDB) Set(bucketName, key string, value []byte) (rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrKeyInvalid
|
||||||
|
if key == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrValueInvalid
|
||||||
|
if value == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return cc.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
return b.Put([]byte(key), value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取
|
||||||
|
func (cc *boltDB) Get(bucketName, key string) (rv []byte, rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrKeyInvalid
|
||||||
|
if key == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
rv = b.Get([]byte(key))
|
||||||
|
if rv == nil {
|
||||||
|
return ErrKeyNotFound
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存在
|
||||||
|
func (cc *boltDB) Has(bucketName, key string) (ok bool) {
|
||||||
|
_, err := cc.Get(bucketName, key)
|
||||||
|
return errors.Is(err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 不存在
|
||||||
|
func (cc *boltDB) HasNot(bucketName, key string) (ok bool) {
|
||||||
|
_, err := cc.Get(bucketName, key)
|
||||||
|
return errors.Is(err, ErrKeyNotFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
func (cc *boltDB) Delete(bucketName, key string) (rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrKeyInvalid
|
||||||
|
if key == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return cc.db.Update(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
return b.Delete([]byte(key))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询所有list
|
||||||
|
func (cc *boltDB) GetList(bucketName string) (rv [][]byte, rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
return b.ForEach(func(k, v []byte) error {
|
||||||
|
rv = append(rv, v)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询所有map
|
||||||
|
func (cc *boltDB) GetMap(bucketName string) (rv map[string][]byte, rer error) {
|
||||||
|
rv = make(map[string][]byte)
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
return b.ForEach(func(k, v []byte) error {
|
||||||
|
rv[string(k)] = v
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 前缀扫描list
|
||||||
|
func (cc *boltDB) ScanPrefixList(bucketName, prefix string) (rv [][]byte, rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrPrefixInvalid
|
||||||
|
if prefix == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
for k, v := c.Seek([]byte(prefix)); k != nil && bytes.HasPrefix(k, []byte(prefix)); k, v = c.Next() {
|
||||||
|
rv = append(rv, v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 前缀扫描map
|
||||||
|
func (cc *boltDB) ScanPrefixMap(bucketName, prefix string) (rv map[string][]byte, rer error) {
|
||||||
|
rv = make(map[string][]byte)
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrPrefixInvalid
|
||||||
|
if prefix == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
for k, v := c.Seek([]byte(prefix)); k != nil && bytes.HasPrefix(k, []byte(prefix)); k, v = c.Next() {
|
||||||
|
rv[string(k)] = v
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后缀扫描list
|
||||||
|
func (cc *boltDB) ScanSuffixList(bucketName, prefix string) (rv [][]byte, rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrPrefixInvalid
|
||||||
|
if prefix == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
for k, v := c.Seek([]byte(prefix)); k != nil && bytes.HasSuffix(k, []byte(prefix)); k, v = c.Next() {
|
||||||
|
rv = append(rv, v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后缀扫描map
|
||||||
|
func (cc *boltDB) ScanSuffixMap(bucketName, prefix string) (rv map[string][]byte, rer error) {
|
||||||
|
rv = make(map[string][]byte)
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrPrefixInvalid
|
||||||
|
if prefix == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
for k, v := c.Seek([]byte(prefix)); k != nil && bytes.HasSuffix(k, []byte(prefix)); k, v = c.Next() {
|
||||||
|
rv[string(k)] = v
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 范围扫描list
|
||||||
|
func (cc *boltDB) ScanRangeList(bucketName, start, end string) (rv [][]byte, rer error) {
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrRangeStartInvalid
|
||||||
|
if start == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrRangeEndInvalid
|
||||||
|
if end == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
for k, v := c.Seek([]byte(start)); k != nil && bytes.Compare(k, []byte(end)) <= 0; k, v = c.Next() {
|
||||||
|
rv = append(rv, v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 范围扫描list
|
||||||
|
func (cc *boltDB) ScanRangeMap(bucketName, start, end string) (rv map[string][]byte, rer error) {
|
||||||
|
rv = make(map[string][]byte)
|
||||||
|
rer = ErrBucketInvalid
|
||||||
|
if bucketName == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrRangeStartInvalid
|
||||||
|
if start == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = ErrRangeEndInvalid
|
||||||
|
if end == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rer = cc.db.View(func(tx *bolt.Tx) error {
|
||||||
|
b := tx.Bucket([]byte(bucketName))
|
||||||
|
if b == nil {
|
||||||
|
return ErrBucketNotFound
|
||||||
|
}
|
||||||
|
c := b.Cursor()
|
||||||
|
for k, v := c.Seek([]byte(start)); k != nil && bytes.Compare(k, []byte(end)) <= 0; k, v = c.Next() {
|
||||||
|
rv[string(k)] = v
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package boltdb
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg_default = Config{
|
||||||
|
Name: "db.pp",
|
||||||
|
}
|
||||||
|
|
||||||
|
func configDefault(config ...Config) Config {
|
||||||
|
if len(config) < 1 {
|
||||||
|
return cfg_default
|
||||||
|
}
|
||||||
|
cfg := config[0]
|
||||||
|
|
||||||
|
if cfg.Name == "" {
|
||||||
|
cfg.Name = cfg_default.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
6
go.mod
6
go.mod
|
@ -3,8 +3,12 @@ module git.shikicc.com/golang/kit
|
||||||
go 1.21.4
|
go 1.21.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
go.etcd.io/bbolt v1.3.10
|
||||||
go.uber.org/zap v1.26.0
|
go.uber.org/zap v1.26.0
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require go.uber.org/multierr v1.10.0 // indirect
|
require (
|
||||||
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
|
golang.org/x/sys v0.4.0 // indirect
|
||||||
|
)
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -4,12 +4,18 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||||
|
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||||
|
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||||
|
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||||
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
|
@ -17,7 +17,7 @@ type LogFileConfig struct {
|
||||||
FileAge_DAY int // 日志文件保留天数
|
FileAge_DAY int // 日志文件保留天数
|
||||||
}
|
}
|
||||||
|
|
||||||
type ZapConfig struct {
|
type Config struct {
|
||||||
JsonFormat bool // 是否使用json格式,默认false
|
JsonFormat bool // 是否使用json格式,默认false
|
||||||
Mode int8 // 日志启用级别
|
Mode int8 // 日志启用级别
|
||||||
DebugLog LogFileConfig // Debug日志配置
|
DebugLog LogFileConfig // Debug日志配置
|
||||||
|
@ -27,7 +27,7 @@ type ZapConfig struct {
|
||||||
FatalLog LogFileConfig // Fatal日志配置
|
FatalLog LogFileConfig // Fatal日志配置
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg_default = ZapConfig{
|
var cfg_default = Config{
|
||||||
DebugLog: LogFileConfig{
|
DebugLog: LogFileConfig{
|
||||||
Filename: "./log/debug",
|
Filename: "./log/debug",
|
||||||
FileSize_MB: 5,
|
FileSize_MB: 5,
|
||||||
|
@ -60,7 +60,7 @@ var cfg_default = ZapConfig{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func configDefault(config ...ZapConfig) ZapConfig {
|
func configDefault(config ...Config) Config {
|
||||||
if len(config) < 1 {
|
if len(config) < 1 {
|
||||||
return cfg_default
|
return cfg_default
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ func jsonencoderConfig() zapcore.EncoderConfig {
|
||||||
return encoderConfig
|
return encoderConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config ...ZapConfig) *zap.SugaredLogger {
|
func New(config ...Config) *zap.SugaredLogger {
|
||||||
cfg := configDefault(config...)
|
cfg := configDefault(config...)
|
||||||
|
|
||||||
var encoder zapcore.Encoder
|
var encoder zapcore.Encoder
|
||||||
|
|
Loading…
Reference in New Issue