# 6.3 session 儲存 上一節我們介紹了 Session 管理器的實現原理,定義了儲存 session 的介面,這小節我們將範例一個基於記憶體的 session 儲存介面的實現,其他的儲存方式,讀者可以自行參考範例來實現,記憶體的實現請看下面的例子程式碼 ```Go package memory import ( "container/list" "github.com/astaxie/session" "sync" "time" ) var pder = &Provider{list: list.New()} type SessionStore struct { sid string //session 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 } } 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 管理器中。這樣就可以方便的呼叫了。我們如何來呼叫該引擎呢?請看下面的程式碼 ```Go import ( "github.com/astaxie/session" _ "github.com/astaxie/session/providers/memory" ) ``` 當 import 的時候已經執行了 memory 函式裡面的 init 函式,這樣就已經註冊到 session 管理器中,我們就可以使用了,透過如下方式就可以初始化一個 session 管理器: ```Go var globalSessions *session.Manager //然後在 init 函式中初始化 func init() { globalSessions, _ = session.NewManager("memory", "gosessionid", 3600) go globalSessions.GC() } ``` ## links * [目錄]() * 上一節:[Go 如何使用 session](<06.2.md>) * 下一節:[預防 session 劫持](<06.4.md>)