3 回答
TA贡献1804条经验 获得超8个赞
我建议不要使用这样的全局会话。相反,您可以创建一个负责所有数据库交互的类型。例如:
type DataStore struct {
session *mgo.Session
}
func (ds *DataStore) ucol() *mgo.Collection { ... }
func (ds *DataStore) UserExist(user string) bool { ... }
这种设计有很多好处。一个重要的是,它允许您同时进行多个会话,因此,例如,如果您有一个 http 处理程序,您可以创建一个本地会话,该会话由一个独立会话支持,仅用于该请求:
func (s *WebSite) dataStore() *DataStore {
return &DataStore{s.session.Copy()}
}
func (s *WebSite) HandleRequest(...) {
ds := s.dataStore()
defer ds.Close()
...
}
在这种情况下,mgo 驱动程序表现良好,因为会话在内部缓存和重用/维护。每个会话在使用时也将由一个独立的套接字支持,并且可以配置独立的设置,并且还将具有独立的错误处理。如果您使用单个全局会话,这些是您最终必须处理的问题。
TA贡献1828条经验 获得超3个赞
在 go 1.7 中,在 web 服务器上处理 mongo 会话的最惯用的方法是使用新的标准库包context编写一个中间件,该中间件可以在defer session.Close()调用请求上下文 Done() 时附加到。所以你不需要记得关闭
AttachDeviceCollection = func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
db, err := infra.Cloner()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
collection, err := NewDeviceCollection(db)
if err != nil {
db.Session.Close()
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
ctx := context.WithValue(r.Context(), DeviceRepoKey, collection)
go func() {
select {
case <-ctx.Done():
collection.Session.Close()
}
}()
next.ServeHTTP(w, r.WithContext(ctx))
})
}
- 3 回答
- 0 关注
- 184 浏览
添加回答
举报