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