BadgerKV is a Go library that provides a standardized key-value store interface built on top of BadgerDB. It implements the github.com/bborbe/kv interface, offering a clean and consistent API for database operations including transactions, buckets, and key-value operations.
- Standardized Interface: Implements the
github.com/bborbe/kvinterface for consistent database operations - Transaction Support: Full ACID transaction support with automatic rollback on errors
- Bucket-based Organization: Organize data into logical buckets within transactions
- Memory & Disk Storage: Support for both file-based and in-memory databases
- Iterator Support: Forward and reverse iteration over bucket contents
- Context-aware: Full context support for cancellation and deadlines
- Thread-safe: Safe for concurrent use across multiple goroutines
go get github.com/bborbe/badgerkvpackage main
import (
"context"
"log"
"github.com/bborbe/badgerkv"
)
func main() {
ctx := context.Background()
// Open a file-based database
db, err := badgerkv.OpenPath(ctx, "/tmp/mydb")
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Start a transaction
err = db.Update(ctx, func(ctx context.Context, tx badgerkv.Tx) error {
// Get or create a bucket
bucket, err := tx.CreateBucketIfNotExists([]byte("users"))
if err != nil {
return err
}
// Store a key-value pair
return bucket.Put([]byte("user:1"), []byte(`{"name": "John", "age": 30}`))
})
if err != nil {
log.Fatal(err)
}
// Read data
err = db.View(ctx, func(ctx context.Context, tx badgerkv.Tx) error {
bucket := tx.Bucket([]byte("users"))
if bucket == nil {
return nil // bucket doesn't exist
}
value, err := bucket.Get([]byte("user:1"))
if err != nil {
return err
}
log.Printf("User data: %s", value)
return nil
})
if err != nil {
log.Fatal(err)
}
}// Create an in-memory database (useful for testing)
db, err := badgerkv.OpenMemory(ctx)
if err != nil {
log.Fatal(err)
}
defer db.Close()// Use minimal memory settings for resource-constrained environments
db, err := badgerkv.OpenPath(ctx, "/tmp/mydb", badgerkv.MinMemoryUsageOptions)
if err != nil {
log.Fatal(err)
}
defer db.Close()err = db.View(ctx, func(ctx context.Context, tx badgerkv.Tx) error {
bucket := tx.Bucket([]byte("users"))
if bucket == nil {
return nil
}
// Forward iteration
iter := bucket.Iterator()
defer iter.Close()
for iter.First(); iter.Valid(); iter.Next() {
key := iter.Key().Data()
value := iter.Item().Value()
log.Printf("Key: %s, Value: %s", key, value)
}
return nil
})import "github.com/dgraph-io/badger/v4"
// Define custom options
customOptions := func(opts *badger.Options) {
opts.Logger = nil // Disable logging
opts.SyncWrites = true // Force sync on writes
}
db, err := badgerkv.OpenPath(ctx, "/tmp/mydb", customOptions)OpenPath(ctx, path, ...options)- Open file-based databaseOpenMemory(ctx, ...options)- Open in-memory databaseDB.View(ctx, fn)- Read-only transactionDB.Update(ctx, fn)- Read-write transactionDB.Close()- Close database
Tx.Bucket(name)- Get existing bucketTx.CreateBucket(name)- Create new bucket (fails if exists)Tx.CreateBucketIfNotExists(name)- Get or create bucketTx.DeleteBucket(name)- Delete bucket and all contents
Bucket.Get(key)- Retrieve value by keyBucket.Put(key, value)- Store key-value pairBucket.Delete(key)- Delete keyBucket.Iterator()- Create iterator for bucket contents
Iterator.First()- Move to first itemIterator.Last()- Move to last itemIterator.Next()- Move to next itemIterator.Prev()- Move to previous itemIterator.Valid()- Check if iterator position is validIterator.Key()- Get current keyIterator.Item()- Get current item
BadgerKV prevents nested transactions by tracking transaction state in the context. Use IsTransactionOpen(ctx) to check if a transaction is already active.
if badgerkv.IsTransactionOpen(ctx) {
// Already in a transaction, cannot start nested transaction
return errors.New("nested transactions not supported")
}BadgerKV uses the github.com/bborbe/errors package for enhanced error handling with context preservation:
err = db.Update(ctx, func(ctx context.Context, tx badgerkv.Tx) error {
bucket, err := tx.CreateBucket([]byte("test"))
if err != nil {
return errors.Wrapf(ctx, err, "create bucket failed")
}
return bucket.Put([]byte("key"), []byte("value"))
})
if err != nil {
log.Printf("Transaction failed: %v", err)
}BadgerKV is thoroughly tested using Ginkgo v2 and Gomega:
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run specific test
go test -run TestSpecificFunction ./...- BadgerDB v4: High-performance key-value database
- github.com/bborbe/kv: Common key-value interface
- github.com/bborbe/errors: Enhanced error handling
- github.com/bborbe/collection: Utility functions
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Run
make precommitto ensure code quality - Submit a pull request
This project is licensed under the BSD-style license. See the LICENSE file for details.