go语言中文文档:www.topgoer.com
转载:https://studygolang.com/articles/27391#reply0
buntdbbuntdb感谢@kiyonlin推荐!
快速使用先安装:
$ go get github.com/tidwall/buntdb后使用:
package main
import (
"fmt"
"log"
"github.com/tidwall/buntdb"
)
func main() {
db, err := buntdb.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.Update(func(tx *buntdb.Tx) error {
oldValue, replaced, err := tx.Set("testkey", "testvalue", nil)
if err != nil {
return err
}
fmt.Printf("old value:%q replaced:%t\n", oldValue, replaced)
return nil
})
db.View(func(tx *buntdb.Tx) error {
value, err := tx.Get("testkey")
if err != nil {
return err
}
fmt.Println("value is:", value)
return nil
})
}buntdbsqlitebuntdbbuntdb.Open():memory:buntdbbuntdbdb.View()func (tx *buntdb.Tx) errordb.View()txtxtxGet()db.View(func(tx *buntdb.Tx) error {
value, err := tx.Get("testkey")
if err != nil {
return err
}
fmt.Println("value is:", value)
return nil
})db.Update()func (tx *buntdb.Tx) errortxSettx.Set()Set()truedb.Update()如果运行两次上面的程序,我们会看到下面的输出:
// 第一次运行
$ go run main.go
old value:"" replaced:false
value is: testvalue
// 第二次运行
$ go run main.go
old value:"testvalue" replaced:true
value is: testvalue注意:
db.View()db.Update()dbErrNotFound遍历buntdbdb.View()buntdbAscend()func (tx *Tx) Ascend(index string, iterator func(key, value string) bool) errorAscend()iteratoriteratorfalsefunc main() {
db, err := buntdb.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.Update(func(tx *buntdb.Tx) error {
data := map[string]string{
"a": "apple",
"b": "banana",
"p": "pear",
"o": "orange",
}
for key, value := range data {
tx.Set(key, value, nil)
}
return nil
})
db.View(func(tx *buntdb.Tx) error {
var count int
tx.Ascend("", func(key, value string) bool {
fmt.Printf("key:%s value:%s\n", key, value)
count++
if count >= 3 {
return false
}
return true
})
return nil
})
}""iteratorfalsekey:a value:apple
key:b value:banana
key:o value:orange索引buntdbdb.CreateIndex()func (db *DB) CreateIndex(name, pattern string, less ...func(a, b string) bool) errornamepattern*user:*:nameuser::namelessbuntdbIndexStringIndexInt/IndexUint/IndexFloatfunc main() {
db, err := buntdb.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.CreateIndex("names", "user:*:name", buntdb.IndexString)
db.Update(func(tx *buntdb.Tx) error {
tx.Set("user:1:name", "tom", nil)
tx.Set("user:2:name", "Randi", nil)
tx.Set("user:3:name", "jane", nil)
tx.Set("user:4:name", "Janet", nil)
tx.Set("user:5:name", "Paula", nil)
tx.Set("user:6:name", "peter", nil)
tx.Set("user:7:name", "Terri", nil)
return nil
})
db.View(func(tx *buntdb.Tx) error {
tx.Ascend("names", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
return nil
})
}user:*:namenamesbuntdb.IndexStringbuntdbAscend()namesuser:*:nameuser:*:name*user:*buntdbfunc main() {
db, err := buntdb.Open(":memory:")
if err != nil {
log.Fatal(err)
}
defer db.Close()
db.CreateIndex("ages", "user:*:age", buntdb.IndexInt)
db.Update(func(tx *buntdb.Tx) error {
tx.Set("user:1:age", "16", nil)
tx.Set("user:2:age", "35", nil)
tx.Set("user:3:age", "24", nil)
tx.Set("user:4:age", "32", nil)
tx.Set("user:5:age", "25", nil)
tx.Set("user:6:age", "28", nil)
tx.Set("user:7:age", "31", nil)
return nil
})
db.View(func(tx *buntdb.Tx) error {
tx.Ascend("ages", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
return nil
})
}user:*:ageagesIndexIntJSON 索引buntdbbuntdbbuntdb.IndexJSON()name.firstcontact.emailfunc main() {
db, _ := buntdb.Open(":memory:")
defer db.Close()
db.CreateIndex("first_name", "user:*", buntdb.IndexJSON("name.first"))
db.CreateIndex("age", "user:*", buntdb.IndexJSON("age"))
db.Update(func(tx *buntdb.Tx) error {
tx.Set("user:1", `{"name":{"first":"zhang","last":"san"},"age":18}`, nil)
tx.Set("user:2", `{"name":{"first":"li","last":"si"},"age":27`, nil)
tx.Set("user:3", `{"name":{"first":"wang","last":"wu"},"age":32}`, nil)
tx.Set("user:4", `{"name":{"first":"sun","last":"qi"},"age":8}`, nil)
return nil
})
db.View(func(tx *buntdb.Tx) error {
fmt.Println("Order by first name")
tx.Ascend("first_name", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
fmt.Println("Order by age")
tx.Ascend("age", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
fmt.Println("Order by age range 18-30")
tx.AscendRange("age", `{"age":18}`, `{"age":30}`, func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
return nil
})
}user:name.firstagename.firstageAscendRangeAscendAscendRangeminmax[min, max)max多重索引CreateIndex()first_nameagename.firstagefunc main() {
db, _ := buntdb.Open(":memory:")
defer db.Close()
db.CreateIndex("first_name_age", "user:*", buntdb.IndexJSON("name.first"), buntdb.IndexJSON("age"))
db.Update(func(tx *buntdb.Tx) error {
tx.Set("user:1", `{"name":{"first":"zhang","last":"san"},"age":18}`, nil)
tx.Set("user:2", `{"name":{"first":"li","last":"si"},"age":27`, nil)
tx.Set("user:3", `{"name":{"first":"wang","last":"wu"},"age":30}`, nil)
tx.Set("user:4", `{"name":{"first":"sun","last":"qi"},"age":8}`, nil)
tx.Set("user:5", `{"name":{"first":"li", "name":"dajun"},"age":20}`, nil)
return nil
})
db.View(func(tx *buntdb.Tx) error {
tx.Ascend("first_name_age", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
return nil
})
}user:2user:5name.firstliageuser:5user:2降序buntdb.Desc()buntdb.IndexIntbuntdb.Desc(buntdb.IndexInt)func main() {
db, _ := buntdb.Open(":memory:")
defer db.Close()
db.CreateIndex("ages", "user:*:age", buntdb.Desc(buntdb.IndexInt))
db.Update(func(tx *buntdb.Tx) error {
tx.Set("user:1:age", "16", nil)
tx.Set("user:2:age", "35", nil)
tx.Set("user:3:age", "24", nil)
tx.Set("user:4:age", "32", nil)
tx.Set("user:5:age", "25", nil)
tx.Set("user:6:age", "28", nil)
tx.Set("user:7:age", "31", nil)
return nil
})
db.View(func(tx *buntdb.Tx) error {
tx.Ascend("ages", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
return nil
})
}过期buntdbbuntdb.SetOptionsbuntdbnilfunc main() {
db, _ := buntdb.Open(":memory:")
defer db.Close()
db.Update(func(tx *buntdb.Tx) error {
tx.Set("testkey", "testvalue", &buntdb.SetOptions{Expires: true, TTL: time.Second})
return nil
})
db.View(func(tx *buntdb.Tx) error {
value, _ := tx.Get("testkey")
fmt.Println("value is:", value)
return nil
})
time.Sleep(time.Second)
db.View(func(tx *buntdb.Tx) error {
value, _ := tx.Get("testkey")
fmt.Println("value is:", value)
return nil
})
}1sSleepvalue is: testvalue
value is: 杂项遍历时删除buntdbfunc main() {
db, _ := buntdb.Open(":memory:")
defer db.Close()
db.Update(func(tx *buntdb.Tx) error {
tx.Set("user:1:age", "16", nil)
tx.Set("user:2:age", "35", nil)
tx.Set("user:3:age", "24", nil)
tx.Set("user:4:age", "32", nil)
tx.Set("user:5:age", "25", nil)
tx.Set("user:6:age", "28", nil)
tx.Set("user:7:age", "31", nil)
return nil
})
db.Update(func(tx *buntdb.Tx) error {
// 先汇总
deleteKeys := make([]string, 0)
tx.Ascend("", func(key, value string) bool {
age, _ := strconv.ParseUint(value, 10, 64)
if age >= 30 {
deleteKeys = append(deleteKeys, key)
}
return true
})
// 再删除
for _, key := range deleteKeys {
tx.Delete(key)
}
return nil
})
db.View(func(tx *buntdb.Tx) error {
tx.Ascend("", func(key, value string) bool {
fmt.Printf("%s: %s\n", key, value)
return true
})
return nil
})
}Web 服务buntdbbuntdbpackage main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"time"
"github.com/tidwall/buntdb"
)
var db *buntdb.DB
func init() {
var err error
db, err = buntdb.Open("data.db")
if err != nil {
log.Fatal(err)
}
}
func response(w http.ResponseWriter, err error, data interface{}) {
bytes, _ := json.Marshal(map[string]interface{}{
"error": err,
"data": data,
})
w.Write(bytes)
}
func set(w http.ResponseWriter, r *http.Request) {
key := r.FormValue("key")
value := r.FormValue("value")
expire, _ := strconv.ParseBool(r.FormValue("expire"))
ttl, _ := time.ParseDuration(r.FormValue("ttl"))
var setOption *buntdb.SetOptions
if expire && ttl > 0 {
setOption = &buntdb.SetOptions{Expires: true, TTL: ttl}
}
err := db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(key, value, setOption)
return err
})
response(w, err, nil)
}
func get(w http.ResponseWriter, r *http.Request) {
key := r.FormValue("key")
var value string
err := db.View(func(tx *buntdb.Tx) error {
var err error
value, err = tx.Get(key)
return err
})
response(w, err, value)
}
type Pair struct {
Key string
Value string
}
func iterate(w http.ResponseWriter, r *http.Request) {
index := r.FormValue("index")
fmt.Println(index)
var items []Pair
err := db.View(func(tx *buntdb.Tx) error {
err := tx.Ascend(index, func(key, value string) bool {
fmt.Println(key, value)
items = append(items, Pair{key, value})
return true
})
return err
})
response(w, err, items)
}
func createIndex(w http.ResponseWriter, r *http.Request) {
name := r.FormValue("name")
pattern := r.FormValue("pattern")
less := buntdb.IndexString
err := db.CreateIndex(name, pattern, less)
response(w, err, nil)
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/get", get)
mux.HandleFunc("/set", set)
mux.HandleFunc("/iterate", iterate)
mux.HandleFunc("/create_index", createIndex)
server := &http.Server{
Addr: ":8000",
Handler: mux,
}
if err := server.ListenAndServe(); err != nil {
log.Fatal(err)
}
}我只编写了基本读取、设置、创建索引和遍历的功能,代码并不难理解。下面我们先运行程序,然后用浏览器请求:
localhost:8000/set?key=name&value=dj{"error":null, "data":null}errornulllocalhost:8000/set?key=dj&value=18{"error":null, "data":null}localhost:8000/iterate{
"data": [
{
"Key": "age",
"Value": "18"
},
{
"Key": "name",
"Value": "dj"
}
],
"error": null
}感兴趣可以试着添加更多的功能。如果对 Go Web 编程不太了解,可以去看看我的Go Web 编程系列文章。