增加boltdb工具

main
cc 2024-07-20 17:53:07 +00:00
parent 4b754a0164
commit e5186c503d
6 changed files with 380 additions and 5 deletions

343
db/boltdb/boltdb.go Normal file
View File

@ -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
}

22
db/boltdb/config.go Normal file
View File

@ -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
View File

@ -3,8 +3,12 @@ module git.shikicc.com/golang/kit
go 1.21.4
require (
go.etcd.io/bbolt v1.3.10
go.uber.org/zap v1.26.0
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
View File

@ -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/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
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/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
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/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
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/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -17,7 +17,7 @@ type LogFileConfig struct {
FileAge_DAY int // 日志文件保留天数
}
type ZapConfig struct {
type Config struct {
JsonFormat bool // 是否使用json格式,默认false
Mode int8 // 日志启用级别
DebugLog LogFileConfig // Debug日志配置
@ -27,7 +27,7 @@ type ZapConfig struct {
FatalLog LogFileConfig // Fatal日志配置
}
var cfg_default = ZapConfig{
var cfg_default = Config{
DebugLog: LogFileConfig{
Filename: "./log/debug",
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 {
return cfg_default
}

View File

@ -33,7 +33,7 @@ func jsonencoderConfig() zapcore.EncoderConfig {
return encoderConfig
}
func New(config ...ZapConfig) *zap.SugaredLogger {
func New(config ...Config) *zap.SugaredLogger {
cfg := configDefault(config...)
var encoder zapcore.Encoder