go Web框架--gin

隔好多个月,我又重回后端。回想起当年被SpringBoot虐的体无完肤,心中还是有点悲伤。。

今天介绍一下go语言的一个web框架:gin

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

这个框架上手简单,性能优秀,相信是go语言后端框架的入门的不二之选。

QuickStart

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
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() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

就用官网的这个例子来讲解吧。首先定义一个r变量为gin.Default()。之后就可以调用它的GETPOSTPUTDELETE等方法了。在例子中,GET函数中的第一个参数为路由地址,也就是当我们访问localhost:8080/ping时,会触发第二个参数,也就是一个方法。该方法一般接收一个*Context类型参数。源码中对该类型有介绍:Context是gin最重要的组成部分。例如,它允许我们在中间件之间传递变量、管理流、验证请求的JSON和呈现JSON响应。它的定义在github.com/gin-gonic-gin@v1.6.3/context.go中,大家可以自行阅读。在示例中,c这个变量调用了JSON方法,这里可以看一下该方法的定义:

// JSON serializes the given struct as JSON into the response body.
// It also sets the Content-Type as "application/json".
func (c *Context) JSON(code int, obj interface{}) {
	c.Render(code, render.JSON{Data: obj})
}

可以看到源码中的注释已经解释的很清楚了这个函数的作用了,它将接受到的结构体序列化为JSON数据作为响应体返回。它同时指定了Content-Typeapplication/json,这个可以在控制台中查看。第一个参数是浏览器响应的状态码,第二个参数是响应体。gin.H是什么呢?

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

可以看到,它本质就是map[string]interface{}——也就是go中的map。string表明参数中的key必须为string类型,interface{}表明参数中的value可以为任意类型。也就是我们看到的"message": "pong",。后面的"pong"可以是任意的go语言合法类型,而前面的"message"则必须为string类型,否则会报错。

再来看一个进阶的例子:

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

	router.POST("/form_post", func(c *gin.Context) {
		message := c.PostForm("message")
		nick := c.DefaultPostForm("nick", "anonymous")

		c.JSON(200, gin.H{
			"status":  "posted",
			"message": message,
			"nick":    nick,
		})
	})
	router.Run(":8080")
}

这是一个接受POST请求的方法。当我们向localhost:8080/form_post发送post请求时,就会触发对应的方法。这个方法做了什么呢?首先message := c.PostForm("message"),将message赋值为请求体中名为message的值,如果没有该值则为空字符串。将nick赋值为请求体中名为nick的值,如果没有该值则为默认值:"anonymous"。然后返回的是一个JSON数据,通过gin.H进行序列化。这里我们可以通过postman来进行测试,读者可以自行测试。最后我们可以看到router.Run(":8080"),也就是说我们可以指定该路由运行的端口,默认为8080

Context这个结构体中还有很多实用的方法,例如:

  • Param()用来匹配路由中的参数,例如:

    // This handler will match /user/john but will not match /user/ or /user
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })
    

    当我们访问/usr/sleepdevil时,name就被赋值为sleepdevil

  • Query()用来匹配路由中的查询参数,即?后面跟的键值对的值。

  • FormFile()用来接收文件。

  • any more……

Using middleware

当我们通过gin.Default()创建一个路由对象时,已经自带了LoggerRecovery中间件了。如果我们想创建一个不带任何中间件的路由该怎么办呢?gin.New()完美解决了我们的需求。通过该函数即可创建一个不带任何中间件的路由。

创建完成之后可以通过Use()函数来注册中间件。

有关gin的入门就说这么多,在前后端分离的当下,前端工程师至少应会后端增删改查接口的设计。有关gin框架的深入,可以去这里查看。