gin 基本使用

gin 初体验

go 复制代码
import (
  "net/http"
  "github.com/gin-gonic/gin"
)

func main() {
  r := gin.Default()
  r.GET("/ping", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{
      "message": "pong",
    })
  })
  r.Run()
}

gin 路由接受一个 type HandlerFunc func(Context) 类型的函数

New 和 Default 的区别

gin.New 和 gin.Default 都可以创建一个类型为 *gin.Engine 的 router

他们的区别是,gin.Default 加了两个中间件:Logger(), Recovery()

路由分组

路由分组功能是将相同功能的路由进行分组,方便管理

go 复制代码
r := gin.Default()
r.GET("/goods/list", goodList)
r.GET("/goods/1", goodDetail)
r.POST("goods/add", createGood)
func goodList(c *gin.Context)   {}
func goodDetail(c *gin.Context) {}
func createGood(c *gin.Context) {}
go 复制代码
r := gin.Default()
goodsGroup := r.Group("/goods")
{
  goodsGroup.GET("/list", goodList)
  goodsGroup.GET("/1", goodDetail)
  goodsGroup.POST("/add", createGood)
}

url 中的变量

要获取 url 中的变量,使用 :xxx 的形式

go 复制代码
func main() {
  r := gin.Default()
  goodsGroup := r.Group("/goods")
  {
    goodsGroup.GET("/:id", goodDetail)
  }
  r.Run()
}

func goodDetail(c *gin.Context) {
  id := c.Param("id")
  c.JSON(http.StatusOK, gin.H{
    "message": "id: " + id,
  })
}

这种形式会有一个问题,如果有两个路由,一个是 /goods/list,一个是 /goods/:id,那么 /goods/list 会被 /goods/:id 匹配到

解决办法是使用 goodsGroup.GET("/list", goodList),这样就不会有问题了

go 复制代码
func main() {
  r := gin.Default()
  goodsGroup := r.Group("/goods")
  {
    goodsGroup.GET("/list", goodList)
    goodsGroup.GET("/:id", goodDetail)
  }
  r.Run()
}

func goodList(c *gin.Context) {
  c.JSON(http.StatusOK, gin.H{
    "message": "list",
  })
}

func goodDetail(c *gin.Context) {
  id := c.Param("id")
  c.JSON(http.StatusOK, gin.H{
    "message": "id: " + id,
  })
}

但是其他路由还是会进入到 /goods/:id 中,比如 /goods/detail

如果只想匹配 id 是数字,需要这样做

通过一个结构体来绑定 uri 中的参数,在注册函数中使用 ShouldBindUri 方法来绑定,如果不是绑定的类型,就返回错误

go 复制代码
type Params struct {
	ID int `uri:"id" binding:"required"`
}

func main() {
	r := gin.Default()
	goodsGroup := r.Group("/goods")
	{
		goodsGroup.GET("/:id", goodDetail)
	}

	r.Run()
}
func goodDetail(c *gin.Context) {
	id := c.Param("id")
	var params Params
	if err := c.ShouldBindUri(&params); err != nil {
		c.Status(http.StatusBadRequest)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"message": "id: " + id,
	})
}

还有一种形式是使用 * 来匹配,比如 /goods/*name

如果访问的路由是 /goods/1/2/3/4,那么 id 就是 1,name 就是 /2/3/4,一般用来访问服务器上的文件

go 复制代码
goodsGroup.GET("/:id/*name", goodPersoon)
func goodPerson(c *gin.Context) {
  id := c.Param("id")
  name := c.Param("name")
  c.JSON(http.StatusOK, gin.H{
    "id": id,
    "name": name,
  })
}

获取请求中的参数

获取 query 参数,可以使用 c.Query("key"),如果没有这个参数,就返回空字符串

如果想要获取 query 参数,但是没有这个参数,就返回默认值,可以使用 c.DefaultQuery("key", "default")

go 复制代码
page := c.DefaultQuery("page", "1")
size := c.Query("size")

获取 body 参数,可以使用 c.PostForm("key"),如果没有这个参数,就返回空字符串

如果想要获取 body 参数,但是没有这个参数,就返回默认值,可以使用 c.DefaultPostForm("key", "default")

go 复制代码
name := c.DefaultPostForm("name", "default")
age := c.PostForm("age")

PostForm 是针对 Content-Type 是 application/x-www-form-urlencoded 和 application/form-data 的情况

如果请求参数是 application/json,那么需要使用 c.ShouldBindJSON/c.BindJSON 方法来获取参数

go 复制代码
type Body struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

func goodAdd(c *gin.Context) {
	var body Body
	c.BindJSON(&body)
	c.JSON(http.StatusOK, gin.H{
		"name": body.Name,
		"age":  body.Age,
	})
}

表单验证

表单验证可以直接使用 binding 标签来实现

gin 内置了 validator,文档:validator

注册时,需要输入两次密码,可以使用 eqfield 来验证两次密码是否一致

go 复制代码
type SignUpForm struct {
  Age        uint8  `json:"age" binding:"required,gte=1,lte=130"`
  Name       string `json:"name" binding:"required,min=3"`
  Email      string `json:"email" binding:"required,email"`
  Password   string `json:"password" binding:"required"`
  RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}
r.POST("/signup", func(c *gin.Context) {
  var signUpFrom SignUpForm
  if err := c.ShouldBindJSON(&signUpFrom); err != nil {
    c.JSON(http.StatusBadRequest, gin.H{
      "error": err.Error(),
    })
    return
  }
  c.JSON(http.StatusOK, gin.H{
    "message": "ok",
  })
})
相关推荐
0x派大星2 天前
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
开发语言·后端·golang·go·json·gin
get2002 天前
Gin 框架中间件详细介绍
中间件·gin
bigbig猩猩2 天前
Gin 框架中的表单处理与数据绑定
驱动开发·gin
荣~博客2 天前
Golang语言整合jwt+gin框架实现token
开发语言·golang·gin
拧螺丝专业户3 天前
gin源码阅读(2)请求体中的JSON参数是如何解析的?
前端·json·gin
留乘船3 天前
使用gin -gorm-jwt-中间件拦截的一个小项目
开发语言·学习·中间件·golang·gin
0x派大星4 天前
【Golang】——Gin 框架中的模板渲染详解
开发语言·后端·golang·go·gin
0x派大星5 天前
【Golang】——Gin 框架中的表单处理与数据绑定
开发语言·后端·golang·go·gin
杜杜的man5 天前
【go从零单排】gin+gorm理解及实现CRUD
开发语言·golang·gin
杨若瑜6 天前
Go语言24小时极速学习教程(五)Go语言中的SpringMVC框架——Gin
学习·golang·gin