在Web服务器应用程序Golang中使用键值存储

I tried to get a simple key value store working inside of a go webserver app, which should store some information.

The issue is, I can only create one instance of it, since its writing to the disk and the folder is locked, so I need to find away to access the key value store with my Webserver.

So every current instance can access it (read/write). How do I do that?

Currently My app looks like that: https://play.golang.org/p/_SmGBZlP0Vi The Package I wanted to use is this: https://github.com/peterbourgon/diskv

Basically I would create an instance before the main and pass the instance of the key value store, to the rtt function, but that seems not directly be possible in go. Or do I something wrong?

Global Conn Instance

First create a package with a single instance of the key value store and make the connection a package variable that you connect once and then keep open for all future use. Here some pseudo code sample:

package kvstore

var conn *diskv.Conn // or whatever the type of the conn is

func Connect(...) {
    // crate connection and fill conn
    conn = diskv.New(...)
}

func Write(k, v []byte) error {
    return conn.Write(k, v)
}

That way yo have a "global" connection that can be used from everywhere. Simply call kvstore.Write(...) anywhere to write to the store.

Sync concurrent access

If your application uses multiple goroutines that can access the kvstore you (might -- depending if the package you use already does this for you or not) need to sync the access. You can do this by using a mutex for the connection:

var (
    conn *diskv.Conn // or whatever the type of the conn is
    mutex sync.Mutex
)

func Write(k, v []byte) error {
    // everywhere you use the conn object, lock the mutex before and unlock after
    mutex.Lock()
    defer mutex.Unlock()
    return conn.Write(k, v)
}

You can also use the actor pattern. Here a post by Peter Bourgon that explains the actor pattern. With the actor pattern we can make sure the conn object is only used in one goroutine making the use of a mutex unnecessary.

Simple kvstore package implementation

package kvstore

import "github.com/peterbourgon/diskv"

var conn *diskv.Diskv

// Connect opens the global diskv db
func Connect(dir string) {
    flatTransform := func(s string) []string { return []string{} }

    conn = diskv.New(diskv.Options{
        BasePath:     dir,
        Transform:    flatTransform,
        CacheSizeMax: 1024 * 1024,
    })
}

// Write writes to the global diskv db
func Write(k string, v []byte) error {
    return conn.Write(k, v)
}

// Read reads from the global diskv db
func Read(k string) ([]byte, error) {
    return conn.Read(k)
}

// Erase deletes a key from the global discv db
func Erase(k string) error {
    return conn.Erase(k)
}

Sample usage of kvstore

package main

import (
    "github.com/tehsphinx/diskv"
)

func main() {
    // call this once in startup sequence.
    kvstore.Connect("my-data-dir")

    // use this anywhere to write to key value store
    kvstore.Write("alpha", []byte{'1', '2', '2'})

    // use this anywhere to read from kvstore
    kvstore.Read("alpha")

    // use this anywhere to delete from kvstore
    kvstore.Erase("alpha")
}

Just copy it in two different folders and try. It works.