# 6.3 session存储
上一节我们介绍了Session管理器的实现原理,定义了存储session的接口,这小节我们将示例一个基于内存的session存储接口的实现,其他的存储方式,读者可以自行参考示例来实现,内存的实现请看下面的例子代码
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
}
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管理器中。这样就可以方便的调用了。我们如何来调用该引擎呢?请看下面的代码
import (
"github.com/astaxie/session"
_ "github.com/astaxie/session/providers/memory"
)
当import的时候已经执行了memory函数里面的init函数,这样就已经注册到session管理器中,我们就可以使用了,通过如下方式就可以初始化一个session管理器:
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>)
- 目录
- Go环境配置
- Go安装
- GOPATH 与工作空间
- Go 命令
- Go开发工具
- 小结
- Go语言基础
- 你好,Go
- Go基础
- 流程和函数
- struct
- 面向对象
- interface
- 并发
- 小结
- Web基础
- web工作方式
- Go搭建一个简单的web服务
- Go如何使得web工作
- Go的http包详解
- 小结
- 表单
- 处理表单的输入
- 验证表单的输入
- 预防跨站脚本
- 防止多次递交表单
- 处理文件上传
- 小结
- 访问数据库
- database/sql接口
- 使用MySQL数据库
- 使用SQLite数据库
- 使用PostgreSQL数据库
- 使用beedb库进行ORM开发
- NOSQL数据库操作
- 小结
- session和数据存储
- session和cookie
- Go如何使用session
- session存储
- 预防session劫持
- 小结
- 文本文件处理
- XML处理
- JSON处理
- 正则处理
- 模板处理
- 文件操作
- 字符串处理
- 小结
- Web服务
- Socket编程
- WebSocket
- REST
- RPC
- 小结
- 安全与加密
- 预防CSRF攻击
- 确保输入过滤
- 避免XSS攻击
- 避免SQL注入
- 存储密码
- 加密和解密数据
- 小结
- 国际化和本地化
- 设置默认地区
- 本地化资源
- 国际化站点
- 小结
- 错误处理,调试和测试
- 错误处理
- 使用GDB调试
- Go怎么写测试用例
- 小结
- 部署与维护
- 应用日志
- 网站错误处理
- 应用部署
- 备份和恢复
- 小结
- 如何设计一个Web框架
- 项目规划
- 自定义路由器设计
- controller设计
- 日志和配置设计
- 实现博客的增删改
- 小结
- 扩展Web框架
- 静态文件支持
- Session支持
- 表单支持
- 用户认证
- 多语言支持
- pprof支持
- 小结
- 参考资料