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