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()
   }
}
相关推荐
倔强菜鸟2 小时前
2025.11.21-GO语言入门(一)
开发语言·后端·golang
风生u2 小时前
Go的并发(协程)
开发语言·后端·golang
米花町的小侦探2 小时前
Ubuntu安装多版本golang
linux·ubuntu·golang
Tony Bai11 小时前
Go 安全新提案:runtime/secret 能否终结密钥残留的噩梦?
java·开发语言·jvm·安全·golang
卿雪18 小时前
Redis 线程模型:Redis为什么这么快?Redis为什么引入多线程?
java·数据库·redis·sql·mysql·缓存·golang
源代码•宸21 小时前
分布式缓存-GO(项目整体架构简介、Ubuntu 22.04 64位安装GoLang、安装Docker、解决Go module 的依赖问题)
经验分享·分布式·后端·ubuntu·缓存·docker·golang
MC皮蛋侠客21 小时前
Linux安装go及环境配置教程
linux·运维·golang
golang学习记1 天前
Redis Pipeline 实战指南:提升 Go 后端性能的利器
redis·golang·php
kgduu1 天前
go ethreum之Trie
开发语言·后端·golang