Go基础学习记录之Session存储

{app.params.name}}{app.params.name}}{app.params.name}}

Session存储

我们在上篇文章中介绍了一个简单的Session管理器的工作原理,除此之外,我们还定义了一个Session存储接口。在本次分享中,我将展示一个实现此接口的基于内存的会话存储引擎的示例。您也可以将其定制为其他形式的Session存储。

package memory

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

	"github.com/durban89/wiki/session"
)

// Store 存储
type Store struct {
	sid      string                      // unique session is
	lastTime time.Time                   // last save time
	value    map[interface{}]interface{} // session value save inside
}

// Provider 寄存器
type Provider struct {
	lock     sync.RWMutex             // locker
	sessions map[string]*list.Element // map in memory
	list     *list.List               // for gc
}

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

// Set Session
func (s *Store) Set(key, value interface{}) error {
	s.value[key] = value
	memoryProvider.SessionUpdate(s.sid)
	return nil
}

// Get Session
func (s *Store) Get(key interface{}) interface{} {
	memoryProvider.SessionUpdate(s.sid)
	if v, ok := s.value[key]; ok {
		return v
	}

	return nil

}

// Del Session
func (s *Store) Del(key interface{}) error {
	delete(s.value, key)
	memoryProvider.SessionUpdate(s.sid)
	return nil
}

// SID Session ID
func (s *Store) SID() string {
	return s.sid
}

// SessionInit 一个Session
func (p *Provider) SessionInit(sid string) (session.Session, error) {
	memoryProvider.lock.Lock()
	defer memoryProvider.lock.Unlock()
	v := make(map[interface{}]interface{}, 0)
	store := &Store{
		sid:      sid,
		lastTime: time.Now(),
		value:    v,
	}

	res := memoryProvider.list.PushBack(store)
	memoryProvider.sessions[sid] = res

	return store, nil
}

// SessionRead 一个Session
func (p *Provider) SessionRead(sid string) (session.Session, error) {
	if v, ok := memoryProvider.sessions[sid]; ok {
		return v.Value.(*Store), nil
	}

	store, err := memoryProvider.SessionInit(sid)
	return store, err

}

// SessionDestroy 一个Session
func (p *Provider) SessionDestroy(sid string) error {
	if v, ok := memoryProvider.sessions[sid]; ok {
		delete(memoryProvider.sessions, sid)
		memoryProvider.list.Remove(v)
		return nil
	}

	return nil
}

// SessionGC 一个Session
func (p *Provider) SessionGC(maxLifeTime int64) {
	memoryProvider.lock.Lock()
	defer memoryProvider.lock.Unlock()

	for {
		v := memoryProvider.list.Back()
		if v == nil {
			break
		}

		if v.Value.(*Store).lastTime.Unix()+maxLifeTime < time.Now().Unix() {
			memoryProvider.list.Remove(v)
			delete(memoryProvider.sessions, v.Value.(*Store).sid)
		} else {
			break
		}
	}
}

// SessionUpdate 一个Session
func (p *Provider) SessionUpdate(sid string) error {
	memoryProvider.lock.Lock()
	defer memoryProvider.lock.Unlock()

	if v, ok := memoryProvider.sessions[sid]; ok {
		v.Value.(*Store).lastTime = time.Now()
		memoryProvider.list.MoveToFront(v)
	}

	return nil
}

func init() {
	memoryProvider.sessions = make(map[string]*list.Element, 0)
	session.RegisterProvider("memory", memoryProvider)
}

上面的示例实现了基于内存的Session存储机制。它使用其init()函数将此存储引擎注册到Session管理器。那么我们如何从主程序注册这个引擎呢?

import (
	"github.com/durban89/wiki/session"

	// memory session provider
	_ "github.com/durban89/wiki/session/providers/memory"
)

我们使用空白导入机制(它将自动调用包的init()函数)将此引擎注册到Session管理器。然后,我们使用以下代码初始化Session管理器:

var appSession *session.Manager

func init() {
	appSession, _ := session.GetManager("memory", "sessionid", 3600)

	go appSession.SessionGC()
}

 

版权声明

durban创作并维护的 小绒毛的足迹博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。

本文首发于 博客( https://www.xiaorongmao.com ),版权所有,侵权必究。

本文永久链接: https://www.xiaorongmao.com/blog/84


版权声明

durban创作并维护的 小绒毛的足迹博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。

本文首发于 小绒毛的足迹博客( https://www.xiaorongmao.com ),版权所有,侵权必究。

本文永久链接: https://www.xiaorongmao.com/blog/84