Files
build-web-application-with-…/zh-tw/06.3.md
2019-02-26 01:40:54 +08:00

140 lines
3.6 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儲存介面的實現其他的儲存方式讀者可以自行參考示例來實現記憶體的實現請看下面的例子程式碼
```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
* [目錄](<preface.md>)
* 上一節: [Go如何使用session](<06.2.md>)
* 下一節: [預防session劫持](<06.4.md>)