2016-09-22 15 views
0

私はバックエンドでgolangを使用しています。mongodbは私のデータベースです。 Webアプリケーションのユーザーセッション(betwenログインとログアウト)を永続性のためのmongodbに保存したいと思います。mongodb用ではなくmysql専用のプロバイダがあるので、私はmongodbをサポートするように編集しました。無効なメモリアドレスまたはnilポインタの逆参照を取得しています。 コードは次のようであるとしてください、私はセッションをmongodb golangに保存

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

エラーknow.Thanksせてくださいコーディングする任意のより良い方法がある場合:

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 

答えて

0

ないあなたのコードについて確認が、ここでのサンプルがありますmongodbへのセッションを作成して使用するパッケージファイルです。あなたのメインパッケージで次に

package mydb 

import (
    "fmt" 
    "os" 

    "gopkg.in/mgo.v2" 
    "gopkg.in/mgo.v2/bson" 
) 

var Db *mgo.Session 

type DbLink struct { 
    DbName string 
} 

func NewDbSession(url string) { 
    var e error 

    Db, e = mgo.Dial(url) 

    if e != nil { 
     panic(e) 
     os.Exit(-1) 
    } 
} 

package main 

import (
    "fmt" 
    "os" 

    "mydb" 
) 

func main() { 
    // <user> the user to access the db 
    // <pwd> the database user password 
    // <host> hostname or ip address of the database server (localhost i.e.) 
    // <port> the port where the database server is listening (usually 27016). 
    mydb.NewDbSession("mongodb://<user>:<pwd>@<host>:<port>/?authSource=<db_name>") 

    session := mydb.Db.Copy() 
    defer session.Close() 

    col := session.DB("my_db_schema").C("my_collection_name") 

    // row is a list of struct depends on collection 
    err := col.Find(bson.M{"field_name": "value"}).All(&row) 
    if err != nil { 
     fmt.Printf("%s\n", err) 
    } 

} 

これは、あなたが開始するために役立つはずである非常に簡単な例です。

は、それがのNoSQLスキーマレスデータベース管理システムであるとしてMongoDBのは、それは、MySQLの非常に異なっだと考えてみましょう。

詳細については、mgoパッケージのドキュメントを参照してください。

あなたのユーザーセッションは、構造体のいくつかの問題を持っている:

type SessionStore struct { 
    c  *mgo.Session 
    sid string 
    lock sync.RWMutex 
    values map[interface{}]interface{} 
} 

まずあなたがキーをエクスポートするために大文字を使用する必要があります。

代わりCのたとえばあなたはシドロックとそうでC、およびを使用する必要があります。

type SessionStore struct { 
    C  *mgo.Session    `json:"C" bson:"c"` 
    Sid string      `json:"Sid" bson:"sid,omitempty"` 
    Lock sync.RWMutex    `json:"Lock" bson:"lock,omitempty"` 
    Values map[interface{}]interface{} `json:"Values" bson:"values,omitempty"` 
} 

私はポインタで動作するとは思わない。

+0

申し訳ありませんmongodbの一意のセッションIDを持つユーザーセッション(Webアプリケーションのログインとログアウトの間に)を保存する必要があります....どうかしてください。ありがとうございます.... –

+0

@RajeshKumar私は自分の答えを更新しました。見てください –

+0

marioさん、ありがとうございました。同じエラーのproblem.thanksに直面しているit.Butまだ... –

0

これは私が通常行うことです。

package mongo 

import (
    "time" 

    "gopkg.in/mgo.v2" 
) 

// DataStore containing a pointer to a mgo session 
type DataStore struct { 
    Session *mgo.Session 
} 

// ConnectToTagserver is a helper method that connections to pubgears' tagserver 
// database 
func (ds *DataStore) ConnectToTagserver() { 
    mongoDBDialInfo := &mgo.DialInfo{ 
     Addrs: []string{"some IP"}, 
     Timeout: 60 * time.Second, 
     Database: "some db", 
    } 
    sess, err := mgo.DialWithInfo(mongoDBDialInfo) 
    if err != nil { 
     panic(err) 
    } 
    sess.SetMode(mgo.Monotonic, true) 
    ds.Session = sess 
} 

// Close is a helper method that ensures the session is properly terminated 
func (ds *DataStore) Close() { 
    ds.Session.Close() 
} 

その後、私のモデルのパッケージに、私は、その後、いくつかのルートでは最後に、その後、モデルファイル内のセッションオブジェクトを作成し、だから私はモンゴファイル内のセッションのラッパーを作成し、この

package models 

import (
    "./mongo" 
    "gopkg.in/mgo.v2/bson" 
) 

// AdSize represents the data object stucture that is returned by querying 
// mongo's account collection 
type AdSize struct { 
    ID  bson.ObjectId `bson:"_id,omitempty"` 
    Providers []string  `bson:"providers"` 
    Size  string  `bson:"size"` 
} 

// GetAllAdsizes is a helper function designed to retrieve all the objects in the 
// adsize collection 
func GetAllAdsizes() ([]AdSize, error) { 
    ds := mongo.DataStore{} 
    ds.ConnectToTagserver() 
    defer ds.Close() 
    adSizes := []AdSize{} 
    adSizeCollection := ds.Session.DB("some database").C("some collection") 
    err := adSizeCollection.Find(bson.M{}).Sort("name").All(&adSizes) 
    return adSizes, err 
} 

ような何かを行いますfile私はmongoセッションを処理したメソッドGetAllAdsizes()を呼び出します。セッションは、GetAllAdsizes()メソッドの終了まで延期されます(遅延時に閉じられたため)。しかし、このようなものを変更することができます。ここでは、すべてのユーザーの処理を行い、ユーザーがログアウトするとセッションを終了します。また、こちらをご覧くださいBest practice to maintain a mgo session、あなたは同様のタイプのロジックを見ることができます。

関連する問題