栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

Golang gin框架

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Golang gin框架

gin框架学习
  • 一、Gin 介绍
  • 二、Gin 环境搭建
  • 三、golang 程序的热加载
  • 四、Gin 框架中的路由
    • 4.1 路由概述
    • 4.2 简单的路由配置
    • 4.3 动态路由
    • 4.4 c.String() c.JSON() c.JSONP() c.XML() c.HTML()
      • 4.4.1 返回一个字符串
      • 4.4.2 返回一个 JSON 数据
      • 4.4.3 返回JSOPN
      • 4.4.4 渲染模板
  • 五、Gin HTML 模板渲染
    • 5.1 全部模板放在一个目录里面的配置方法
    • 5.2 模板放在不同目录里面的配置方法
    • 5.3 gin 模板基本语法
  • 六、静态文件服务
  • 七、路由详解
    • 7.1 GET POST 以及获取 Get Post 传值
      • 7.1.1 Get 请求传值
      • 7.1.2 动态路由传值
      • 7.1.3 Post 请求传值 获取 form 表单数据
      • 7.1.4 Get 传值绑定到结构体
      • 7.1.5 Post 传值绑定到结构体
      • 7.1.6 获取 Post Xml 数据
    • 7.2 路由分组
    • 7.3 路由分离
  • 八、Gin 中自定义控制器
    • 8.1 控制器分组
    • 8.2 控制器的继承
  • 九、Gin 中间件
    • 9.1 路由中间件
      • 9.1.1 初识中间件
      • 9.1.2 ctx.Next()调用该请求的剩余处理程序
      • 9.1.3 一个路由配置多个中间件的执行顺序
      • 9.1.4 ctx.Abort()了解
    • 9.2 全局中间件
    • 9.3 在路由分组中配置中间件
    • 9.4 中间件和对应控制器之间数据共享
    • 中间件注意事项
      • gin默认中间件
      • gin中间件中使用`goroutine`
  • 十、Gin 中自定义Model
    • 10.1 关于Model
    • 10.2 Model 里面封装公共的方法
  • 十一、Gin 文件上传
  • 十二、Gin 中的Cookie
    • 12.1 Cookie 介绍
    • 12.2 Cookie 能实现的功能
    • 12.3 设置和获取Cookie
      • 12.3.1 设置`Cookie`
      • 12.3.2 获取`Cookie`
      • 12.3.3 删除`Cookie`
      • 12.3.3 举例
    • 12.4 多个二级域名共享cookie
  • 十三、Gin 中的Session
  • 十四、Gin 中使用GORM 操作mysql 数据库
  • 十五、原生 SQL 和 SQL 生成器
  • 十六、Gin 中使用GORM 实现表关联查询
  • 十七、 GORM 中使用事务
  • 十八、Gin 中使用go-ini 加载.ini 配置文件

一、Gin 介绍
  • Gin 是一个 Go (Golang) 编写的轻量级 http web 框架,运行速度非常快,如果你是性能和高效的追求者
  • Gin 最擅长的就是 Api 接口的高并发,如果项目的规模不大,业务相对简单,这个时候我们也推荐您使用 Gin
  • Gin 的官网:https://gin-gonic.com/zh-cn/
  • Github 地址:https://github.com/gin-gonic/gin
二、Gin 环境搭建
  • 要安装 Gin 软件包,需要先安装 Go 并设置 Go 工作区(demo)
  1. 下载并安装 gin
    $ go get -u github.com/gin-gonic/gin
  2. 将 gin 引入到代码中
    import "github.com/gin-gonic/gin"
  3. (可选)如果使用诸如 http.StatusOK 之类的常量,则需要引入 net/http 包:
    import "net/http"
  4. 进入项目demo根目录, 第三方包用mod.mod 管理
    $ go mod init demo
  5. 新建 main.go 配置路由
