使用gin封装一个web脚手架(六):实现session(中)


本文摘自网络,作者,侵删。

设计好session的数据结构后开始存放初始session值

先在context.go中定义好session的结构体

package context

//context/context.go

import (
	"github.com/gin-gonic/gin"
	"strings"
)

type Context struct {
	*gin.Context
}

type HandlerFunc func(*Context)

func (c *Context) Domain() string {

	return c.Request.Host[:strings.Index(c.Request.Host, ":")]
}

type Session struct {
	Cookie      string                 `json:"cookie"`
	ExpireTime  int64                  `json:"expire_time"`
	SessionList map[string]interface{} `json:"session_list"`
}

复制代码

接下来在session中间件中存储初始化数据

package session

import (
	context2 "context"
	"encoding/json"
	uuid "github.com/satori/go.uuid"
	"myGin/context"
	"myGin/redis"
	"time"
)

var cookieName = "my_gin"

var lifeTime = 3600

func Session(c *context.Context) {

	sessionKey := uuid.NewV4().String()

	c.SetCookie(cookieName, sessionKey, lifeTime, "/", c.Domain(), false, true)

	session := context.Session{
		Cookie:      sessionKey,
		ExpireTime:  time.Now().Unix() + int64(lifeTime),
		SessionList: make(map[string]interface{}),
	}

	jsonString, _ := json.Marshal(session)

	redis.Client().Set(context2.TODO(), sessionKey, jsonString, time.Second*time.Duration(lifeTime))

}
复制代码

运行浏览器后,在redis中出现

image.png

问题出现了,虽然数据存储进去了,但是每刷新一次浏览器就会重新存储一次session,这显然不是我们想要的。正确的逻辑应该是,cookie存在并且能够在redis中找到这个值就不需要重新设置了。

修改一下代码

package session

import (
	context2 "context"
	"encoding/json"
	uuid "github.com/satori/go.uuid"
	"myGin/context"
	"myGin/redis"
	"time"
)

var cookieName = "my_gin"

var lifeTime = 3600

func Session(c *context.Context) {

	cookie, err := c.Cookie(cookieName)

	if err == nil {

		sessionString, err := redis.Client().Get(context2.TODO(), cookie).Result()

		if err == nil {

			var session context.Session

			json.Unmarshal([]byte(sessionString), &session)

			return
		}

	}

	sessionKey := uuid.NewV4().String()

	c.SetCookie(cookieName, sessionKey, lifeTime, "/", c.Domain(), false, true)

	session := context.Session{
		Cookie:      sessionKey,
		ExpireTime:  time.Now().Unix() + int64(lifeTime),
		SessionList: make(map[string]interface{}),
	}

	jsonString, _ := json.Marshal(session)

	redis.Client().Set(context2.TODO(), sessionKey, jsonString, time.Second*time.Duration(lifeTime))

}
复制代码

为了防止二次查询,将session结果存储到gin的context中

package session

import (
	context2 "context"
	"encoding/json"
	uuid "github.com/satori/go.uuid"
	"myGin/context"
	"myGin/redis"
	"time"
)

var cookieName = "my_gin"

var lifeTime = 3600

func Session(c *context.Context) {

	cookie, err := c.Cookie(cookieName)

	if err == nil {

		sessionString, err := redis.Client().Get(context2.TODO(), cookie).Result()

		if err == nil {

			var session context.Session

			json.Unmarshal([]byte(sessionString), &session)

			//存储到context中,方便当前请求中的其他函数好操作session
			c.Set("_session", session)

			return
		}

	}

	sessionKey := uuid.NewV4().String()

	c.SetCookie(cookieName, sessionKey, lifeTime, "/", c.Domain(), false, true)

	session := context.Session{
		Cookie:      sessionKey,
		ExpireTime:  time.Now().Unix() + int64(lifeTime),
		SessionList: make(map[string]interface{}),
	}

	//这里也要
	c.Set("_session", session)

	jsonString, _ := json.Marshal(session)

	redis.Client().Set(context2.TODO(), sessionKey, jsonString, time.Second*time.Duration(lifeTime))

}
复制代码


本文来自:掘金

感谢作者:一位不愿意透露姓名的杨先生

查看原文:使用gin封装一个web脚手架(六):实现session(中)

相关阅读 >>

Golang快速入门(二)初尝命令行参数

从log4j2的角度看Golang的zap

leetcode Golang

Go是弱语言么

一个微服务 demo 将我三年 Go web 开发经验传授给你

一文讲解Golang怎么实现反转链表

Go之http包的服务端介绍

Golang单向链表

[Go] Golang happen before 的保证原则

教你使用Golang实现redis服务器

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...

    正在狠努力加载,请稍候...