Go: Gin的用法

文章目录

获取参数

路径传参

go 复制代码
func main() {
	e := gin.Default()
	e.GET("/findUser/:username/:userid", FindUser)

	server := e.Run(":8080")
	log.Fatalln(server)
}

func FindUser(context *gin.Context) {
	username := context.Param("username")
	userid := context.Param("userid")
	context.String(http.StatusOK, username, userid)
}

url 传参(查询字符串)

普通解析:

go 复制代码
func test2() {
	e := gin.Default()
	e.GET("/findUser", FindUser2)
	log.Fatalln(e.Run(":8080"))
}

func FindUser2(c *gin.Context) {
	username := c.DefaultQuery("username", "defaultUser")
	userid := c.Query("userid")
	c.String(http.StatusOK,username,userid)
}

参数转成结构体:

go 复制代码
func test2() {
	e := gin.Default()
	e.GET("/findUser", FindUserToStruct)
	log.Fatalln(e.Run(":8080"))
}

func FindUserToStruct(context *gin.Context) {
	var query FindUserQuery
	if err := context.ShouldBindQuery(&query); err != nil {
		return
	}
	fmt.Println(query)
}

post json传参

普通解析:

go 复制代码
func test3() {
	e := gin.Default()
	e.POST("/findUser", FindUser3)
	log.Fatalln(e.Run(":8080"))
}

func FindUser3(context *gin.Context) {
	username := context.PostForm("username")
	password := context.PostForm("password")
	context.String(http.StatusOK, username, password)
}

参数转成结构体:

go 复制代码
func test3() {
	e := gin.Default()
	e.POST("/findUser", PostFindUserToStruct)
	log.Fatalln(e.Run(":8080"))
}

func PostFindUserToStruct(context *gin.Context) {
	var body PostFindUserBody
	if err := context.BindJSON(&body); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(body)
}

type PostFindUserBody struct {
	Name string `json:"username"`
	Age  int    `json:"age"`
}

数据校验

必填类:

go 复制代码
标签	说明
required	必填字段,不能为空
omitempty	可空,空则跳过后续校验
示例:
Name string `json:"name" validate:"required"`
Age  int    `json:"age" validate:"omitempty,min=1"`

字符串长度校验
标签	说明
min=数字	最小长度
max=数字	最大长度
len=数字	固定长度
示例:
Password string `validate:"min=6,max=18"`
Code     string `validate:"len=6"`

数值范围校验
标签	说明
gt=数字	大于
lt=数字	小于
gte=数字	大于等于
lte=数字	小于等于
示例:
Age int `validate:"gte=1,lte=150"`

Gin 中启用 validator
Gin 默认集成 validator,只需要:
if err := c.ShouldBind(&req); err != nil {
    errs := err.(validator.ValidationErrors)
    fmt.Println(errs)
}

例:

go 复制代码
func test4() {
	e := gin.Default()
	e.POST("/testValidator", Register)
	log.Fatalln(e.Run(":8080"))
}

type LoginUser struct {
	Username string `binding:"required"  json:"username" form:"username" uri:"username"`
	Password string `binding:"required" json:"password" form:"password" uri:"password"`
}

func Register(ctx *gin.Context) {
	newUser := &LoginUser{}
	if err := ctx.ShouldBind(newUser); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(*newUser)
}

数据响应

go 复制代码
func FindUser3(context *gin.Context) {
	username := context.PostForm("username")
	password := context.PostForm("password")
	context.String(http.StatusOK, username, password)
}

// JSON方式进行渲染
func (c *Context) JSON(code int, obj any) 

接口分组

go 复制代码
func test5() {
	e := gin.Default()
	
	v1 := e.Group("v1");
	{
		v1.POST("/login", func(c *gin.Context) {})
		v1.POST("/signup", func(c *gin.Context) {})
	}
	v2 := e.Group("v2");
	{
		v2.POST("/v2/login", func(c *gin.Context) {})
		v2.POST("/v2/signup", func(c *gin.Context) {})
	}
}

