I m using golang in the back end and mongodb is my database. I wanted to store the user session(betwen login and logout )of my web application in the mongodb for the persistence.Since there is provider available only for mysql not for mongodb,I edited it to support mongodb.But when i try to use it i m getting the invalid memory address or nil pointer dereference. The code is as follows and please if there is any better way to code please let me know.Thanks
type (
SessionStore struct {
c *mgo.Session
sid string
lock sync.RWMutex
values map[interface{}]interface{}
}
)
var mgopder = &Provider{}
func (st *SessionStore) Set(key, value interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
st.values[key] = value
return nil
}
// Get value from mongodb session
func (st *SessionStore) Get(key interface{}) interface{} {
st.lock.RLock()
defer st.lock.RUnlock()
if v, ok := st.values[key]; ok {
return v
}
return nil
}
// Delete value in mongodb session
func (st *SessionStore) Delete(key interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
delete(st.values, key)
return nil
}
// Flush clear all values in mongodb session
func (st *SessionStore) Flush() error {
st.lock.Lock()
defer st.lock.Unlock()
st.values = make(map[interface{}]interface{})
return nil
}
// SessionID get session id of this mongodb session store
func (st *SessionStore) SessionID() string {
return st.sid
}
// SessionRelease save mongodb session values to database.
// must call this method to save values to database.
func (st *SessionStore) SessionRelease(w http.ResponseWriter) {
defer st.c.Close()
b, err := session.EncodeGob(st.values)
if err != nil {
return
}
st.c.DB("Employee").C("Sessions").Update(nil, bson.M{"$set": bson.M{
"session_data": b,
"session_expiry": time.Now().Unix(),
"session_key": st.sid,
},
},
)
/*st.c.Exec("UPDATE "+TableName+" set `session_data`=?, `session_expiry`=? where session_key=?",
b, time.Now().Unix(), st.sid)*/
}
type Provider struct {
maxlifetime int64
savePath string
Database string
}
// connect to mongodb
func (mp *Provider) connectInit() *mgo.Session {
ds, err := mgo.Dial("Employee")
if err != nil {
return nil
}
return ds
}
// SessionInit init mongodb session.
// savepath is the connection string of mongodb
func (mp *Provider) SessionInit(maxlifetime int64, savePath string) error {
mp.maxlifetime = maxlifetime
mp.savePath = savePath
mp.Database = "Employee"
return nil
}
// SessionRead get mysql session by sid
func (mp *Provider) SessionRead(sid string) (session.Store, error) {
var sessiondata []byte
ds := mp.connectInit()
defer ds.Close()
c := ds.DB(mp.Database).C("Session")
err := c.Find(bson.M{
"session_key": sid,
}).Select(bson.M{"session_data": 1}).All(&sessiondata)
if err != nil {
if err.Error() == "not found" {
c.Insert(bson.M{
"session_key": sid,
"session_data": " ",
"session_expiry": time.Now().Unix(),
})
}
}
var kv map[interface{}]interface{}
if len(sessiondata) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = session.DecodeGob(sessiondata)
if err != nil {
return nil, err
}
}
rs := &SessionStore{c: ds, sid: sid, values: kv}
return rs, nil
}
// SessionExist check mongodb session exist
func (mp *Provider) SessionExist(sid string) bool {
var sessiondata []byte
ds := mp.connectInit()
defer ds.Close()
c := ds.DB("Employee").C("Sessions")
err := c.Find(bson.M{
"session_key": sid,
}).Select(bson.M{
"session_data": 1,
}).One(&sessiondata)
if err != nil {
if err.Error() == "not found" {
return false
}
}
return true
}
// SessionRegenerate generate new sid for mysql session
func (mp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
var sessiondata []byte
ds := mp.connectInit()
defer ds.Close()
c := ds.DB("Employee").C("Sessions")
err := c.Find(bson.M{
"session_key": oldsid,
}).Select(bson.M{
"session_data": 1,
}).One(&sessiondata)
if err != nil {
if err.Error() == "not found" {
c.Insert(bson.M{
"sessoin_key": oldsid,
"session_data": " ",
"session_expiry": time.Now().Unix(),
})
}
}
/* row := c.QueryRow("select session_data from "+TableName+" where session_key=?", oldsid)
err := row.Scan(&sessiondata)
c.Update(bson.M{"sessoin_key": oldsid}, bson.M{
"$set": bson.M{
"session_key": sid,
},
})
/*c.Exec("update "+TableName+" set `session_key`=? where session_key=?", sid, oldsid)
*/
var kv map[interface{}]interface{}
if len(sessiondata) == 0 {
kv = make(map[interface{}]interface{})
} else {
kv, err = session.DecodeGob(sessiondata)
if err != nil {
return nil, err
}
}
rs := &SessionStore{c: ds, sid: sid, values: kv}
return rs, nil
}
// SessionDestroy delete mysql session by sid
func (mp *Provider) SessionDestroy(sid string) error {
ds := mp.connectInit()
defer ds.Close()
c := ds.DB("Employee").C("Sessions")
c.Remove(bson.M{
"session_key": sid,
})
return nil
}
// SessionGC delete expired values in mysql session
func (mp *Provider) SessionGC() {
ds := mp.connectInit()
defer ds.Close()
c := ds.DB("Employee").C("Sessions")
c.Remove(bson.M{
"session_expiry": bson.M{
"$lt": time.Now().Unix() - mp.maxlifetime,
},
})
return
}
// SessionAll count values in mysql session
func (mp *Provider) SessionAll() int {
var total int
ds := mp.connectInit()
defer ds.Close()
c := ds.DB("Employee").C("Sessions")
total, err := c.Count()
if err != nil {
return 0
}
return total
}
func init() {
session.Register("mongodb", mgopder)
}
Error:
panic: runtime error: invalid memory address or nil pointer dereference
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x6db254]
goroutine 6 [running]:
panic(0xa2f560, 0xc0820080b0)
C:/Go/src/runtime/panic.go:481 +0x3f4
gopkg.in/mgo%2ev2.(*Session).Close(0x0)
C:/Projects/Go/src/gopkg.in/mgo.v2/session.go:1612 +0x144
panic(0xa2f560, 0xc0820080b0)
C:/Go/src/runtime/panic.go:443 +0x4f7
gopkg.in/mgo%2ev2.(*Session).acquireSocket(0x0, 0xc082290000, 0x0, 0x0, 0x0)
C:/Projects/Go/src/gopkg.in/mgo.v2/session.go:4409 +0x4ba
gopkg.in/mgo%2ev2.(*Collection).writeOp(0xc082279f30, 0x8feb80, 0xc082326060, 0xc082326001, 0x0, 0x0, 0x0)
C:/Projects/Go/src/gopkg.in/mgo.v2/session.go:4604 +0xe7
gopkg.in/mgo%2ev2.(*Collection).Remove(0xc082279f30, 0x9d4700, 0xc082326030, 0x0, 0x0)
C:/Projects/Go/src/gopkg.in/mgo.v2/session.go:2586 +0x15c
sample/models.(*Provider).SessionGC(0xe2f5a0)
C:/Projects/Go/src/sample/models/model.go:234 +0x3dc
github.com/astaxie/beego/session.(*Manager).GC(0xc082258b20)
C:/Projects/Go/src/github.com/astaxie/beego/session/session.go:271 +0x48
created by github.com/astaxie/beego.registerSession
C:/Projects/Go/src/github.com/astaxie/beego/hooks.go:68 +0x31d