Files
build-web-application-with-…/ja/06.3.md
2014-12-14 23:27:42 +08:00

138 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 6.3 sessionストレージ
上の節でSessionマネージャの実装原理をご紹介しました。sessionを保存するインターフェースを定義したので、この節ではメモリに基づくsessionストレージインターフェースの実装例をご説明します。その他の保存方法についてはご自身で例を参考に実装してみてください。メモリの実装については下のコード例をご覧ください。
package memory
import (
"container/list"
"github.com/astaxie/session"
"sync"
"time"
)
var pder = &Provider{list: list.New()}
type SessionStore struct {
sid string //session idユニークID
timeAccessed time.Time //最終アクセス時間
value map[interface{}]interface{} //sessionに保存される値
}
func (st *SessionStore) Set(key, value interface{}) error {
st.value[key] = value
pder.SessionUpdate(st.sid)
return nil
}
func (st *SessionStore) Get(key interface{}) interface{} {
pder.SessionUpdate(st.sid)
if v, ok := st.value[key]; ok {
return v
} else {
return nil
}
return nil
}
func (st *SessionStore) Delete(key interface{}) error {
delete(st.value, key)
pder.SessionUpdate(st.sid)
return nil
}
func (st *SessionStore) SessionID() string {
return st.sid
}
type Provider struct {
lock sync.Mutex //ロックに使用します
sessions map[string]*list.Element //メモリに保存するために使用します
list *list.List //gcを行うために使用します
}
func (pder *Provider) SessionInit(sid string) (session.Session, error) {
pder.lock.Lock()
defer pder.lock.Unlock()
v := make(map[interface{}]interface{}, 0)
newsess := &SessionStore{sid: sid, timeAccessed: time.Now(), value: v}
element := pder.list.PushBack(newsess)
pder.sessions[sid] = element
return newsess, nil
}
func (pder *Provider) SessionRead(sid string) (session.Session, error) {
if element, ok := pder.sessions[sid]; ok {
return element.Value.(*SessionStore), nil
} else {
sess, err := pder.SessionInit(sid)
return sess, err
}
return nil, nil
}
func (pder *Provider) SessionDestroy(sid string) error {
if element, ok := pder.sessions[sid]; ok {
delete(pder.sessions, sid)
pder.list.Remove(element)
return nil
}
return nil
}
func (pder *Provider) SessionGC(maxlifetime int64) {
pder.lock.Lock()
defer pder.lock.Unlock()
for {
element := pder.list.Back()
if element == nil {
break
}
if (element.Value.(*SessionStore).timeAccessed.Unix() + maxlifetime) < time.Now().Unix() {
pder.list.Remove(element)
delete(pder.sessions, element.Value.(*SessionStore).sid)
} else {
break
}
}
}
func (pder *Provider) SessionUpdate(sid string) error {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
element.Value.(*SessionStore).timeAccessed = time.Now()
pder.list.MoveToFront(element)
return nil
}
return nil
}
func init() {
pder.sessions = make(map[string]*list.Element, 0)
session.Register("memory", pder)
}
上のコードはメモリに保存するsessionメカニズムを実現しています。init関数を通じてsessionマネージャに登録されます。このように簡単にコールすることができます。どのようにこのエンジンをコールするのでしょうか下のコードをご覧ください。
import (
"github.com/astaxie/session"
_ "github.com/astaxie/session/providers/memory"
)
importを行う際、memory関数ではinit関数がすでに実行されています。これによりすでにsessionマネージャへの登録が済んでいますので、使用することができます。下の方法によってsessionマネージャを初期化することができます
var globalSessions *session.Manager
//この後、init関数で初期化を行います。
func init() {
globalSessions, _ = session.NewManager("memory", "gosessionid", 3600)
go globalSessions.GC()
}
## links
* [目次](<preface.md>)
* 前へ: [Goはどのようにしてsessionを使用するか](<06.2.md>)
* 次へ: [sessionハイジャックの予防](<06.4.md>)