导读
本套笔记是为了学习过其他语言框架,想要快速掌握gin框架推行的一套笔记。 虽然为了青训营而制作的一套笔记,但其他想要学go的程序员也可以通过这个上手go世界,后续会带你快速上手gorm,学完这两个之后,简体版抖音基本上就可以独立完成了,后续还会进行大项目的讲解开发,制作不易,喜欢的就点个关注吧。
注意
代码详解大部分是注释的形式给出,请留意代码注释。
Gin框架介绍
导读:Gin是一个非常受欢迎的Golang Web框架,它旨在提供高性能、易用和轻量级的解决方案。
中间件
中间件(Middleware)是在应用程序处理请求和生成响应之间执行的一系列功能组件。它请求到达目标处理程序之前或响应回传给客户端之前,对请求和响应进行预处理或后处理。类似java的拦截器。
大白话:Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数,这个钩子函数就叫中间件。
在 Gin 框架中,gin.HandlerFunc 是一个具有特定签名的函数类型,它接受一个 *gin.Context 参数,并没有返回值。这个函数类型被用作中间件函数和路由处理函数的类型,Gin中的中间件必须是一个gin.HandlerFunc类型。
单独注册中间件
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func get(c *gin.Context) { fmt.Println("get运行了") c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) } //定义一个中间件 func m1(c *gin.Context) { fmt.Println("中间件运行了") } func main() { router := gin.Default() router.GET("/get", m1, get) router.Run(":8080") }
当我们运行之后,发送send,会执行m1,之后执行get。
postman接收到信息
多个中间件
router.GET,后面可以跟很多HandlerFunc方法,这些方法其实都可以叫中间件
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func get(c *gin.Context) { fmt.Println("get运行了") c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) } // 定义一个中间件 func m1(c *gin.Context) { fmt.Println("m1运行了") } func m2(c *gin.Context) { fmt.Println("m2运行了") } func main() { router := gin.Default() router.GET("/get", m1, get,m2) router.Run(":8080") }
运行结果如下
先运行m1,之后运行get,最后运行m2,以此类推,也可以增加更多的中间件
中间件拦截响应
只需要修改m1
// 定义一个中间件 func m1(c *gin.Context) { fmt.Println("m1运行了") //用于终止请求的处理流程并立即返回响应 c.Abort() }
运行结果
可以看到只有m1运行了
中间件放行
使用c.next()进行放行,会直接运行下一个方法,下一个方法运行结束之后运行c.next()之后的方法
修改代码
func get(c *gin.Context) { fmt.Println("get运行了") c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) c.Next() fmt.Println("get再次运行") } // 定义一个中间件 func m1(c *gin.Context) { fmt.Println("m1运行了") c.Next() fmt.Println("m1再次运行") } func m2(c *gin.Context) { fmt.Println("m2运行了") c.Next() fmt.Println("m2再次运行") }
运行结果如图
注意:如果其中一个中间件响应了c.Abort(),后续中间件将不再执行,直接按照顺序走完所有的响应中间件
全局注册中间件
在 Gin 框架中,Use 方法用于将中间件函数注册到全局中间件链中。全局中间件会在每个请求处理之前都被执行,无论请求的路径是什么。使用Use去注册全局中间件,Use接收的参数也是多个HandlerFunc
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func get(c *gin.Context) { fmt.Println("get运行了") c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) c.Next() fmt.Println("get再次运行") } func m10(c *gin.Context) { fmt.Println("m10运行了") } func main() { router := gin.Default() router.Use(m10) router.GET("/get", get) router.POST("/post", get) router.Run(":8080") }
我们使用get和post分别发送请求,m10都会先运行。
中间件传递数据
我们使用c.Get()和c.Set()方法来传递数据
c.Set() 是 Gin 框架中的方法,用于在请求处理过程中设置键值对数据。
c.Get() 是 Gin 框架中的方法,用于获取在请求处理过程中设置的键值对数据。
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func get(c *gin.Context) { name, _ := c.Get("name")//获得数据 fmt.Println(name) c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) c.Next() } func m10(c *gin.Context) { fmt.Println("m10运行了") c.Set("name", "xiaoming") //定义一个数据 } func main() { router := gin.Default() router.Use(m10) router.GET("/get", get) router.Run(":8080") }
运行结果
可以看到成功拿到了数据name
Set()第二个参数是any类型,所有我们可以用它传任意类型,在接收的时候做好断言即可 例如一个结构体
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) type User struct { Name string Age int } //定义user结构体 func get(c *gin.Context) { name, _ := c.Get("user") //获得结构退 fmt.Println(name)//打印结构体 c.JSON(http.StatusOK, gin.H{ "msg": "ok", })//响应信息 c.Next() } func m10(c *gin.Context) { fmt.Println("m10运行了") c.Set("user", User{ Name: "xiaoming", Age: 18, }) 构造结构体user } func main() { router := gin.Default() router.Use(m10) router.GET("/get", get) router.Run(":8080") }
运行结果
路由
路由分组
将一系列的路由放到一个组下,统一管理
package main import ( "github.com/gin-gonic/gin" "net/http" ) func get(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) } func main() { router := gin.Default() r := router.Group("/group") //分组 r.GET("/get", get) r.POST("/post", get) router.Run(":8080") }
这样在postman里面我们如果要发送请求,只需要这样
两个响应的结果都是一样的
路由分组注册中间件
就是在分组后面加上Use就可以了
package main import ( "fmt" "github.com/gin-gonic/gin" "net/http" ) func middle(c *gin.Context) { fmt.Println("middle ...in") } func get(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) } func main() { router := gin.Default() r := router.Group("/group").Use(middle) //分组并且使用全局中间件 r.GET("/get", get) r.POST("/post", get) router.Run(":8080") }
分别发送请求之后
权限验证
以前后端最流行的jwt为例,如果用户登录了,前端发来的每一次请求都会在请求头上携带上token
后台拿到这个token进行校验,验证是否过期,是否非法
如果通过就说明这个用户是登录过的
不通过就说明用户没有登录
package main import ( "github.com/gin-gonic/gin" "net/http" ) //验证jwt令牌是否正确的方法 //每次都要验证 func JwtTokenMiddleware(c *gin.Context) { // 获取请求头的token token := c.GetHeader("token") // 调用jwt的验证函数 if token == "1234" { // 验证通过 c.Next() return } // 验证不通过 c.JSON(200, gin.H{"msg": "权限验证失败"}) c.Abort() } func get(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "msg": "ok", }) } func main() { router := gin.Default() r := router.Group("/group").Use(JwtTokenMiddleware) r.GET("/get", get) r.POST("/post", get) router.Run(":8080") }
我们使用postman发送请求
1: 如果token != 1234
2: 如果token = 1234












