Golang:存储/缓存要在以下http请求中提供的值

Dan*_*e B 13 caching http global-variables go

我正在编写一些Go webservices(也使用http.ListenAndServe在Go中实现web服务器).我有一个结构图,我想保留在内存中(大约数据大小为100Kb)供不同的http请求使用.

在Go中实现这一目标的最佳方法是哪种?根据您的经验,使用全局包变量或缓存系统(如memcache/groupcache)是否更好?

Kyl*_*ons 12

除了您已经收到的答案之外,还可以考虑使用接收器调整的方法值http.HandlerFunc.

如果您的数据是在流程开始之前加载的数据,您可以使用以下内容:

type Common struct {
    Data map[string]*Data
}

func NewCommon() (*Common, error) {
    // load data
    return c, err
}

func (c *Common) Root(w http.ResponseWriter, r *http.Request) {
    // handler
}

func (c *Common) Page(w http.ResponseWriter, r *http.Request) {
    // handler
}

func main() {
    common, err := NewCommon()
    if err != nil { ... }

    http.HandleFunc("/", common.Root)
    http.HandleFunc("/page", common.Page)

    http.ListenAndServe(...)
}
Run Code Online (Sandbox Code Playgroud)

如果所有Common数据都是只读的,这很好用.如果Common数据是读/写的,那么你会想要更像:

type Common struct {
    lock sync.RWMutex
    data map[string]Data // Data should probably not have any reference fields
}

func (c *Common) Get(key string) (*Data, bool) {
    c.lock.RLock()
    defer c.lock.RUnlock()
    d, ok := c.data[key]
    return &d, ok
}

func (c *Common) Set(key string, d *Data) {
    c.lock.Lock()
    defer c.lock.Unlock()
    c.data[key] = *d
}
Run Code Online (Sandbox Code Playgroud)

其余基本相同,除了直接通过接收器的字段访问数据,您可以通过getter和setter访问它们.在正在读取大部分数据的Web服务器中,您可能需要RWMutex,以便可以彼此同时执行读取.第二种方法的另一个优点是您已经封装了数据,因此如果您的应用程序需要增加,您可以在将来添加透明写入和/或读取内存缓存或组缓存或其他类似内容.

我真正喜欢将处理程序定义为对象上的方法的一件事是它可以更容易地对它们进行单元测试:您可以轻松定义一个表驱动的测试,其中包含您想要的值和您期望的输出而不必丢弃全局变量.


pet*_*rSO 2

不要沉迷于过早的优化。定义一个Go包API来封装数据,然后你可以随时更改实现。例如,只是乱写乱画,

package data

type Key struct {
    // . . .
}

type Data struct {
    // . . .
}

var dataMap map[Key]Data

func init() {
    dataMap = make(map[Key]Data)
}

func GetData(key Key) (*Data, error) {
    data := dataMap[key]
    return &data, nil
}
Run Code Online (Sandbox Code Playgroud)