gorilla/sessions 阅读

// 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)
}

 

posted @ 2014-03-11 21:08  ggaaooppeenngg  阅读(869)  评论(0编辑  收藏  举报