1

I am creating the mongodb connection from main method and defer that open connection.

func main(){
    session := db.CreateConnection(connectionStr)
    defer session.Close()
}

The issue is I need to pass this sesstion object to user handler struct and from that pass to db handler.

type UserController struct {
    DB DBOps
}

type DBOps struct {
    session *mgo.Session
}

Question: How can we directly create the session object and inside db handler file and defer that when application closes ?

db.go

type DBOps struct {
    session *mgo.Session
}

func (m *DBOps) Init(connectionstr string) error {
    session, err := mgo.Dial(connectionstr)

    // Check if connection error, is mongo running?
    if err != nil {
        panic(err)
    }
}

inside main function I can just call

func main(){
    db.Init(connectionstr);
}

but How to defer this session object on the main method ?

Himanshu
  • 12,071
  • 7
  • 46
  • 61
R.Roshan
  • 199
  • 4
  • 14
  • 4
    Related, see this answer [how MongoDB session should be handled / used](https://stackoverflow.com/questions/47179890/too-many-open-files-in-mgo-go-server/47180097#47180097). – icza Jan 09 '18 at 09:40
  • OK thanks. understood. But the session created on init will be there even after close the main method. Thats my worry ? – R.Roshan Jan 09 '18 at 09:53
  • 3
    If you return from the `main` function, your whole app will terminate and not wait for other non-`main` goroutines to complete. See: [What's wrong with this golang code?](https://stackoverflow.com/questions/28958192/whats-wrong-with-this-golang-code/28958240#28958240) – icza Jan 09 '18 at 09:53

1 Answers1

1

you can create global variable for assigning the session object, return session object from a function. Use session object to fetch data and then defer the session after querying from mongo.

var (
    mgoSession     *mgo.Session
    databaseName = "myDB"
)

func getSession () *mgo.Session {
    if mgoSession == nil {
        var err error
        mgoSession, err = mgo.Dial("localhost")
        if err != nil {
             panic(err) // no, not really
        }
    }
    return mgoSession.Clone()
}

func withCollection(collection string, s func(*mgo.Collection) error)   
{    
    session := getSession()
    defer session.Close()
    c := session.DB(databaseName).C(collection)
    return s(c)
}

I have cloned session object and returned it to function used to query mongo and defer the session there. By above approach you can directly access session object inside handler.

Himanshu
  • 12,071
  • 7
  • 46
  • 61