做好每一件事,读好每一本书,天道酬勤
GIN学习
2022-01-14 / 8 min read

详细的学习gin的知识点,不是第一次学习了,这次梳理一个学习的文档出来

第一个gin程序

 这里我们开始演示一下gin的开始程序,也就是快速入门。
 我们来看一下代码:
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

这里我们详细的拆分一下这个代码,

导包

这里我们可以使用go mod进行包的导入

代码细节

第一行代码

	r := gin.Default()

这个一行代码,就是产生了一个gin的实例
然后后面进行操作,

r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

这里面首先有一个GET方法,对于这个GET方法我们首先来看一下它的源码

// GET is a shortcut for router.Handle("GET", path, handle).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodGet, relativePath, handlers)
}

看到源码我们可以看到里面的参数,首先第一个参数就是注册的路径,然后第二个就是处理器的注册。
在这里我们注册的是一个匿名函数。当然我们也可以修改成:


func  pong(c *gin.Context)  {
	c.JSON(200, gin.H{
		"message": "pong",
	})
}
func main() {
	r := gin.Default()
	r.GET("/ping", pong)
	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

在这里我们需要注意的就是这个函数的类型要是:func (c *gin.Context)
然后我们可以发现在传递参数的里面,我们使用的是gin.H
我们点开它的源码:

// H is a shortcut for map[string]interface{}
type H map[string]interface{}

我们看到了它就是一个map类型,因为在gin中经常使用的原因,所以开发者对它进行了封装。这样我们使用起来就更加的方便。

gin中new和Default的不同

在这里我们介绍两个方法,他们返回回来的都是一个*Engine
那么它们有什么不一样呢,在这里我们要知道的是不一样的点是使用Default后它会默认开启两个中间件,一个是recover一个是logger。

路由分组和URL

在我们的开发中,我们为了程序的可读性,我们一般会把路由进行分组。
也是为了后期更好的寻找路由。
那么我们如何进行分组呢?
我们使用的是Group方法。

package main

import "github.com/gin-gonic/gin"

func  pong(c *gin.Context)  {
	c.JSON(200, gin.H{
		"message": "pong",
	})
}
//演示分组
func main() {
	r := gin.Default()
    group := r.Group("/v1")
	{
		group.GET("/ping", pong)
	}

	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

获取url参数

这里我们通过url传入参数,那么我们怎么操作呢?

package main

import "github.com/gin-gonic/gin"

func  pong(c *gin.Context)  {
	id := c.Param("id")
	c.JSON(200, gin.H{
		"message": id,
	})
}
//演示分组
func main() {
	r := gin.Default()
    group := r.Group("/v1")
	{
		group.GET("/:id", pong)
	}

	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

但是呢我们可以发现这个东西是有问题的,我们这里设定的是id,按照我们常识这里,我们知道id一般来说是数字,但是这里不管是数值还是什么都可以传输。
那么我们怎么进行限制呢?
这里我们运用到了之后的表单验证的方式。

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type Person struct {
	ID string `uri:"id" binding:"required,uuid"`
	Name string `uri:"name" binding:"required"`
}
func main() {
	r := gin.Default()
    r.GET("/:name/:id", func(context *gin.Context) {
		var person Person
		if err := context.ShouldBindUri(&person);err != nil{
		context.Status(404)
		return
		}
		context.JSON(http.StatusOK,gin.H{
			"name":person.Name,
			"id":person.ID,
		})
	})

	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

获取GET和POST参数

这两种方式是我们比较常见的方式。那么下面我们详细的说明一下

GET

使用到的方法有两个一个是DefaultQuery和Query。这两个方法的区别在于,前者是可以有默认值的,后者不能设置默认值

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
    r.GET("/name",name)

	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

func name(c *gin.Context){
	name := c.DefaultQuery("name","lzz")
	c.JSON(http.StatusOK,gin.H{
		"name":name,
	})
}

POST

在post中我们要取出参数,我们也有两个方法,两个方法的区别和上面是一样的。
分别是DefaultPostForm和PostForm。

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
    r.POST("/postname",Postname)
	r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

func Postname(c *gin.Context) {
	posrname := c.DefaultPostForm("name","lzz")
	c.JSON(http.StatusOK,gin.H{
		"name":posrname,
	})
}

关于gin表单验证

 我们在做web开发的时候,肯定是会遇见表单验证的需求的,表单验证也是为了一定的安全性。

关于表单验证这里我们直接上代码,详情可以查看官方文档。

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

type LoginForm struct {
	User string `form:"user1" json:"user" binding:"required,min=3,max=10"`
	Password string `form:"password" json:"password" binding:"required"`
}

type SignUpForm struct {
	Age        uint8  `form:"age" json:"age" binding:"gte=1,lte=130"`
	Name       string `form:"name" binding:"required,min=3"`
	Email      string `form:"email" binding:"required,email"`
	Password   string `form:"password" binding:"required"`
	RePassword string `form:"re_password" binding:"required,eqfield=Password"`
}
func main() {
   router := gin.Default()
   router.POST("/login", func(c *gin.Context) {
	   var login LoginForm
	  if  err := c.ShouldBind(&login);err != nil{
		  fmt.Println(err.Error())
		 c.JSON(http.StatusBadRequest,gin.H{
			  "err": err.Error(),
		  })
		  return
	  }
		  c.JSON(http.StatusOK,gin.H{
			  "msg":"登录成功",
		  })
   })
   router.POST("/sigin", func(context *gin.Context) {
	var siginUpForm  SignUpForm
	if err := context.ShouldBind(&siginUpForm); err != nil{
		fmt.Println(err.Error())
		context.JSON(http.StatusBadRequest,gin.H{
			"err":err.Error(),
		})
		return
	}
	context.JSON(http.StatusOK,gin.H{
		"msg":"成功",
	})
   })
   router.Run()
}