Le migliori pratiche per mantenere una sessione di mgo

Attualmente sto usando un mongodb con mgo lib per un’applicazione web, ma non sono sicuro se il modo in cui lo sto usando, è buono ..

package db import ( "gopkg.in/mgo.v2" ) const ( MongoServerAddr = "192.168.0.104" RedisServerAddr = "192.168.0.104" ) var ( MongoSession, err = mgo.Dial(MongoServerAddr) MDB = MongoSession.DB("message") MCol = MDB.C("new") MSav = MDB.C("save") UDB = MongoSession.DB("account") UCol = UDB.C("user") ) 

Avvio la sessione db e creo variabili che prendono la raccolta e il valore del documento, quindi quando ho bisogno di interrogare una raccolta, io uso la variabile per realizzarla.

Come quello :

 func UserExist(username string) bool { user := Users{} err := db.UCol.Find(bson.M{"username": username}).One(&user) if err != nil { return false } else { return true } } 

Quindi c’è una buona pratica o questa va bene ..? Grazie

    Suggerisco di non usare una sessione globale come quella. Invece, è ansible creare un tipo responsabile di tutte le interazioni del database. Per esempio:

     type DataStore struct { session *mgo.Session } func (ds *DataStore) ucol() *mgo.Collection { ... } func (ds *DataStore) UserExist(user string) bool { ... } 

    Ci sono molti vantaggi in questo design. Un aspetto importante è che ti consente di avere più sessioni contemporaneamente, quindi se hai un gestore http, ad esempio, puoi creare una sessione locale supportata da una sessione indipendente solo per quella richiesta:

     func (s *WebSite) dataStore() *DataStore { return &DataStore{s.session.Copy()} } func (s *WebSite) HandleRequest(...) { ds := s.dataStore() defer ds.Close() ... } 

    In questo caso, il driver mgo si comporta bene, poiché le sessioni vengono memorizzate nella cache interna e riutilizzate / gestite. Ogni sessione sarà inoltre supportata da un socket indipendente mentre è in uso e potrebbe avere impostazioni indipendenti configurate e avrà anche una gestione degli errori indipendente. Questi sono problemi che dovrai affrontare se stai utilizzando un’unica sessione globale.

    Sebbene non risponda direttamente alla tua domanda, per quanto riguarda il controllo della sessione di mgo devi usare il rinvio / recupero dal panico di mgo calls (anche mgo.session.Ping). Per quanto posso dire, non c’è altro modo di controllare lo stato della sessione di mgo ( mig godocs ). Puoi utilizzare il suggerimento di Gustavo Niemeyer e aggiungere un metodo al tuo tipo di DataStore .

     func (d *DataStore) EnsureConnected() { defer func() { if r := recover(); r != nil { //Your reconnect logic here. } }() //Ping panics if session is closed. (see mgo.Session.Panic()) d.Ping() } 

    Con go 1.7, il modo più idiomatico di gestire la sessione di mongo su un server web consiste nell’usare il nuovo context pacchetto della libreria standard per scrivere un middleware che può albind la defer session.Close() a ogniqualvolta viene chiamato il contesto della richiesta Done (). Quindi non è necessario ricordare per chiudere

     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)) }) }