我正在写一些Go Webservices(也可以使用http.ListenAndServe在Go中实现webserver).
我有一个我想保存在内存中的结构体映射(大约数据大小为100Kb)被不同的http请求使用.
我有一个我想保存在内存中的结构体映射(大约数据大小为100Kb)被不同的http请求使用.
在Go中实现这一点的最好方法是哪个?
根据您的经验,最好使用全局包变量或缓存系统(如memcache / groupcache)?
除了您已经收到的答案之外,还要考虑使用接收机咖喱
method values和
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(...) }
如果所有的普通数据都是只读的,这样做很好.如果公共数据是读/写,那么你会想要一些更像:
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 }
其余的基本相同,除了直接通过接收者的字段访问数据,您可以通过getter和setter访问它们.在大多数数据正在读取的Web服务器中,您可能需要一个RWMutex,以便读取可以彼此并发执行.第二种方法的另一个优点是您已经封装了数据,因此如果您的应用程序需要增长,可以添加透明写入和/或从内存缓存或组缓存中读取的内容,或将来会添加其他内容.
我真正喜欢将我的处理程序定义为对象的方法的一件事是,它使得单元测试更容易:您可以轻松地定义一个table driven test,其中包含所需的值和您期望的输出,而不必随身携带全局变量