這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
main
// main project main.gopackage mainimport ("fmt""html/template""log""net/http""strings""session"_"memory""time")func sayHelloName(w http.ResponseWriter, r *http.Request) {r.ParseForm()fmt.Println(r.Form)fmt.Println(r.URL.Path)fmt.Println(r.URL.Scheme)fmt.Println(r.Form["url_long"])for k, v := range r.Form {fmt.Println("key: ", k)fmt.Println("value:", strings.Join(v, ""))}fmt.Fprintln(w, "hello nihao")}func login(w http.ResponseWriter, r *http.Request) {r.ParseForm()fmt.Println("method: ", r.Method)if r.Method == "GET" {t, err := template.ParseFiles("src/html/login.gtpl")if err != nil {fmt.Println(err)return}t.Execute(w, nil)} else {fmt.Println("username: ", r.Form["username"])fmt.Println("password: ", r.Form["password"])}}func login2(w http.ResponseWriter, r *http.Request) {sess := globalSessions.SessionStart(w, r)r.ParseForm()if r.Method == "GET" {t, _ := template.ParseFiles("src/html/login.gtpl")//w.Header().Set("Content-Type", "text/html")t.Execute(w, sess.Get("username"))} else {sess.Set("username", r.Form["username"])http.Redirect(w, r, "/", 302)}}func count(w http.ResponseWriter, r *http.Request) {sess := globalSessions.SessionStart(w, r)createtime := sess.Get("createtime")if createtime == nil {sess.Set("createtime", time.Now().Unix())} else if (createtime.(int64) + 360) < (time.Now().Unix()) {globalSessions.SessionDestroy(w, r)sess = globalSessions.SessionStart(w, r)}ct := sess.Get("countnum")if ct == nil {sess.Set("countnum", 1)} else {sess.Set("countnum", (ct.(int) + 1))}t, _ := template.ParseFiles("count.gtpl")w.Header().Set("Content-Type", "text/html")t.Execute(w, sess.Get("countnum"))}func main() {//http.HandleFunc("/", sayHelloName);http.HandleFunc("/login", login)http.HandleFunc("/login2", login2)err := http.ListenAndServe(":9090", nil)if err != nil {log.Fatalf("Listen and server", err)}}var globalSessions *session.Managerfunc init() {globalSessions, _ = session.NewSessionManager("memory", "goSessionid", 3600)go globalSessions.GC()fmt.Println("fd")}
session
package sessionimport ("crypto/rand""encoding/base64""fmt""io""net/http""net/url""sync""time")type Manager struct {cookieName stringlock sync.Mutexprovider ProvidermaxLifeTime int64}type Provider interface {SessionInit(sid string) (Session, error)SessionRead(sid string) (Session, error)SessionDestroy(sid string) errorSessionGC(maxLifeTime int64)}type Session interface {Set(key, value interface{}) errorGet(key interface{}) interface{}Delete(ket interface{}) errorSessionID() string}func NewSessionManager(provideName, cookieName string, maxLifeTime int64) (*Manager, error) {provide, ok := provides[provideName]if !ok {return nil, fmt.Errorf("session: unknown provide %q (forgotten import?", provideName)}return &Manager{cookieName: cookieName, provider: provide, maxLifeTime: maxLifeTime}, nil}func Register(name string, provide Provider) {if provide == nil {panic("session: Register provide is nil")}if _, dup := provides[name]; dup {panic("session: Register called twice for provide " + name)}provides[name] = provide}var provides = make(map[string]Provider)func (manager *Manager) sessionId() string {b := make([]byte, 32)if _, err := io.ReadFull(rand.Reader, b); err != nil {return ""}return base64.URLEncoding.EncodeToString(b)}func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (session Session) {manager.lock.Lock()defer manager.lock.Unlock()cookie, err := r.Cookie(manager.cookieName)if err != nil || cookie.Value == "" {sid := manager.sessionId()session, _ = manager.provider.SessionInit(sid)cookie := http.Cookie{Name: manager.cookieName, Value: url.QueryEscape(sid), Path: "/", HttpOnly: true, MaxAge: int(manager.maxLifeTime)}http.SetCookie(w, &cookie)} else {sid, _ := url.QueryUnescape(cookie.Value)session, _ = manager.provider.SessionRead(sid)}return session}func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request){cookie, err := r.Cookie(manager.cookieName)if err != nil || cookie.Value == "" {return} else {manager.lock.Lock()defer manager.lock.Unlock()manager.provider.SessionDestroy(cookie.Value)expiration := time.Now()cookie := http.Cookie{Name: manager.cookieName, Path: "/",HttpOnly: true, Expires: expiration, MaxAge: -1}http.SetCookie(w, &cookie)}}func (manager *Manager) GC() {manager.lock.Lock()defer manager.lock.Unlock()manager.provider.SessionGC(manager.maxLifeTime)time.AfterFunc(time.Duration(manager.maxLifeTime), func(){ manager.GC() })}
memory
package memoryimport ("container/list""time""sync""fmt""session")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] = valuepder.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 (provider *Provider) SessionInit(sid string) (session.Session, error) {provider.lock.Lock()defer provider.lock.Unlock()v := make(map[interface{}]interface{}, 0)newsess := &SessionStore{sid: sid, timeAccessed: time.Now(), value: v}element := provider.list.PushBack(newsess)provider.sessions[sid] = elementreturn newsess, nil}func (provider *Provider) SessionRead(sid string) (session.Session, error) {if element, ok := provider.sessions[sid]; ok {return element.Value.(*SessionStore), nil} else {sess, err := provider.SessionInit(sid)return sess, err}return nil, nil}func (provider *Provider) SessionDestroy(sid string) error {if element, ok := provider.sessions[sid]; ok {delete(provider.sessions, sid)provider.list.Remove(element)return nil}return nil}func (provider *Provider) SessionGC(maxLifeTime int64) {provider.lock.Lock()defer provider.lock.Unlock()for {element := provider.list.Back()if element == nil {break}if (element.Value.(*SessionStore).timeAccessed.Unix() + maxLifeTime) <time.Now().Unix() {provider.list.Remove(element)delete(provider.sessions, element.Value.(*SessionStore).sid)} else {break}}}func (provider *Provider) SessionUpdate(sid string) error {provider.lock.Lock()defer provider.lock.Unlock()if element, ok := provider.sessions[sid]; ok {element.Value.(*SessionStore).timeAccessed = time.Now()provider.list.MoveToFront(element)return nil}return nil}var pder = &Provider{list: list.New()}func init() {pder.sessions = make(map[string]*list.Element, 0)session.Register("memory", pder)fmt.Println("wzz")}