Gin框架

155 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

安装:

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

go在1.13版本后,默认开启了: GOSUMDB=sum.golang.org 而这个网址sum.golang.org 在国内是无法访问,故需要关闭 go env -w GO111MODULE=on

更换国内源

go env -w GOPROXY=mirrors.aliyun.com/goproxy/,di…

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

r := gin.Default()

Gin实例创建路由:(使用匿名函数来处理GET请求,当请求到达“/hello”路径时,返回一个JSON响应。)

1.Gin 支持 GET、POST、PUT、PATCH、DELETE、OPTIONS 等请求类型。

2.可通过 *gin.Context 的 Param 函数获取请求 Path 中的参数,Path 路径中参数以:开头,如:/user/:name,能够匹配路径 /user/xx

3.可通过 *gin.Context 的 Query 函数获取参数,如:/user?name=xcbeyond

4.Gin 提供了路由分组的能力,方便管理分组管理路由,将具有相同路由 URL 前缀的进行分类处理,常见于不同版本的分组,如:/api/v1/api/v1。也支持多级分组。

5.路由支持拆分 。

r.GET("/hello", func(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "Hello, World!",
    })
})

请求和响应:

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")

        if token == "" {
            c.AbortWithStatus(401)
        } else {
            c.Next()
        }
    }
}

gin特点:

  • 零分配路由。
  • 最快的 http 路由器和框架。
  • 完整的单元测试支持。
  • API 冻结,新版本的发布不会破坏你的代码。
  • Gin 项目可以轻松部署在任何云提供商上。

集成Swagger

$ go get github.com/swaggo/swag/cmd/swag

安装gin-swagger

$ go get -u github.com/swaggo/gin-swagger 
$ go get -u github.com/swaggo/gin-swagger/swaggerFiles
package main

import (
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"

	_ "github.com/swaggo/gin-swagger/example/basic/docs" // docs is generated by Swag CLI, you have to import it.
)

func main() {
	r := gin.New()

	url := ginSwagger.URL("http://localhost:8080/swagger/doc.json") // The url pointing to API definition
	r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler, url))

	r.Run()
}

实例引用:(视频的上传与下载接口的实现)

package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "os"

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

func main() {
    r := gin.Default()

    r.POST("/upload", func(c *gin.Context) {
        file, header, err := c.Request.FormFile("file")
        if err != nil {
            c.String(http.StatusBadRequest, fmt.Sprintf("文件上传失败: %s", err.Error()))
            return
        }
        defer file.Close()

        filename := header.Filename
        out, err := os.Create("videos/" + filename)
        if err != nil {
            log.Fatal(err)
        }
        defer out.Close()

        _, err = io.Copy(out, file)
        if err != nil {
            log.Fatal(err)
        }

        c.String(http.StatusOK, fmt.Sprintf("文件 %s 上传成功", filename))
    })

    r.GET("/download/:name", func(c *gin.Context) {
        filename := c.Param("name")
        file, err := os.Open("videos/" + filename)
        if err != nil {
            c.String(http.StatusBadRequest, fmt.Sprintf("文件 %s 下载失败: %s", filename, err.Error()))
            return
        }
        defer file.Close()

        c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
        c.Header("Content-Type", "application/octet-stream")
        c.File("videos/" + filename)
    })

    r.Run(":8080")
}