I'm new to GOLANG - I would like to reduce the complexity of the handlers in my GO API. I'm coming from a Node.js background!
At the moment a route handler looks like this:
func getCards(c web.C, w http.ResponseWriter, r *http.Request) {
session := *MongoConnection().CreateSession()
defer session.Close()
collection := session.DB(db).C(cardsCollection)
result := []Card{}
err := collection.Find(bson.M{}).All(&result)
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
encoder := json.NewEncoder(w)
encoder.Encode(result)
}
What I would like to do is return a collection for use without having to do this part:
session := *MongoConnection().CreateSession()
defer session.Close()
collection := session.DB(db).C(cardsCollection)
Instead I would like to do something like
collection := Card.Collection()
And have it create the session etc, Is this possible?
Why don't you have the session created in your main
function, and pass it to the packages that need it. This is obviously missing a ton of stuff but the general idea would be
package main
//imports
func main() {
session := *MongoConnection().CreateSession()
defer session.Close()
Card.SetSession(session)
//other stuff
log.Fatal(http.ListenAndServe(":80", nil))
}
Then in Card
package Card
var session *mgo.Session
func SetSession(s *mgo.Session) {
session = s
}
func (c *Card) Collection() *mgo.Collection {
return session.DB(db).C(cardsCollection)
}
What you are describing is a factory pattern. But there are caveats to deal with. Defer is local to scope it is called. So in case you would put the defer into a factory method, the session would be closed basically when it is returned.
Simply defining just one session und reuse it all over the place is pretty much the same as using a single SQL database connection and not a pool - it scales horribly.
Here is what I tend to do: I have my collections as global, and do the following at the beginning of my method
// Create a func-local session
myCollection := globalCollection.With( globalCollection.Database.Session.Copy() )
// Close it on exiting the scope
defer myCollection.Database.Session.Close()
Of course, you could externalize the first line into a factory, but that would not really declutter the code or make it more readable.