boltdb/bolt 是一个纯 Go 实现的嵌入式键值数据库,旨在提供简洁、高效、可靠的数据存储方案。它使用 B+ 树数据结构进行存储,并且支持 ACID 事务。


项目介绍

项目名称:Bolt


GitHub 仓库:boltdb/bolt

描述:Bolt 是一个高性能的嵌入式键值数据库,用于 Go 语言应用程序。它特别适合需要将数据存储在文件中的场景。


特性

嵌入式:无需单独的服务器进程,直接嵌入到 Go 应用程序中。

高性能:使用内存映射文件(mmap)实现快速读写操作。

事务支持:支持完全的 ACID 事务,包括嵌套事务。

简单易用:API 简洁明了,容易上手。

持久化:数据持久化存储在磁盘文件中。


安装方法

你可以使用 go get 命令来安装 Bolt:

go get go.etcd.io/bbolt

注意:原始的 boltdb/bolt 项目已经被封存,推荐使用社区维护的 etcd-io/bbolt。


使用示例

以下是一些简单的示例代码,展示如何在你的 Go 项目中使用 Bolt。


打开或创建数据库


package main

import (
    "log"
    "go.etcd.io/bbolt"
)

func main() {
    // 打开数据库文件,如果不存在则创建
    db, err := bbolt.Open("mydb.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
}

创建和更新桶(Bucket)


package main

import (
    "log"
    "go.etcd.io/bbolt"
)

func main() {
    db, err := bbolt.Open("mydb.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // 开启读写事务
    err = db.Update(func(tx *bbolt.Tx) error {
        // 创建一个名为 "MyBucket" 的桶
        _, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }
}

插入和读取数据


package main

import (
    "fmt"
    "log"
    "go.etcd.io/bbolt"
)

func main() {
    db, err := bbolt.Open("mydb.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // 插入数据
    err = db.Update(func(tx *bbolt.Tx) error {
        bucket := tx.Bucket([]byte("MyBucket"))
        if bucket == nil {
            return fmt.Errorf("Bucket not found")
        }
        // 插入 key-value 对
        err := bucket.Put([]byte("key1"), []byte("value1"))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }

    // 读取数据
    err = db.View(func(tx *bbolt.Tx) error {
        bucket := tx.Bucket([]byte("MyBucket"))
        if bucket == nil {
            return fmt.Errorf("Bucket not found")
        }
        // 获取 value
        value := bucket.Get([]byte("key1"))
        fmt.Printf("key1: %s\n", value)
        return nil
    })
    if err != nil {
        log.Fatal(err)
    }
}

删除数据


package main

import (
    "log"
    "go.etcd.io/bbolt"
)

func main() {
    db, err := bbolt.Open("mydb.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // 删除数据
    err = db.Update(func(tx *bbolt.Tx) error {
        bucket := tx.Bucket([]byte("MyBucket"))
        if bucket == nil {
            return fmt.Errorf("Bucket not found")
        }
        // 删除 key-value 对
        err := bucket.Delete([]byte("key1"))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }
}

高级用法

使用嵌套桶(Nested Buckets)


package main

import (
    "log"
    "go.etcd.io/bbolt"
)

func main() {
    db, err := bbolt.Open("mydb.db", 0600, nil)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // 创建嵌套桶
    err = db.Update(func(tx *bbolt.Tx) error {
        bucket, err := tx.CreateBucketIfNotExists([]byte("ParentBucket"))
        if err != nil {
            return err
        }
        _, err = bucket.CreateBucketIfNotExists([]byte("ChildBucket"))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }

    // 插入数据到嵌套桶
    err = db.Update(func(tx *bbolt.Tx) error {
        parentBucket := tx.Bucket([]byte("ParentBucket"))
        if parentBucket == nil {
            return fmt.Errorf("ParentBucket not found")
        }
        childBucket := parentBucket.Bucket([]byte("ChildBucket"))
        if childBucket == nil {
            return fmt.Errorf("ChildBucket not found")
        }
        // 插入 key-value 对
        err := childBucket.Put([]byte("nestedKey"), []byte("nestedValue"))
        return err
    })
    if err != nil {
        log.Fatal(err)
    }

    // 读取嵌套桶中的数据
    err = db.View(func(tx *bbolt.Tx) error {
        parentBucket := tx.Bucket([]byte("ParentBucket"))
        if parentBucket == nil {
            return fmt.Errorf("ParentBucket not found")
        }
        childBucket := parentBucket.Bucket([]byte("ChildBucket"))
        if childBucket == nil {
            return fmt.Errorf("ChildBucket not found")
        }
        // 获取 value
        value := childBucket.Get([]byte("nestedKey"))
        log.Printf("nestedKey: %s\n", value)
        return nil
    })
    if err != nil {
        log.Fatal(err)
    }
}

结论

boltdb/bolt 是一个功能强大且易于使用的嵌入式键值数据库,非常适合需要高效、可靠数据存储的 Go 应用程序。

通过上述示例,应该能够快速上手并集成 Bolt 到你的项目中。