Search code examples
gomgo

Best Practise opening DB


Note: I am not sure if this is the most accurate title for this post, if not, please advise on a better one.

Currently I am creating a server where I have a couple of handlers (using goji). After receiving a request, I want to interact with a MongoDB database I have (using mgo). My question is:

I am assuming doing this kind of stuff every time I am handling a request is expensive:

uri := os.Getenv("MONGOHQ_URL")

if uri == "" {

    panic("no DB connection string provided")
}

session, err := mgo.Dial(uri)

So, would it be better for me to have a global var that I can access from inside the handlers? So I would go with something like this:

var session *mgo.Session

func main() {

    session = setupDB()
    defer session.Close()

    goji.Get("/user", getUser)
    goji.Serve()
}

func getUser(c web.C, w http.ResponseWriter, r *http.Request) {
// Use the session var here
}

My question is related to what would be the best practise here? Opening the DB every time a request comes in, or keep it open for the entire duration of the application.


Solution

  • What about wraping your handler in a Controller struct like this: (http://play.golang.org/p/NK6GO_lqgk)

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "os"
    
        "github.com/zenazn/goji"
        "github.com/zenazn/goji/web"
    )
    
    type Controller struct {
        session *Session
    }
    
    func NewController() (*Controller, error) {
        if uri := os.Getenv("MONGOHQ_URL"); uri == "" {
            return nil, fmt.Errorf("no DB connection string provided")
        }
        session, err := mgo.Dial(uri)
        if err != nil {
            return nil, err
        }
        return &Controller{
            session: session,
        }, nil
    }
    
    func (c *Controller) getUser(c web.C, w http.ResponseWriter, r *http.Request) {
        // Use the session var here
    }
    
    func main() {
        ctl, err := NewController()
        if err != nil {
            log.Fatal(err)
        }
        defer ctl.session.Close()
    
        goji.Get("/user", ctl.getUser)
        goji.Serve()
    }
    

    This way, you can embed your session in your handler and add any other data that you might need.