go-gin快速入门(2)
1.中间件
- 全局中间件(所有请求都经过此中间件)
- 关键字 Use(自定义func)
- 自定义func 需要返回gin.HandleFunc
- 可以使用Set 设置key,value. 使用Get 获取值
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func main() {
r := gin.Default()
r.Use(Name())
r.GET("/test1", func(c *gin.Context) {
value, _ := c.Get("request") // 获取值
c.JSON(http.StatusOK, gin.H{
"message": "success",
"data": value})
})
r.Run(":8080")
}
func Name() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
fmt.Println("中间件被执行了.")
c.Set("request", "value") // 设置值
status := c.Writer.Status()
fmt.Println("执行状态", status)
t2 := time.Since(t)
fmt.Println("耗时", t2)
}
}
测试代码:
import httpx # httpx第三方库和requests类似,https://www.python-httpx.org/quickstart/
one = httpx.get("http://0.0.0.0:8080/test1")
one.json()
{'data': 'value', 'message': 'success'}
-
局部中间件 和Next() / Abort()
- Next 让程序继续执行,Abort 终止执行
- 在指定func前添加 中间件,只对其产生作用
func main() { // 创建路由 r := gin.New() r.Use(MyLogger()) goodsGroup := r.Group("/goods") { goodsGroup.GET("/test1", func1) goodsGroup.POST("/test2", tokenRequired(), func2) } _ = r.Run(":8081") } func MyLogger() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() c.Set("name", "zap") //给request中的header设置X-Token c.Request.Header.Set("X-Token", "123") //让原来的逻辑继续执行 c.Next() end := time.Since(start) fmt.Println("耗时:", end) status := c.Writer.Status() log.Println(status) } } func func2(context *gin.Context) { v, ok := context.Get("name") if !ok { fmt.Println("name不存在") } context.JSON(http.StatusOK, gin.H{ "code": 200, "data": v}) } func func1(context *gin.Context) { v, ok := context.Get("name") if !ok { fmt.Println("设置的name不存在, ") } context.JSON(http.StatusOK, gin.H{ "code": v}) } func tokenRequired() gin.HandlerFunc { return func(c *gin.Context) { var token string for k, v := range c.Request.Header { fmt.Printf("key:%s, value:%v, type:%T\n", k, v, v) // key:X-Token, value:[123], type:[]string if k == "X-Token" { token = v[0] } } if token != "123" { c.JSON(http.StatusUnauthorized, gin.H{ "mse": "未登录", }) c.Abort() // 结束执行 } // 继续执行后面的逻辑 c.Next() fmt.Println("中间件执行完毕.") } }测试代码:
httpx.get("http://0.0.0.0:8081/goods/test1").text httpx.post("http://0.0.0.0:8081/goods/test2").text
2.cookie练习
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取客户端cookie并校验
if cookie, err := c.Cookie("abc"); err == nil {
if cookie == "123" {
fmt.Println("cookie 验证 通过, cookie:", cookie)
return
}
}
// 否则就是没通过
c.JSON(http.StatusUnauthorized, gin.H{
"err": "验证失败",
})
//验证失败则不用在调用后续的函数处理
c.Abort()
return
}
}
func main() {
r := gin.Default()
r.GET("/login", func(c *gin.Context) {
//设置cookie
c.SetCookie("abc", "123", 60, "/", "localhost", false, true)
c.JSON(http.StatusOK, gin.H{"msg": "success"})
})
r.GET("/home", AuthMiddleware(), func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"msg": "success", "data": "home"})
})
_ = r.Run(":8080")
}
3. 自定义参数验证
-
参考 https://pkg.go.dev/github.com/go-playground/validator/v10#FieldLevel
-
关键点:自定义func, 注册func
package main import ( "fmt" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-playground/validator/v10" "net/http" ) type User struct { Name string `json:"name" binding:"required,NotAdmin"` } func NotAdmin(fl validator.FieldLevel) bool { fmt.Println("验证方法") // 1.先调试 验证进入此方法了 fmt.Println("fl.Field():", fl.Field()) // FieldLevel是一个接口,在此接口实现的方法,其中Field返回字段值 // fl.Field 返回值是反射类型,不能直接比较,就转字符串比较 if fl.Field().Interface().(string) != "admin" { return false } return true } func main() { r := gin.Default() if v, ok := binding.Validator.Engine().(*validator.Validate); ok { // 注册自定义验证规则,两则名称可以不一致,tag 在struct中使用 v.RegisterValidation("NotAdmin", NotAdmin) } r.POST("/1", func(c *gin.Context) { var user User if e := c.BindJSON(&user); e == nil { fmt.Println(user) // 调试代码 c.JSON(http.StatusOK, gin.H{"msg": "success"}) } else { c.JSON(http.StatusBadRequest, gin.H{"msg": "参数错误"}) } }) r.Run(":9999") }测试代码:
httpx.post("http://0.0.0.0:9999/1", json={"name":"admin1"}).json() {'msg': '参数错误'} httpx.post("http://0.0.0.0:9999/1", json={"name":"admin"}).json() {'msg': 'success'}
本文来自博客园,作者:CV-coding,转载请注明原文链接:https://www.cnblogs.com/CV-coding/articles/15458426.html
浙公网安备 33010602011771号