Go gin框架入门教程
1. 介绍
Gin 是一个用 Golang编写的 高性能的web 框架, 由于http路由的优化,速度提高了近 40 倍。 Gin的特点就是封装优雅、API友好。
Gin的一些特性:
-
快速 基于 Radix 树的路由,小内存占用。没有反射。可预测的 API 性能。
-
支持中间件 传入的 HTTP 请求可以由一系列中间件和最终操作来处理。 例如:Logger,Authorization,GZIP,最终操作 DB。
-
Crash 处理 Gin 可以 catch 一个发生在 HTTP 请求中的 panic 并 recover 它。这样,你的服务器将始终可用。例如,你可以向 Sentry 报告这个 panic!
-
JSON 验证 Gin 可以解析并验证请求的 JSON,例如检查所需值的存在。
-
路由组 更好地组织路由。是否需要授权,不同的 API 版本…… 此外,这些组可以无限制地嵌套而不会降低性能。
-
错误管理 Gin 提供了一种方便的方法来收集 HTTP 请求期间发生的所有错误。最终,中间件可以将它们写入日志文件,数据库并通过网络发送。
-
内置渲染 Gin 为 JSON,XML 和 HTML 渲染提供了易于使用的 API。
-
可扩展性 新建一个中间件非常简单。
2.安装包
提示:依赖 Go 1.6 及以上版本
下载并安装 gin
go get -u github.com/gin-gonic/gin
3.一个简单http server的例子
package main
// 导入gin包
import "github.com/gin-gonic/gin"
// 入口函数
func main() {
// 初始化一个http服务对象
r := gin.Default()
// 设置一个get请求的路由,url为/ping, 处理函数(或者叫控制器函数)是一个闭包函数。
r.GET("/ping", func(c *gin.Context) {
// 通过请求上下文对象Context, 直接往客户端返回一个json
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}
将代码保存至demo.go文件中,然后, 执行 go run demo.go 命令来运行代码, 然后就可以通过localhost:8080/ping 访问了。
4.项目结构
实际项目业务功能和模块会很多,我们不可能把所有代码都写在一个go文件里面或者写在一个main入口函数里面;我们需要对项目结构做一些规划,方便维护代码以及扩展。
Gin框没有对项目结构做出限制,我们可以根据自己项目需要自行设计。
这里给出一个典型的MVC框架大致的项目结构的例子,大家可以参考下:
├── conf #项目配置文件目录
│ └── config.toml #大家可以选择自己熟悉的配置文件管理工具包例如:toml、xml等等
├── controllers #控制器目录,按模块存放控制器(或者叫控制器函数),必要的时候可以继续划分子目录。
│ ├── food.go
│ └── user.go
├── main.go #项目入口,这里负责Gin框架的初始化,注册路由信息,关联控制器函数等。
├── models #模型目录,负责项目的数据存储部分,例如各个模块的Mysql表的读写模型。
│ ├── food.go
│ └── user.go
├── static #静态资源目录,包括Js,css,jpg等等,可以通过Gin框架配置,直接让用户访问。
│ ├── css
│ ├── images
│ └── js
├── logs #日志文件目录,主要保存项目运行过程中产生的日志。
└── views #视图模板目录,存放各个模块的视图模板,当然有些项目只有api,是不需要视图部分,可以忽略这个目录
└── index.html
5.Gin框架运行模式
为方便调试,Gin 框架在运行的时候默认是debug模式,在控制台默认会打印出很多调试日志,上线的时候我们需要关闭debug模式,改为release模式。
设置Gin框架运行模式:
5.1.通过环境变量设置
export GIN_MODE=release
GIN_MODE环境变量,可以设置为debug或者release
5.2.通过代码设置
在main函数,初始化gin框架的时候执行下面代码
// 设置 release模式
gin.SetMode(gin.ReleaseMode)
// 或者 设置debug模式
gin.SetMode(gin.DebugMode)
Gin路由与控制器
1.概述
路由是一个过程,指的是一个http请求,如何找到对应的处理器函数(也可以叫控制器函数),Gin框架的路由是基于httprouter包实现的。
控制器函数主要负责执行http请求-响应任务。
一个简单的例子:
r := gin.Default()
// 路由定义post请求, url路径为:/user/login, 绑定doLogin控制器函数
r.POST("/user/login", doLogin)
// 控制器函数
func doLogin(c *gin.Context) {
// 获取post请求参数
username := c.PostForm("username")
password := c.PostForm("password")
// 通过请求上下文对象Context, 直接往客户端返回一个字符串
c.String(200, "username=%s,password=%s", username,password)
}
2.路由规则
一条路由规则由三部分组成:
-
http请求方法
-
url路径
-
控制器函数
1.http请求方法
常用的http请求方法有下面4种:
-
GET
-
POST
-
PUT
-
DELETE
2.url路径
echo框架,url路径有三种写法:
-
静态url路径
-
带路径参数的url路径
-
带星号(*)模糊匹配参数的url路径
下面看下各种url路由的例子
// 例子1, 静态Url路径, 即不带任何参数的url路径
/users/center
/user/111
/food/12
// 例子2,带路径参数的url路径,url路径上面带有参数,参数由冒号(:)跟着一个字符串定义。
// 路径参数值可以是数值,也可以是字符串
//定义参数:id, 可以匹配/user/1, /user/899 /user/xiaoli 这类Url路径
/user/:id
//定义参数:id, 可以匹配/food/2, /food/100 /food/apple 这类Url路径
/food/:id
//定义参数:type和:page, 可以匹配/foods/2/1, /food/100/25 /food/apple/30 这类Url路径
/foods/:type/:page
// 例子3. 带星号(*)模糊匹配参数的url路径
// 星号代表匹配任意路径的意思, 必须在*号后面指定一个参数名,后面可以通过这个参数获取*号匹配的内容。
//以/foods/ 开头的所有路径都匹配
//匹配:/foods/1, /foods/200, /foods/1/20, /foods/apple/1
/foods/*path
//可以通过path参数获取*号匹配的内容。
3.控制器函数
控制器函数定义:
func HandlerFunc(c *gin.Context)
控制器函数接受一个上下文参数。 可以通过上下文参数,获取http请求参数,响应http请求。
4.路由定义例子
//实例化gin实例对象。
r := gin.Default()
//定义post请求, url路径为:/users, 绑定saveUser控制器函数
r.POST("/users", saveUser)
//定义get请求,url路径为:/users/:id (:id是参数,例如: /users/10, 会匹配这个url模式),绑定getUser控制器函数
r.GET("/users/:id", getUser)
//定义put请求
r.PUT("/users/:id", updateUser)
//定义delete请求
r.DELETE("/users/:id", deleteUser)
//控制器函数实现
func saveUser(c *gin.Context) {
...忽略实现...
}
func getUser(c *gin.Context) {
...忽略实现...
}
func updateUser(c *gin.Context) {
...忽略实现...
}
func deleteUser(c *gin.Context) {
...忽略实现...
}
提示:实际项目开发中不要把路由定义和控制器函数都写在一个go文件,不方便维护,可以参考第一章的项目结构,规划自己的业务模块。
3.分组路由
在做api开发的时候,如果要支持多个api版本,我们可以通过分组路由来实现api版本处理。
例子:
func main() {
router := gin.Default()
// 创建v1组
v1 := router.Group("/v1")
{
// 在v1这个分组下,注册路由
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
// 创建v2组
v2 := router.Group("/v2")
{
// 在v2这个分组下,注册路由
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
router.Run(":8080")
}
上面的例子将会注册下面的路由信息:
-
/v1/login
-
/v1/submit
-
/v1/read
-
/v2/login
-
/v2/submit
-
/v2/read
路由分组,其实就是设置了同一类路由的url前缀。
Gin如何处理请求参数
本章介绍Gin框架获取请求参数的方式
1.获取Get 请求参数
Get请求url例子:/path?id=1234&name=Manu&value=111
获取Get请求参数的常用函数:
-
func (c *Context) Query(key string) string
-
func (c *Context) DefaultQuery(key, defaultValue string) string
-
func (c *Context) GetQuery(key string) (string, bool)
例子:
func Handler(c *gin.Context) {
//获取name参数, 通过Query获取的参数值是String类型。
name := c.Query("name")
//获取name参数, 跟Query函数的区别是,可以通过第二个参数设置默认值。
name := c.DefaultQuery("name", "tizi365")
//获取id参数, 通过GetQuery获取的参数值也是String类型,
// 区别是GetQuery返回两个参数,第一个是参数值,第二个参数是参数是否存在的bool值,可以用来判断参数是否存在。
id, ok := c.GetQuery("id")
if !ok {
// 参数不存在
}
}
提示:GetQuery函数,判断参数是否存在的逻辑是,参数值为空,参数也算存在,只有没有提交参数,才算参数不存在。
2.获取Post请求参数
获取Post请求参数的常用函数:
-
func (c *Context) PostForm(key string) string
-
func (c *Context) DefaultPostForm(key, defaultValue string) string
-
func (c *Context) GetPostForm(key string) (string, bool)
例子:
func Handler(c *gin.Context) {
//获取name参数, 通过PostForm获取的参数值是String类型。
name := c.PostForm("name")
// 跟PostForm的区别是可以通过第二个参数设置参数默认值
name := c.DefaultPostForm("name", "tizi365")
//获取id参数, 通过GetPostForm获取的参数值也是String类型,
// 区别是GetPostForm返回两个参数,第一个是参数值,第二个参数是参数是否存在的bool值,可以用来判断参数是否存在。
id, ok := c.GetPostForm("id")
if !ok {
// 参数不存在
}
}
3.获取URL路径参数
获取URL路径参数,指的是获取 /user/:id 这类型路由绑定的参数,这个例子绑定了一个参数id。
获取url路径参数常用函数:
-
func (c *Context) Param(key string) string
例子:
r := gin.Default()
r.GET("/user/:id", func(c *gin.Context) {
// 获取url参数id
id := c.Param("id")
})
4.将请求参数绑定到struct对象
前面获取参数的方式都是一个个参数的读取,比较麻烦,Gin框架支持将请求参数自动绑定到一个struct对象,这种方式支持Get/Post请求,也支持http请求body内容为json/xml格式的参数。
例子:
下面例子是将请求参数绑定到User struct对象。
// User 结构体定义
type User struct {
Name string `json:"name" form:"name"`
Email string `json:"email" form:"email"`
}
通过定义struct字段的标签,定义请求参数和struct字段的关系。 下面对User的Name字段的标签进行说明。
struct标签说明:
标签 | 说明 |
---|---|
json:"name" | 数据格式为json格式,并且json字段名为name |
form:"name" | 表单参数名为name |
提示:你可以根据自己的需要选择支持的数据类型,例如需要支持json数据格式,可以这样定义字段标签: json:"name"
下面看下控制器代码:
r.POST("/user/:id", func(c *gin.Context) {
// 初始化user struct
u := User{}
// 通过ShouldBind函数,将请求参数绑定到struct对象, 处理json请求代码是一样的。
// 如果是post请求则根据Content-Type判断,接收的是json数据,还是普通的http请求参数
if c.ShouldBind(&u) == nil {
// 绑定成功, 打印请求参数
log.Println(u.Name)
log.Println(u.Email)
}
// http 请求返回一个字符串
c.String(200, "Success")
})
提示:如果你通过http请求body传递json格式的请求参数,并且通过post请求的方式提交参数,则需要将Content-Type设置为application/json, 如果是xml格式的数据,则设置为application/xml
5.Gin如何获取客户ip
r := gin.Default()
r.GET("/ip", func(c *gin.Context) {
// 获取用户IP
ip := c.ClientIP()
})
Gin处理请求结果
本章介绍处理完http请求后如何响应请求,Gin框架支持以字符串、json、xml、文件等格式响应请求。
gin.Context上下文对象支持多种返回处理结果,下面分别介绍不同的响应方式。
1.以字符串方式响应请求
通过String函数返回字符串。
函数定义:
func (c *Context) String(code int, format string, values ...interface{})
参数说明:
参数 | 说明 |
---|---|
code | http状态码 |
format | 返回结果,支持类似Sprintf函数一样的字符串格式定义,例如,%d 代表插入整数,%s代表插入字符串 |
values | 任意个format参数定义的字符串格式参数 |
例子:
func Handler(c *gin.Context) {
// 例子1:
c.String(200, "欢迎访问tizi360.com!")
// 例子2: 这里定义了两个字符串参数(两个%s),后面传入的两个字符串参数将会替换对应的%s
c.String(200,"欢迎访问%s, 你是%s", "tizi360.com!","最靓的仔!")
}
提示: net/http包定义了多种常用的状态码常量,例如:http.StatusOK == 200, http.StatusMovedPermanently == 301, http.StatusNotFound == 404等,具体可以参考net/http包
2.以json格式响应请求
我们开发api接口的时候常用的格式就是json,下面是返回json格式数据的例子
// User 定义
type User struct {
Name string `json:"name"` // 通过json标签定义struct字段转换成json字段的名字。
Email string `json:"email"`
}
// Handler 控制器
func(c *gin.Context) {
//初始化user对象
u := &User{
Name: "tizi365",
Email: "tizi@tizi365.com",
}
//返回json数据
//返回结果:{"name":"tizi365", "email":"tizi@tizi365.com"}
c.JSON(200, u)
}
3.以xml格式响应请求
// User 定义, 默认struct的名字就是xml的根节点名字,这里转换成xml后根节点的名字为User.
type User struct {
Name string `xml:"name"` // 通过xml标签定义struct字段转换成xml字段的名字。
Email string `xml:"email"`
}
// Handler 控制器
func(c *gin.Context) {
//初始化user对象
u := &User{
Name: "tizi365",
Email: "tizi@tizi365.com",
}
//返回xml数据
//返回结果:
// <?xml version="1.0" encoding="UTF-8"?>
// <User><name>tizi365</name><email>tizi@tizi365.com</email></User>
c.XML(200, u)
}
4.以文件格式响应请求
下面介绍gin框架如何直接返回一个文件,可以用来做文件下载。
例子1:
func(c *gin.Context) {
//通过File函数,直接返回本地文件,参数为本地文件地址。
//函数说明:c.File("文件路径")
c.File("/var/www/1.jpg")
}
例子2:
func(c *gin.Context) {
//通过FileAttachment函数,返回本地文件,类似File函数,区别是可以指定下载的文件名。
//函数说明: c.FileAttachment("文件路径", "下载的文件名")
c.FileAttachment("/var/www/1.jpg", "1.jpg")
}
5.设置http响应头(设置Header)
func(c *gin.Context) {
//设置http响应 header, key/value方式,支持设置多个header
c.Header("site","tizi365")
}
Gin框架 html模板处理
Gin 框架默认封装了golang内置的html/template包用于处理html模版,如果你开发的是接口服务,不提供html页面可以跳过本章内容。
前置技术知识点:
-
模板引擎 - 点击Go模板引擎教程,学习完整的模板引擎语法。
1.返回html结果的例子
func main() {
// 初始化gin对象
router := gin.Default()
// 首先加载templates目录下面的所有模版文件,模版文件扩展名随意
router.LoadHTMLGlob("templates/*")
// 绑定一个url路由 /index
router.GET("/index", func(c *gin.Context) {
// 通过HTML函数返回html代码
// 第二个参数是模版文件名字
// 第三个参数是map类型,代表模版参数
// gin.H 是map[string]interface{}类型的别名
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "Main website",
})
})
// 启动http服务,并且绑定在8080端口
router.Run(":8080")
}
模版代码
文件名:templates/index.html
<html>
<h1>
{{ .title }}
</h1>
</html>
2.处理模版子目录的情况
一般在项目中,因为有多个模块的模版文件,我们都会以多个子目录的方式来组织模版文件,上面的例子只能加载某个目录下面的模版文件,无法加载子目录的模版文件。
例子:
func main() {
router := gin.Default()
// 加载templates目录下面的所有模版文件,包括子目录
// **/* 代表所有子目录下的所有文件
router.LoadHTMLGlob("templates/**/*")
router.GET("/posts/index", func(c *gin.Context) {
// 子目录的模版文件,需要加上目录名,例如:posts/index.tmpl
c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
"title": "Posts",
})
})
router.GET("/users/index", func(c *gin.Context) {
// 子目录的模版文件,需要加上目录名,例如:users/index.tmpl
c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
"title": "Users",
})
})
router.Run(":8080")
}
模版文件:templates/posts/index.tmpl
{{ define "posts/index.tmpl" }}
<html><h1>
{{ .title }}
</h1>
<p>Using posts/index.tmpl</p>
</html>
{{ end }}
模版文件:templates/users/index.tmpl
{{ define "users/index.tmpl" }}
<html><h1>
{{ .title }}
</h1>
<p>Using users/index.tmpl</p>
</html>
{{ end }}
Gin框架如何访问静态资源文件
如果项目中包含js、css、jpg之类的静态文件,怎么访问访问静态文件?
下面例子介绍如何处理访问静态资源文件:
func main() {
router := gin.Default()
// 设置静态资源文件目录,并且绑定一个Url前缀
// 静态资源文件目录:/var/www/tizi365/assets
// /assets是访问静态资源的url前缀
// 例如:
// /assets/images/1.jpg 这个url文件,存储在/var/www/tizi365/assets/images/1.jpg
router.Static("/assets", "/var/www/tizi365/assets")
// 为单个静态资源文件,绑定url
// 这里的意思就是将/favicon.ico这个url,绑定到./resources/favicon.ico这个文件
router.StaticFile("/favicon.ico", "./resources/favicon.ico")
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
提示:设置/favicon.ico这个url,其实就是为网站设置图标,浏览器默认会将这个url作为网站默认图标。
Gin框架如何处理cookie
cookie通常用于在浏览器中保存一些小数据,例如客户标识、用户非铭感数据。注意别使用cookie保存隐私数据。
gin框架主要通过上下文对象提供的SetCookie和Cookie两个函数操作cookie
1.设置cookie
例子:
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
// 设置cookie
c.SetCookie("site_cookie", "cookievalue", 3600, "/", "localhost", false, true)
})
router.Run()
SetCookie函数定义:
func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
参数说明:
参数名 | 类型 | 说明 |
---|---|---|
name | string | cookie名字 |
value | string | cookie值 |
maxAge | int | 有效时间,单位是秒,MaxAge=0 忽略MaxAge属性,MaxAge<0 相当于删除cookie, 通常可以设置-1代表删除,MaxAge>0 多少秒后cookie失效 |
path | string | cookie路径 |
domain | string | cookie作用域 |
secure | bool | Secure=true,那么这个cookie只能用https协议发送给服务器 |
httpOnly | bool | 设置HttpOnly=true的cookie不能被js获取到 |
2.读取cookie
func Handler(c *gin.Context) {
// 根据cookie名字读取cookie值
data, err := c.Cookie("site_cookie")
if err != nil {
// 直接返回cookie值
c.String(200,data)
return
}
c.String(200,"not found!")
}
3.删除coolie
通过将cookie的MaxAge设置为-1, 达到删除cookie的目的。
func Handler(c *gin.Context) {
// 设置cookie MaxAge设置为-1,表示删除cookie
c.SetCookie("site_cookie", "cookievalue", -1, "/", "localhost", false, true)
c.String(200,"删除cookie演示")
}
Gin框架实现文件上传
后端代码:
package main
// 导入gin包
import (
"fmt"
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func main() {
router := gin.Default()
// 设置文件上传大小限制,默认是32m
router.MaxMultipartMemory = 64 << 20 // 64 MiB
router.POST("/upload", func(c *gin.Context) {
// 获取上传文件,返回的是multipart.FileHeader对象,代表一个文件,里面包含了文件名之类的详细信息
// file是表单字段名字
file, _ := c.FormFile("file")
// 打印上传的文件名
log.Println(file.Filename)
// 将上传的文件,保存到./data/1111.jpg 文件中
c.SaveUploadedFile(file, "./data/1111.jpg")
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
router.Run(":8080")
}
html代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Single file upload</title>
</head>
<body>
<h1>上传文件演示</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
文件: <input type="file" name="file"><br><br>
<input type="submit" value="上传文件">
</form>
</body>
</html>
Gin框架中间件
在Gin框架中,中间件(Middleware)指的是可以拦截http请求-响应生命周期的特殊函数,在请求-响应生命周期中可以注册多个中间件,每个中间件执行不同的功能,一个中间执行完再轮到下一个中间件执行。
中间件的常见应用场景如下:
-
请求限速
-
api接口签名处理
-
权限校验
-
统一错误处理
提示:如果你想拦截所有请求做一些事情都可以开发一个中间件函数去实现。
Gin支持设置全局中间件和针对路由分组设置中间件,设置全局中间件意思就是会拦截所有请求,针对分组路由设置中间件,意思就是仅对这个分组下的路由起作用。
1.使用中间件
func main() {
r := gin.New()
// 通过use设置全局中间件
// 设置日志中间件,主要用于打印请求日志
r.Use(gin.Logger())
// 设置Recovery中间件,主要用于拦截paic错误,不至于导致进程崩掉
r.Use(gin.Recovery())
// 忽略后面代码
}
2.自定义中间件
下面通过一个例子,了解如果自定义一个中间件
package main
// 导入gin包
import (
"github.com/gin-gonic/gin"
"log"
"time"
)
// 自定义个日志中间件
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
// 可以通过上下文对象,设置一些依附在上下文对象里面的键/值数据
c.Set("example", "12345")
// 在这里处理请求到达控制器函数之前的逻辑
// 调用下一个中间件,或者控制器处理函数,具体得看注册了多少个中间件。
c.Next()
// 在这里可以处理请求返回给用户之前的逻辑
latency := time.Since(t)
log.Print(latency)
// 例如,查询请求状态吗
status := c.Writer.Status()
log.Println(status)
}
}
func main() {
r := gin.New()
// 注册上面自定义的日志中间件
r.Use(Logger())
r.GET("/test", func(c *gin.Context) {
// 查询我们之前在日志中间件,注入的键值数据
example := c.MustGet("example").(string)
// it would print: "12345"
log.Println(example)
})
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}
Gin框架如何处理session
在Gin框架中,我们可以依赖gin-contrib/sessions中间件处理session。
gin-contrib/sessions中间件支持的存储引擎:
-
cookie
-
memstore
-
redis
-
memcached
-
mongodb
下面介绍session的用法
1.安装session包
go get github.com/gin-contrib/sessions
2.基本的session用法
package main
import (
// 导入session包
"github.com/gin-contrib/sessions"
// 导入session存储引擎
"github.com/gin-contrib/sessions/cookie"
// 导入gin框架包
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 创建基于cookie的存储引擎,secret11111 参数是用于加密的密钥
store := cookie.NewStore([]byte("secret11111"))
// 设置session中间件,参数mysession,指的是session的名字,也是cookie的名字
// store是前面创建的存储引擎,我们可以替换成其他存储引擎
r.Use(sessions.Sessions("mysession", store))
r.GET("/hello", func(c *gin.Context) {
// 初始化session对象
session := sessions.Default(c)
// 通过session.Get读取session值
// session是键值对格式数据,因此需要通过key查询数据
if session.Get("hello") != "world" {
// 设置session数据
session.Set("hello", "world")
// 删除session数据
session.Delete("tizi365")
// 保存session数据
session.Save()
// 删除整个session
// session.Clear()
}
c.JSON(200, gin.H{"hello": session.Get("hello")})
})
r.Run(":8000")
}
2.基于redis存储引擎的session
如果我们想将session数据保存到redis中,只要将session的存储引擎改成redis即可。
使用redis作为存储引擎的例子:
首先安装redis存储引擎的包
go get github.com/gin-contrib/sessions/redis
例子:
package main import ( "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/redis" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // 初始化基于redis的存储引擎 // 参数说明: // 第1个参数 - redis最大的空闲连接数 // 第2个参数 - 数通信协议tcp或者udp // 第3个参数 - redis地址, 格式,host:port // 第4个参数 - redis密码 // 第5个参数 - session加密密钥 store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret")) r.Use(sessions.Sessions("mysession", store)) r.GET("/incr", func(c *gin.Context) { session := sessions.Default(c) var count int v := session.Get("count") if v == nil { count = 0 } else { count = v.(int) count++ } session.Set("count", count) session.Save() c.JSON(200, gin.H{"count": count}) }) r.Run(":8000") }