404路由:匹配不到接口的默认响应

go 复制代码
func test6() {
	e := gin.Default()

	e.NoRoute(func(context *gin.Context) { // 这里只是演示,不要在生产环境中直接返回HTML代码
		context.String(http.StatusNotFound, "查无此接口")
	})
	e.Run(":8080")
}

405路由:请求方法错误

默认情况下,Gin 对 "方法不匹配" 的行为是:

返回 404 Not Found而不是 405,需要开启e.HandleMethodNotAllowed = true

go 复制代码
func test7() {
	e := gin.Default()
	e.HandleMethodNotAllowed = true
	e.GET("/fs", func(c *gin.Context) {})
	// 注册处理器
	e.NoMethod(func(context *gin.Context) {
		context.String(http.StatusMethodNotAllowed, "method not allowed")
	})
	e.Run(":8080")
}

用post访问/fs,则会返回method not allowed

中间件:类似Java的拦截器

全局中间件

全局中间件即作用范围为全局,整个系统所有的请求都会经过此中间件。

go 复制代码
func test8() {
	e := gin.Default()
	e.Use(func(c *gin.Context) {
		fmt.Println("hello", c.Request.RequestURI)
	})
	e.GET("/fs", func(c *gin.Context) {})
	e.Run(":8080")
}

局部中间件

go 复制代码
func test9() {
	e := gin.Default()
	e.Use(func(c *gin.Context) {
		fmt.Println("全局处理器")
	})

	v1 := e.Group("v1", func(c *gin.Context) {
		fmt.Println("v1处理器")
	})
	{
		v1.POST("/fs1", func(c *gin.Context) {})
		v1.POST("/fs2", func(c *gin.Context) {})
	}
	v2 := e.Group("v2")
	{
		v2.POST("/fs3", func(c *gin.Context) {})
		v2.POST("/fs4", func(c *gin.Context) {})
	}
	e.Run(":8080")
}

跨域处理

放到gin.Default().Use(CorsMiddle())即可

go 复制代码
func CorsMiddle() gin.HandlerFunc {
   return func(c *gin.Context) {
      method := c.Request.Method
      origin := c.Request.Header.Get("Origin")
      if origin != "" {
         // 生产环境中的服务端通常都不会填 *,应当填写指定域名
         c.Header("Access-Control-Allow-Origin", origin)
         // 允许使用的HTTP METHOD
         c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
         // 允许使用的请求头
         c.Header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization")
         // 允许客户端访问的响应头
         c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
         // 是否需要携带认证信息 Credentials 可以是 cookies、authorization headers 或 TLS client certificates 
         // 设置为true时,Access-Control-Allow-Origin不能为 *
         c.Header("Access-Control-Allow-Credentials", "true")
      }
      // 放行OPTION请求,但不执行后续方法
      if method == "OPTIONS" {
         c.AbortWithStatus(http.StatusNoContent)
      }
      // 放行
      c.Next()
   }
}
相关推荐
Tony Bai8 小时前
Go 的 AI 时代宣言:我们如何用“老”原则,解决“新”问题?
开发语言·人工智能·后端·golang
L Jiawen9 小时前
【Golang基础】基础知识(下)
服务器·开发语言·golang
apocelipes11 小时前
docker-compose 部署单节点 kafka 4.0 测试环境
docker·golang·kafka·开发工具和环境
先跑起来再说15 小时前
Go 语言的 Mutex 底层实现详解:状态位、CAS、自旋、饥饿模式与信号量
服务器·后端·golang
saber_andlibert15 小时前
【C++转GO】文件操作+协程和管道
开发语言·c++·golang
teamlet18 小时前
naviemail的升级之路-孵化mailrouter
golang
一抹轻笑动人20 小时前
Viger笔记
笔记·golang
昵称为空C1 天前
go+gin 入门指南
go·gin
乐观主义现代人1 天前
gin 框架学习之路
学习·gin
思成Codes1 天前
Go语言的多返回值是如何实现的?
开发语言·后端·golang