【Go】Gin Web 服务框架

一. Gin

Gin是Golang的一个web框架,封装优雅API友好,源码注释比较明确。借助Gin框架开发web服务,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范。

详细参考Github项目地址 https://github.com/gin-gonic/gin

  1. 安装Gin go get -u github.com/gin-gonic/gin
  2. 使用Gin import "github.com/gin-gonic/gin"

二. Hello World

使用Gin只需要几行代码就可以轻松实现一个web服务,下面我们看一个简单的例子实现HTTP请求打印“Hello World”。

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

func main(){
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello World")
    })
    router.Run(":8000")
}
  1. router := gin.Default() 获取默认的Engine
  2. router.GET("/", func(c *gin.Context) HTTP方法绑定路由规则以及相应的处理方法
  3. router.Run(":8000") 开启服务监听8000端口

三. 分组路由

Gin提供了分组路由的功能,能够让代码更加模块化。

v1 := router.Group("/v1")
v1.GET("/login", func(c *gin.Context) {
     c.String(http.StatusOK, "v1 login")
})

v2 := router.Group("/v2")
v2.GET("/login", func(c *gin.Context) {
     c.String(http.StatusOK, "v2 login")
})

四. 中间件

Gin提供了中间件的功能,中间件分为全局中间件、单个路由中间件和分组中间件。
中间件只对注册过的路由函数起作用,对于分组路由使用中间件可以限定中间件的作用范围。

中间件的功能主要用于请求处理之前的鉴权、通用参数解析 以及在请求处理之后统一的响应构建等等。

① 全局中间件

在全局路由上注册中间件

func MiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        fmt.Println("before middleware")
        c.Set("request", "clinet_request")
        c.Next()
        fmt.Println("before middleware")
    }
}
router.Use(MiddleWare())
router.GET("/middleware", func(c *gin.Context) {
	request := c.MustGet("request").(string)
	req, _ := c.Get("request")
	c.JSON(http.StatusOK, gin.H{
		"middile_request": request,
        "request": req,
    })
})

router.Use(MiddleWare()) 表示所有的路由都会经过MiddleWare()函数处理。

② 单个路由中间件

在单个路由上注册中间件

func MiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        fmt.Println("before middleware")
        c.Set("request", "clinet_request")
        c.Next()
        fmt.Println("before middleware")
    }
}
router.GET("/before", MiddleWare(), func(c *gin.Context) {
	request := c.MustGet("request").(string)
	c.JSON(http.StatusOK, gin.H{
        "middile_request": request,
    })
})

router.GET("/before", MiddleWare(), func(c gin.Context) 只有*/before**这个路由会经过MiddleWare()函数处理。

③ 分组中间件

在分组路由上注册中间件

func MiddleWare() gin.HandlerFunc {
    return func(c *gin.Context) {
        fmt.Println("before middleware")
        c.Set("request", "clinet_request")
        c.Next()
        fmt.Println("before middleware")
    }
}
authorized := router.Group("/")
authorized.Use(MyMiddelware())
authorized.POST("/login", loginEndpoint)

authorized := router.Group("/") 和 authorized.Use(MyMiddelware()) 表示只在authorized这个分组下的路由会经过MiddleWare()函数处理。

五. 参数获取

web服务通常是客户端和服务端交互,其中客户端向服务器发送请求,请求参数无非两种,查询字符串query string报文体body参数

① query string参数

query string参数指**?以后连接的key1=value2&key2=value2形式的参数,默认content-type是x-www-form-urlencoded**。

Gin参数获取支持提供默认值,例如下面这段代码

func main(){
    router := gin.Default()
    router.GET("/welcome", func(c *gin.Context) {
        firstname := c.DefaultQuery("firstname", "Guest")
        lastname := c.Query("lastname")
        c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
    })
  router.Run()
}
  1. 使用c.DefaultQuery方法读取参数,当参数不存在的时候会提供一个默认值。
  2. 使用c.Query方法读取参数,当参数不存在的时候返回空字串。

② body参数

HTTP报文体body传输格式常见的有以下4种

  1. application/json 表示以json格式传输
  2. application/x-www-form-urlencoded 表示把query string格式的参数放到body
  3. application/xml 表示以xml格式传输
  4. multipart/form-data 主要用于图片上传
func main(){
    router := gin.Default()
    router.POST("/form_post", func(c *gin.Context) {
        message := c.PostForm("message")
        nick := c.DefaultPostForm("nick", "anonymous")

        c.JSON(http.StatusOK, gin.H{
            "status":  gin.H{
                "status_code": http.StatusOK,
                "status":      "ok",
            },
            "message": message,
            "nick":    nick,
        })
    })
}
  1. c.PostForm(“message”) 从body里获取message字段值,默认content-type是x-www-form-urlencoded
  2. c.DefaultPostForm(“nick”, “anonymous”) 从body里获取nick字段值,获取不到默认值为anonymous
  3. c.JSON 调用c.JSON则返回json数据,其中gin.H封装了生成json的方式。

六. 参数绑定

常规的HTTP请求参数校验需要业务写大量的if else逻辑, Gin提供了参数bind功能支持参数校验。content-type无论是x-www-form-urlencoded 还是 **application/json **都支持。

type User struct {
    Username string `form:"username" json:"username" binding:"required"`
    Passwd   string `form:"passwd"   json:"passwd"   bdinding:"required"`
    Age      int    `form:"age"      json:"age"`
}

func main(){
    router := gin.Default()
    router.POST("/login", func(c *gin.Context) {
        var user User
        var err error
        contentType := c.Request.Header.Get("Content-Type")

        switch contentType {
        case "application/json":
            err = c.BindJSON(&user)
        case "application/x-www-form-urlencoded":
            err = c.BindWith(&user, binding.Form)
        }

        if err != nil {
            fmt.Println(err)
            log.Fatal(err)
        }

        c.JSON(http.StatusOK, gin.H{
            "user":   user.Username,
            "passwd": user.Passwd,
            "age":    user.Age,
        })
    })
}
  1. application/json使用c.BindJSON进行参数校验
  2. application/x-www-form-urlencoded使用c.BindWith进行参数校验

你可能感兴趣的:(17.,Go)