package main

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

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	// 配置路由
	r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"username": "name1",
			"data": "data1",
		})
	})
	// 启动 HTTP 服务,默认在 0.0.0.0:8080 启动服务
	r.Run()
}
  1. 运行你的项目
    $ go run main.go
  2. 可改变默认启动端口
    `r.Run(":9000")
三、golang 程序的热加载
  • 所谓热加载就是当我们对代码进行修改时,程序能够自动重新加载并执行,这在我们开发中 是非常便利的,可以快速进行代码测试,省去了每次手动重新编译
  • 工具一:https://github.com/gravityblast/fresh
  • 安装fresh

在GOPATH下bin目录下有fresh.exe,没有的话,就是安装失败

$cd demo
$go get github.com/pilu/fresh
$fresh

其中:
当运行fresh出现下列错误的时候的解决办法

fresh : 无法将“fresh”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ fresh
+ ~~~~~
    + CategoryInfo          : ObjectNotFound: (fresh:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
  1. 手动下载fresh包
    git clone https://github.com/gravityblast/fresh.git
  2. 安装fresh
    go install github.com/pilu/fresh@latest
  3. 在GOPATH下bin目录下有fresh.exe 如图
  • 工具二:https://github.com/codegangsta/gin
    命令:
    go get github.com/codegangsta/gin
    gin run main.go
四、Gin 框架中的路由 4.1 路由概述

路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等) 组成的,涉及到应用如何响应客户端对某个网站节点的访问

  • RESTful API 是目前比较成熟的一套互联网应用程序的 API 设计理论,所以我们设计我们的路由的时候建议参考 RESTful API 指南。
  • 在 RESTful 架构中,每个网址代表一种资源,不同的请求方式表示执行不同的操作:
请求资源说明
GET (SELECT)从服务器取资源
POST(CREATE)新建资源
PUT (UPDATE)更新资源
DELETE删除资源
4.2 简单的路由配置
  • 简单的路由配置(可以通过 postman 测试)
  • 当用 GET 请求访问一个网址的时候,做什么事情:
r.GET("/", func(c *gin.Context) {
	c.String(200, "hello world")
})
  • 路由里面获取 Get 传值, 域名/news?aid=20
	r.GET("/news", func(c *gin.Context) {
		aid := c.Query("aid")
		c.JSON(200, gin.H{
			"news": aid, // aid = 20
		})
	})

其中:H 为 map[string]interface{}类型

4.3 动态路由
  • 域名/user/20
	r.GET("/user/:id", func(c *gin.Context) {
		id := c.Param("id")
		c.JSON(200, gin.H{
			"news": id, // id 20
		})
	})
4.4 c.String() c.JSON() c.JSONP() c.XML() c.HTML() 4.4.1 返回一个字符串
	r.GET("/news", func(c *gin.Context) {
		aid := c.Query("aid")
		c.String(200, "string")
	})
4.4.2 返回一个 JSON 数据
	r.GET("/json", func(c *gin.Context) {
		aid := c.Query("aid")
		// 方式一:自己拼接 JSON
		c.JSON(http.StatusOK, gin.H{
			"msg": "JSON"
		})
	})
	r.GET("/structJson", func(c *gin.Context) {
		// 结构体方式
		var msg struct {
			Username string `json:"username"`
			Msg string `json:"msg"`
			Age string `json:"age"`
		}
		msg.Username = "name1"
		msg.Msg = "msg1"
		msg.Age = "18"
		c.JSON(200, msg)
	})
4.4.3 返回JSOPN
	r.GET("/JSONP", func(c *gin.Context) { 
	data := map[string]interface{}{
		"foo": "bar",
	}
	// /JSONP?callback=x
	// 将输出:x({"foo":"bar"}) 
	c.JSONP(http.StatusOK, data)
})
4.4.4 渲染模板
	r.GET("/", func(c *gin.Context) {
		c.HTML(
		http.StatusOK, "default/index.html",
		map[string]interface{}{ "title": "前台首页"
		})
	})
五、Gin HTML 模板渲染 5.1 全部模板放在一个目录里面的配置方法
  1. 我们首先在项目根目录新建 templates 文件夹,然后在文件夹中新建 index.html






Document


这是一个 html 模板

{{.title}}
  1. Gin 框架中使用 c.HTML 可以渲染模板, 渲染模板前需要使用 LoadHTMLGlob() 或者LoadHTMLFiles()方法加载模板。
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK,
			"default/index.html",
			map[string]interface{}{"title": "前台首页"})
	})
	r.GET("/", func(c *gin.Context) {
		c.HTML(http.StatusOK, "index.html", gin.H{
			"title": "Main website",
		})
	})
5.2 模板放在不同目录里面的配置方法 5.3 gin 模板基本语法 六、静态文件服务
  • 当我们渲染的 HTML 文件中引用了静态文件时,我们需要配置静态 web 服务
    r.Static("/static", “./static”) 前面的/static 表示路由 后面的./static 表示路径
	r := gin.Default()
	r.Static("/static", "./static")
	r.LoadHTMLGlob("templates*")
七、路由详解
  • 路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等) 组成的,涉及到应用如何响应客户端对某个网站节点的访问。
  • 前面章节我们给大家介绍了路由基础以及路由配置,这里我们详细给大家讲讲路由传值、路 由返回值
7.1 GET POST 以及获取 Get Post 传值 7.1.1 Get 请求传值

GET /user?uid=20&page=1

	r.GET("/user", func(c *gin.Context) { 
		uid := c.Query("uid")
		page := c.DefaultQuery("page", "0") 
		c.String(200, "uid=%v page=%v", uid, page)
	})
7.1.2 动态路由传值

get /user/20

	r.GET("/user/:id", func(c *gin.Context) {
		id := c.Param("id")
		c.JSON(200, gin.H{
			"news": id, // id 20
		})
	})
7.1.3 Post 请求传值 获取 form 表单数据
  • 通过 c.PostForm 接收表单传过来的数据
  • postman进行数据提交
	r.POST("/doAddUser", func(c *gin.Context) {
		username := c.PostForm("username")
		password := c.PostForm("password")
		age := c.DefaultPostForm("age", "20")
		c.JSON(200, gin.H{
			"usernmae": username, "password": password, "age": age,
		})
	})
7.1.4 Get 传值绑定到结构体

/?username=zhangsan&password=123456

type Userinfo struct {
	Username string `form:"username" json:"user"`
	Password string `form:"password" json:"password"`
}

func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	// 配置路由
	r.GET("/", func(c *gin.Context) {
		var userinfo Userinfo
		if err := c.ShouldBind(&userinfo); err == nil {
			c.JSON(http.StatusOK, userinfo)
		} else {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
	})
}
  • 返回数据
    {"user":"zhangsan","password":"123456"}
7.1.5 Post 传值绑定到结构体
	r.POST("/doLogin", func(c *gin.Context) {
		var userinfo Userinfo
		if err := c.ShouldBind(&userinfo); err == nil {
			c.JSON(http.StatusOK, userinfo)
		} else {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		}
	})
7.1.6 获取 Post Xml 数据
  1. 通过ctx.ShouldBindXML获取xml中的数据

我是张三 张三
type Article struct {
	Title   string `json:"title" xml:"title"`
	Content string `json:"content" xml:"content"`
}

	r.POST("/xml", func(ctx *gin.Context) {
		var article Article
		if err := ctx.ShouldBindXML(&article); err == nil {
			ctx.JSON(http.StatusOK, article)
		}else {
			ctx.JSON(http.StatusBadRequest, gin.H {
				"err": err.Error()})
		}
	})

  1. 通过ctx.GetRawData()获取数据
7.2 路由分组
	r := gin.Default()
	apiRouter := r.Group("/api")
	{
		apiRouter.GET("/", func(ctx *gin.Context) {
			ctx.String(200, "api")
		})

		apiRouter.GET("articles", func(ctx *gin.Context) {
			ctx.String(200, "/api/articles")
		})
	}	
7.3 路由分离
  • 在项目新建文件夹router,然后在router目录下创建apiRouter.go 和adminRouter.go,内容如下:
package router
// apiRouter.go
import "github.com/gin-gonic/gin"

func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		apiRouter.GET("/", func(ctx *gin.Context) {
			ctx.String(200, "api")
		})

		apiRouter.GET("articles", func(ctx *gin.Context) {
			ctx.String(200, "/api/articles")
		})
	}
}
package router
// adminRouter.go
import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func AdminRouter(r *gin.Engine) {
	adminRouter := r.Group("/admin")
	{
		adminRouter.GET("/", func(ctx *gin.Context) {
			ctx.String(200, "admin")
		})

		adminRouter.GET("list", func(ctx *gin.Context) {
			ctx.String(http.StatusOK, "admin/list")
		})
	}
}
  • 在main.go中引入路由模块
package main

import (
	"socket/router"

	"github.com/gin-gonic/gin"
)
func main() {
	// 创建一个默认的路由引擎
	r := gin.Default()
	// 引入路由模块
	router.AdminRouter(r)
	router.ApiRouter(r)
	// 启动 HTTP 服务,默认在 0.0.0.0:8080 启动服务
	r.Run()
}
八、Gin 中自定义控制器 8.1 控制器分组
  • 当我们的项目比较大的时候有必要对我们的控制器进行分组 , 业务逻辑放在控制器中
  • 在项目文件夹下面新建controllerapi文件夹,创建userController.go
mkdir controller
cd controller
mkdir api
  • userController.go 内容
package api

import "github.com/gin-gonic/gin"

func UserIndex(c *gin.Context) {
	c.String(200, "api UserIndex")
}

func UserAdd(c *gin.Context)  {
	c.String(200, "api UserAdd")
}

func UserList(c *gin.Context) {
	c.String(200, "api UserList")
}

func UserDelete(c *gin.Context) {
	c.String(200, "api UserDelete")
}
  • 在apiRouter.go中调用userController.go 的函数
import (
	"socket/controller/api"

	"github.com/gin-gonic/gin"
)

func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		apiRouter.GET("/", 
		)

		apiRouter.GET("users", api.UserIndex)
		apiRouter.GET("users/:id", api.UserList)
		apiRouter.POST("users", api.UserAdd)
		apiRouter.PUT("users/:id", api.UserUpdate)
		apiRouter.DELETE("users/:id", api.UserDelete)
	}
}
  • 为了使方法能够继承,我们修改userController.go 内容
package api

import "github.com/gin-gonic/gin"

type UserController struct {

}

func (con UserController) Index(c *gin.Context) {
	c.String(200, "api Index")
}

func (con UserController) Add(c *gin.Context)  {
	c.String(200, "api Add")
}
 
func (con UserController) List(c *gin.Context) {
	c.String(200, "api List")
}

func (con UserController) Update(c *gin.Context) {
	c.String(200, "api update")
}

func (con UserController) Delete(c *gin.Context) {
	c.String(200, "api Delete")
}
  • 继续修改apiRouter.go
func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		apiRouter.GET("/")

		// api.UserController{} 实例化后在可以使用结构体的方法
		apiRouter.GET("users", api.UserController{}.List)
		apiRouter.GET("users/:id", api.UserController{}.List)
		apiRouter.POST("users", api.UserController{}.Add)
		apiRouter.PUT("users/:id", api.UserController{}.Update)
		apiRouter.DELETE("users/:id", api.UserController{}.Delete)
	}
}
8.2 控制器的继承

继承后就可以调用控制器里面的公共方法

  • 在api目录下新建baseController.go,内容如下:
package api

import "github.com/gin-gonic/gin"

type BaseController struct{}

func (con BaseController) success(c *gin.Context) {
	c.String(200, "success")
}

func (con BaseController) error(c *gin.Context) {
	c.String(200, "failed")
}
  • 继续修改userController.go
type UserController struct {
	// 继承BaseController
	BaseController
}

func (con UserController) Index(c *gin.Context) {
	// c.String(200, "api Index")
	con.success(c)
}

func (con UserController) Add(c *gin.Context)  {
	c.String(200, "api Add")
}

func (con UserController) List(c *gin.Context) {
	c.String(200, "api List")
}

func (con UserController) Update(c *gin.Context) {
	c.String(200, "api update")
}

func (con UserController) Delete(c *gin.Context) {
	c.String(200, "api Delete")
}
九、Gin 中间件

Gin 框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、 记录日志、耗时统计等
通俗的讲:中间件就是匹配路由前和匹配路由完成后执行的一系列操作

9.1 路由中间件 9.1.1 初识中间件

Gin 中的中间件必须是一个 gin.HandlerFunc 类型,配置路由的时候可以传递多个 func 回调函数。中间件要放在最后一个回调函数的前面 ,触发的方法都可以称为中间件

// 中间件函数
func InitMiddleWare(c *gin.Context) {
	fmt.Println("init middle ware ")
}
func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		// 中间件要放在最后一个回调函数的前面
		apiRouter.GET("/", InitMiddleWare, api.UserController{}.Index)
	}
}
9.1.2 ctx.Next()调用该请求的剩余处理程序

中间件里面加上 ctx.Next()后,c.Next()的语句后面先不执行,跳转到后面的中间件和回调函数中执行完后,才执行c.Next()后面的语句
可以让我们在路由匹配完成后执行一些操作。比如我们统计一个请求的执行时间

func InitMiddleWare(c *gin.Context) {
	fmt.Println("1- init middle ware ")
	start := time.Now().UnixNano()
	// 调用c.Next()请求的剩余处理程序
	// c.Next()的语句后面先不执行,先跳转路由匹配的最后一个回调函数执行后,
	// 才执行c.Next()后面的语句
	c.Next()
	fmt.Println("3-程序执行完成 计算时间")
	//  计算耗时	Go 语言中的 Since()函数保留时间值,并用于评估与实际时间的差异
	end := time.Now().UnixNano()
	fmt.Println(end - start)
}
func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		// 中间件要放在最后一个回调函数的前面
		apiRouter.GET("/", InitMiddleWare, func(ctx *gin.Context) {
			fmt.Println("2 - 中间件")
			ctx.String(200, "/api")
		})
	}
}
9.1.3 一个路由配置多个中间件的执行顺序
  • 多个中间件执行顺序
func InitMiddleWareOne(c *gin.Context) {
	fmt.Println("one- init middleware start")
	c.Next()
	fmt.Println("one- init middleware end")
}
func InitMiddleWareTwo(c *gin.Context) {
	fmt.Println("Two- init middleware start")
	c.Next()
	fmt.Println("Two- init middleware end")
}

func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		// 中间件要放在最后一个回调函数的前面
		apiRouter.GET("/", InitMiddleWareOne, InitMiddleWareTwo, func(ctx *gin.Context) {
			fmt.Println("首页")
			ctx.String(200, "/api")
		})
	}
}
  • 控制台输出的结果
one- init middleware start
Two- init middleware start
首页
Two- init middleware end
one- init middleware end
9.1.4 ctx.Abort()了解

Abort是终止的意思,ctx.Abort()表示终止调用该请求的剩余处理程序
Abort()后,中间件后面的回调函数(包括后面的中间件)不执行了,直接执行该中间件这里面的语句

9.2 全局中间件
  • r.Use(中间件1,中间件2…)
func InitMiddleWareOne(c *gin.Context) {
	fmt.Println("one- init middleware start")
	c.Next()
	fmt.Println("one- init middleware end")
}
func InitMiddleWareTwo(c *gin.Context) {
	fmt.Println("Two- init middleware start")
	c.Next()
	fmt.Println("Two- init middleware end")
}

func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	apiRouter.Use(InitMiddleWareOne, InitMiddleWareTwo)
	{
		// 中间件要放在最后一个回调函数的前面
		apiRouter.GET("/", func(ctx *gin.Context) {
			fmt.Println("首页")
			ctx.String(200, "/api")
		})
		apiRouter.GET("users", api.UserController{}.Index)
	}
}
9.3 在路由分组中配置中间件 9.4 中间件和对应控制器之间数据共享
  • 中间件中设置值
    ctx.Set("username", "张三")

  • 控制器或者中间件中获取值
    username, _ := ctx.Get("username")

  • username 是一个空接口类型,通过转为字符串v, ok := username.(string)

  • 举例: 中间件

func LoginMiddleWare(c *gin.Context) {
	fmt.Println("login middle ware")
	c.Set("username", "张三")
}
  • 控制器
func (con UserController) Index(c *gin.Context) {
	username, _ := c.Get("username")
	fmt.Println(username) 
	// c.String(200, username)
	
	c.JSON(200, gin.H{
		"username" : username,
	})
	// con.success(c)
}
中间件注意事项 gin默认中间件
  • gin.Default()默认使用了Logger和Recovery中间件,其中:
  • Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release
  • Recovery中间件会recover任何panic,如果有panic的话,为写入500响应码
  • 如果不想使用上面的默认中间件,可以使用gin.New()新建一个没有任何中间件的路由
gin中间件中使用goroutine
  • 当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())
func LoginMiddleWare(c *gin.Context) {
	fmt.Println("login middle ware")
	c.Set("username", "张三")

	// 定义一个goroutine统计日志
	cCp := c.Copy()
	go func ()  {
		time.Sleep(2 * time.Second)
		// 用了c.Request.URL.Path 也没有问题?
		fmt.Println("Done in path " + cCp.Request.URL.Path)
	}()
}
十、Gin 中自定义Model 10.1 关于Model

如果我们的应用非常简单的话,我们可以在Controller 里面处理常见的业务逻辑。但是如果
我们有一个功能想在多个控制器、或者多个模板里面复用的话,那么我们就可以把公共的功
能单独抽取出来作为一个模块(Model)。Model 是逐步抽象的过程,一般我们会在Model
里面封装一些公共的方法让不同Controller 使用,也可以在Model 中实现和数据库打交道

10.2 Model 里面封装公共的方法
  • 新建model/tools.go
package model

import (
	"crypto/md5"
	"fmt"
	"time"
)

//时间戳间戳转换成日期
func UnixToDate(timestamp int) string {
	t := time.Unix(int64(timestamp), 0)
	return t.Format("2006-01-02 15:04:05")
}

//日期转换成时间戳2020-05-02 15:04:05
func DateToUnix(str string) int64 {
	template := "2006-01-02 15:04:05"
	t, err := time.ParseInLocation(template, str, time.Local)
	if err != nil {
		return 0
	}
	return t.Unix()
}

// 获取时间戳
func GetUnix() int64 {
	return time.Now().Unix()
}

// 获取当前日期
func GetDate() string {
	template := "2006-01-02 15:04:05"
	return time.Now().Format(template)
}

// 获取年月日
func GetDay() string {
	template := "20060102"
	return time.Now().Format(template)
}

func Md5(str string) string {
	data := []byte(str)
	return fmt.Sprintf("%xn", md5.Sum(data))
}
十一、Gin 文件上传 十二、Gin 中的Cookie 12.1 Cookie 介绍
  • HTTP 是无状态协议。简单地说,当你浏览了一个页面,然后转到同一个网站的另一个页
    面,服务器无法认识到这是同一个浏览器在访问同一个网站。每一次的访问,都是没有任何
    关系的。如果我们要实现多个页面之间共享数据的话我们就可以使用Cookie 或者Session 实
    现
  • cookie 是存储于访问者计算机的浏览器中。可以让我们用同一个浏览器访问同一个域名
    的时候共享数
12.2 Cookie 能实现的功能
  1. 保持用户登录状态
  2. 保存用户浏览的历史记录
  3. 猜你喜欢,智能推荐
  4. 电商网站的加入购物车
12.3 设置和获取Cookie
  • 前面我们已经使用过ctx.Set("username") 和 ctx.Get("username")来进行数据的保存和共享,但这个使用的只针对是单页面的数据共享,要想实现多页面的共享,就需要Cookie或者Session
  • https://gin-gonic.com/zh-cn/docs/examples/cookie/
12.3.1 设置Cookie

c.SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
其中:
* 第一个参数key
* 第二个参数value
* 第三个参数过期时间.如果只想设置Cookie 的保存路径而不想设置存活时间,可以在第三个参数中传递nil
* 第四个参数cookie 的路径
* 第五个参数cookie 的路径Domain 作用域本地调试配置成localhost , 正式上线配置成域名
* 第六个参数是secure ,当secure 值为true 时,cookie 在HTTP 中是无效,在HTTPS 中才有效
* 第七个参数httpOnly,是微软对COOKIE 做的扩展。如果在COOKIE 中设置了“httpOnly”属性,则通过程序(JS 脚本、applet 等)将无法读取到COOKIE 信息,防止XSS 攻击产生

12.3.2 获取Cookie

cookie, err := c.Cookie("name")

12.3.3 删除Cookie
  • 把第三个参数时间设置为-1
12.3.3 举例
func ApiRouter(r *gin.Engine) {
	apiRouter := r.Group("/api")
	{
		apiRouter.GET("/", func(ctx *gin.Context) {
			// 设置Cookie
			ctx.SetCookie("username", "张三", 3600, "/", "localhost", false, false)
			fmt.Println("首页")
			ctx.String(200, "/api")
		})

		apiRouter.GET("/news", func(ctx *gin.Context) {
			// 获取Cookie
			username, _ := ctx.Cookie("username")
			fmt.Println(username)
			ctx.String(200, "/news/"+username)
		})
	}
}
12.4 多个二级域名共享cookie
  • 我们想的是用户在a.test.com 中设置Cookie 信息后在b.test.com 中获取刚才设置的cookie,也就是实现多个二级域名共享cookie, 这时候的话我们就可以这样设置cookie
    c.SetCookie("usrename", "张三", 3600, "/", ".test.com", false, true)
十三、Gin 中的Session 十四、Gin 中使用GORM 操作mysql 数据库 十五、原生 SQL 和 SQL 生成器 十六、Gin 中使用GORM 实现表关联查询 十七、 GORM 中使用事务 十八、Gin 中使用go-ini 加载.ini 配置文件
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/937836.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号