• gin-gonic/gin使用详解


    ​ Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架, 由于 httprouter,速度提高了近 40 倍。如果你需要极好的性能,使用 Gin 吧。

    ​ gin的github地址:https://github.com/gin-gonic/gin

    ​ 在项目中使用gin框架只需要下面三步:

    ​ 第一步:运行下面指令安装gin(注意go的版本要在1.15以上)

    go get -u github.com/gin-gonic/gin
    
    • 1

    ​ 第二步:在项目中导入包

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

    ​ 第三步:一般情况下,还需要导入net/http

    import "net/http"
    
    • 1

    1 编写一个例子

    ​ 我们编写一个例子,代码内容如下:

    package main
    
    import (
    	"net/http"
    
    	"github.com/gin-gonic/gin"
    )
    
    func main() {
    
    	//创建一个默认的引擎实例
    	engine := gin.Default()
    
    	//定义一个请求url为ask的GET请求
    	engine.GET("/ask", func(context *gin.Context) {
    		context.JSON(http.StatusOK, gin.H{
    			"message": "hello world!",
    		})
    	})
    
    	//在8080端口启动服务
    	engine.Run(":8080")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    ​ 启动上面代码,打开浏览器在上面输入http://127.0.0.1:8080/ask,看到响应结果,至此一个简单的gin服务器搭建完成。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zijU84ji-1660057955069)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809220546432.png)]

    2 gin的api

    ​ 在gin中可以使用GET, POST, PUT, PATCH, DELETE 和OPTIONS的方法,使用方式如下:

    func main() {
      // Creates a gin router with default middleware:
      // logger and recovery (crash-free) middleware
      router := gin.Default()
    
      router.GET("/someGet", getting)
      router.POST("/somePost", posting)
      router.PUT("/somePut", putting)
      router.DELETE("/someDelete", deleting)
      router.PATCH("/somePatch", patching)
      router.HEAD("/someHead", head)
      router.OPTIONS("/someOptions", options)
    
      // By default it serves on :8080 unless a
      // PORT environment variable was defined.
      router.Run()
      // router.Run(":3000") for a hard coded port
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3 GET请求传递参数

    ​ 下面通过三个例子来演示一下GET请求的参数获取。

    3.1 例子一

    ​ 绑定一个router的url,并建立一个处理函数handleGetParam

        engine := gin.Default()
    	//http://127.0.0.1:8080/v1/wangwu/17
    	engine.GET("/v1/:name/:age", handleGetParam)
    
    • 1
    • 2
    • 3
    /**
    * 通过context.Param直接拿到请求中的参数
     */
    func handleGetParam(context *gin.Context) {
    	age := context.Param("age")
    	name := context.Param("name") //context.DefaultQuery("name","0") 没有值就默认
    
    	context.JSON(http.StatusOK, gin.H{
    		"age":  age,
    		"name": name,
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ​ 启动项目,在浏览器中输入http://127.0.0.1:8080/v1/wangwu/17,浏览器响应结果如下,满足预期,代表参数的传值正常取到。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avEkSX8C-1660057955073)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809224210679.png)]

    3.2 例子二

    ​ 绑定一个router的url,并建立一个处理函数handleV2GetParam,在这个例子中还需要创建一个Student的结构体。

    	//http://127.0.0.1:8080/v2/wangwu/17
    	engine.GET("/v2/:name/:age", handleV2GetParam)
    
    • 1
    • 2
    type Student struct {
    	Age  int    `uri:"age" binding:"required"`
    	Name string `uri:"name" binding:"required"`
    }
    
    • 1
    • 2
    • 3
    • 4
    /**
    * 通过绑定的方式获取参数
     */
    func handleV2GetParam(context *gin.Context) {
    	var student Student
    	if err := context.ShouldBindUri(&student); err != nil {
    		context.Status(404)
    		return
    	}
    	context.JSON(http.StatusOK, gin.H{
    		"name": student.Name,
    		"age":  student.Age,
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ​ 启动项目,在浏览器中输入http://127.0.0.1:8080/v2/wangwu/17,浏览器响应结果如下,满足预期,代表参数的传值正常取到。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tpqINqvQ-1660057955074)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809224559475.png)]

    3.3 例子三

    ​ 绑定一个router的url,并建立一个处理函数handleV3GetParam,这个例子是通过在请求url后面拼接参数。

    	//http://127.0.0.1:8080/v3?name=wangwu&age=18
    	engine.GET("/v3", handleV3GetParam)
    
    • 1
    • 2
    /**
    * 获取?形式传参的数据
     */
    func handleV3GetParam(context *gin.Context) {
    	age := context.Query("age")
    	name := context.Query("name")
    
    	context.JSON(http.StatusOK, gin.H{
    		"age":  age,
    		"name": name,
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ​ 启动项目,在浏览器上输入http://127.0.0.1:8080/v3?name=wangwu&age=18也可以拿到预期的结果。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mExj2643-1660057955077)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809224922398.png)]

    4 POST请求

    4.1 form表单传参

    ​ 绑定一个router的url,并建立一个处理函数handleForm,对应代码如下:

        //处理post请求from表单传参的方式
    	engine.POST("/v1", handleForm)
    
    • 1
    • 2
    /**
    * post以form表单的形式发送请求
     */
    func handleForm(context *gin.Context) {
    	name := context.PostForm("name")
    	age := context.DefaultPostForm("age", string(18))
    
    	context.JSON(http.StatusOK, gin.H{
    		"age":  age,
    		"name": name,
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ​ 由于发送的是POST请求,我们可以在postman中进行测试,测试结果满足预期:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTbHCUZI-1660057955078)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809225500148.png)]

    4.2 json传参

    ​ 绑定一个router的url,并建立一个处理函数handleJson,例子中使用到的Student结构体在上面例子有定义,其他对应代码如下:

        //处理post请求json传参
    	engine.POST("/v2", handleJson)
    
    • 1
    • 2
    /**
    * post以json的形式发送请求
     */
    func handleJson(context *gin.Context) {
    	var student Student
    	if err := context.ShouldBind(&student); err != nil {
    		fmt.Println(err.Error())
    		context.JSON(http.StatusBadRequest, gin.H{
    			"error": err.Error(),
    		})
    		return
    	}
    
    	context.JSON(http.StatusOK, gin.H{
    		"name": student.Name,
    		"age":  student.Age,
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    ​ 启动服务,进行测试,测试结果满足预期:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6rqXflsa-1660057955098)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809225808451.png)]

    4.3 上传单个文件

    ​ 编写一个url,绑定的处理器handleFile,对应代码如下:

    	//处理文件上传(单文件上传)
    	engine.POST("/v3", handleFile)
    
    
    • 1
    • 2
    • 3
    /**
    * 单文件上传
     */
    func handleFile(context *gin.Context) {
    
    	file, err := context.FormFile("file")
    
    	if err != nil {
    		fmt.Println("产生错误:", err)
    	}
    	source := "D:\\code\\other\\go-project\\src\\project-study\\gin-study-01\\ch02\\" + file.Filename
    	if err := context.SaveUploadedFile(file, source); err != nil {
    		fmt.Println("保存文件出错:", err)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ​ 测试代码,接口调用成功之后会在指定目录下找到上传文件:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b26rQXBH-1660057955101)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809230223790.png)]

    4.4 多文件上传

    ​ 编写一个url,绑定的处理器handleFiles,对应代码如下:

    //多文件上传
    	engine.POST("/v4", handleFiles)
    
    • 1
    • 2
    /**
    * 多文件上传
     */
    func handleFiles(context *gin.Context) {
    	form, err := context.MultipartForm()
    	if err != nil {
    		fmt.Println("处理文件出错:", err)
    		return
    	}
    	files := form.File
    
    	for _, v := range files {
    		for _, f := range v {
    			s := f.Filename
    			source := "D:\\code\\other\\go-project\\src\\project-study\\gin-study-01\\ch02\\" + s
    			if err := context.SaveUploadedFile(f, source); err != nil {
    				fmt.Println("保存文件出错:", err)
    			}
    		}
    	}
    	values := form.Value
    	for k, v := range values {
    		fmt.Printf("key:%s,value:%v", k, v)
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    ​ 测试接口,本测试上传两个文件都成功了:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZQYMfdEo-1660057955102)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809230709806.png)]

    5 接口组

    ​ 在实际项目开发中,针对相同资源的操作请求的url的前缀一般都是一样的,在gin框架里面,我们可以通过Group实现,编写代码:

      // 接口分组,这样可以保证请求接口url前缀一样
    	group := engine.Group("/openapi")
    
    	{
    		group.GET("/get", func(context *gin.Context) {
    			context.JSON(http.StatusOK, gin.H{
    				"msg": "getsuccess",
    			})
    		})
    
    		group.POST("/post", func(context *gin.Context) {
    			context.JSON(http.StatusOK, gin.H{
    				"msg": "postsuccess",
    			})
    		})
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    ​ 在上述例子中创建了一个Group,这个Group里面定义了两个接口,它们的请求前缀都需要带上openapi。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f0gLAtQo-1660057955104)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809231142330.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QNCwfIIC-1660057955106)(D:\developsoftware\mayun\note\study-note\go\images\image-20220809231201043.png)]

  • 相关阅读:
    QPIC阅读笔记
    算法训练 第三周
    深度学习开发环境搭建
    TMS320C6678 DSP + Xilinx Kintex-7 FPGA核心板参数资料规格书手册
    Kafka - 3.x 文件存储不完全指北
    (8)Lightweight OpenPose轻量化模型之 模型封装 + 摔倒检测
    什么情况?吉利减持沃尔沃股份套现3.5亿美元
    [Linux] Linux文件编程 1.1 文件打开及创建
    c++ 函数重载
    Jenkins+Maven+Gitlab+Tomcat 自动化构建打包、部署
  • 原文地址:https://blog.csdn.net/qq_36305027/article/details/126257592