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