您的位置:首页 > 编程语言 > Go语言

gorilla/sessions 阅读

2014-03-11 21:08 141 查看
// Flashes returns a slice of flash messages from the session.
//
// A single variadic argument is accepted, and it is optional: it defines
// the flash key. If not defined "_flash" is used by default.
func (s *Session) Flashes(vars ...string) []interface{} {
var flashes []interface{}
key := flashesKey
if len(vars) > 0 {
key = vars[0]
}
if v, ok := s.Values[key]; ok {
// Drop the flashes and return it.
delete(s.Values, key)
flashes = v.([]interface{})
}
return flashes
}

// AddFlash adds a flash message to the session.
//
// A single variadic argument is accepted, and it is optional: it defines
// the flash key. If not defined "_flash" is used by default.
func (s *Session) AddFlash(value interface{}, vars ...string) {
key := flashesKey
if len(vars) > 0 {
key = vars[0]
}
var flashes []interface{}
if v, ok := s.Values[key]; ok {
flashes = v.([]interface{})
}
s.Values[key] = append(flashes, value)
}


可以用var...的方法实现一个含有可选参数的函数。

如果有flash的话就把flash拿出来,再通过append加上去,如果没有的话就直接添加上。

下面是我把beego里的sess_mem的接口实现加上了flash支持,另外在session里面给接口加上两个方法。

package session

import (
"container/list"
"sync"
"time"
//"fmt"
)

const flash = "___Flash"

var mempder = &MemProvider{list: list.New(), sessions: make(map[string]*list.Element)}

type MemSessionStore struct {
sid          string                      //session id唯一标示
timeAccessed time.Time                   //最后访问时间
value        map[interface{}]interface{} //session里面存储的值
//传说中的读写全球锁
lock sync.RWMutex
}

//设置flash
func (st *MemSessionStore) FlashSet(value interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
var flashes []interface{}
if v, ok := st.value[flash]; ok {
flashes = v.([]interface{})
}
st.value[flash] = append(flashes, value)
return nil
}

//返回flash
func (st *MemSessionStore) FlashGet() []interface{} {
st.lock.Lock()
defer st.lock.Unlock()
if v, ok := st.value[flash]; ok {
temp := v
delete(st.value, flash)
return temp.([]interface{})
} else {
return nil
}
return nil
}

//map不是线程安全的
func (st *MemSessionStore) Set(key, value interface{}) error {
//所有想要Lock的都会阻塞,直到解锁
st.lock.Lock()
defer st.lock.Unlock()
//fmt.Println("set")
st.value[key] = value
return nil
}

func (st *MemSessionStore) Get(key interface{}) interface{} {
//所有想要读的都会阻塞,直到解锁
st.lock.RLock()
//这里是为了拿到读锁,也就是说,占用这个资源给这个资源上锁
//之所以要上锁就是因为,比如写的时候已经上锁了,那么不用锁机制的话
//get就会拿到写之后的呢?还是写之前的呢?所以要有锁机制,用Rlock阻塞
defer st.lock.RUnlock()

if v, ok := st.value[key]; ok {
return v
} else {
return nil
}
return nil
}

func (st *MemSessionStore) Delete(key interface{}) error {
st.lock.Lock()
defer st.lock.Unlock()
delete(st.value, key)
return nil
}

func (st *MemSessionStore) Flush() error {
st.lock.Lock()
defer st.lock.Unlock()
//删除的方法,只有把这个map赋个空值了
st.value = make(map[interface{}]interface{})
return nil
}

func (st *MemSessionStore) SessionID() string {
return st.sid
}

func (st *MemSessionStore) SessionRelease() {

//这里怎么没实现?写个空函数在这里

}

type MemProvider struct {
lock        sync.RWMutex             //用来锁
sessions    map[string]*list.Element //用来存储在内存
list        *list.List               //用来做gc
maxlifetime int64
savePath    string
}

func (pder *MemProvider) SessionInit(maxlifetime int64, savePath string) error {
pder.maxlifetime = maxlifetime
pder.savePath = savePath
return nil
}

func (pder *MemProvider) SessionRead(sid string) (SessionStore, error) {
pder.lock.RLock()
if element, ok := pder.sessions[sid]; ok {
go pder.SessionUpdate(sid)
pder.lock.RUnlock()
return element.Value.(*MemSessionStore), nil
} else {
pder.lock.RUnlock()
pder.lock.Lock()
newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})}
element := pder.list.PushBack(newsess)
pder.sessions[sid] = element
pder.lock.Unlock()
return newsess, nil
}
return nil, nil
}

func (pder *MemProvider) SessionExist(sid string) bool {
pder.lock.RLock()
defer pder.lock.RUnlock()
if _, ok := pder.sessions[sid]; ok {
return true
} else {
return false
}
}

func (pder *MemProvider) SessionRegenerate(oldsid, sid string) (SessionStore, error) {
pder.lock.RLock()
if element, ok := pder.sessions[oldsid]; ok {
go pder.SessionUpdate(oldsid)
pder.lock.RUnlock()
pder.lock.Lock()
//list的节点是Element,有一个Value是一个借口
element.Value.(*MemSessionStore).sid = sid
pder.sessions[sid] = element
delete(pder.sessions, oldsid)
pder.lock.Unlock()
return element.Value.(*MemSessionStore), nil
} else {
pder.lock.RUnlock()
pder.lock.Lock()
newsess := &MemSessionStore{sid: sid, timeAccessed: time.Now(), value: make(map[interface{}]interface{})}
element := pder.list.PushBack(newsess)
pder.sessions[sid] = element
pder.lock.Unlock()
return newsess, nil
}
return nil, nil
}

func (pder *MemProvider) SessionDestroy(sid string) error {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
delete(pder.sessions, sid)
pder.list.Remove(element)
return nil
}
return nil
}

func (pder *MemProvider) SessionGC() {
pder.lock.RLock()
for {
element := pder.list.Back()
if element == nil {
break
}
if (element.Value.(*MemSessionStore).timeAccessed.Unix() + pder.maxlifetime) < time.Now().Unix() {
pder.lock.RUnlock()
pder.lock.Lock()
pder.list.Remove(element)
delete(pder.sessions, element.Value.(*MemSessionStore).sid)
pder.lock.Unlock()
pder.lock.RLock()
} else {
break
}
}
pder.lock.RUnlock()
}

//这个命名不是太好的感觉

func (pder *MemProvider) SessionAll() int {
return pder.list.Len()
}

func (pder *MemProvider) SessionUpdate(sid string) error {
pder.lock.Lock()
defer pder.lock.Unlock()
if element, ok := pder.sessions[sid]; ok {
element.Value.(*MemSessionStore).timeAccessed = time.Now()
pder.list.MoveToFront(element)
return nil
}
return nil
}

func init() {
//注册使用这个接口,会话提供者
Register("memory", mempder)
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: