Go语言web框架 Gin

Gin

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

Gin拥有多种特性:快速、支持中间件、Crash 处理、JSON 验证、路由组、错误管理、内置渲染、可扩展性等等。

安装

要安装 Gin 软件包,需要先安装 Go 并设置 Go 工作区。

1.下载并安装 gin:

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

2.将 gin 引入到代码中:

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

3.(可选)如果使用诸如 http.StatusOK 之类的常量,则需要引入 net/http 包:

1
import "net/http"

开始

首先,创建一个名为 example.go 的文件

1
$ touch helloGin.go

接下来, 将如下的代码写入 example.go 中:

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("/hello", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello Gin",
})
})
r.Run("localhost:8001") // 监听并在 localhost:8001 上启动服务
}

然后, 执行 go run helloGin.go 命令来运行代码:

1
2
# 运行 example.go 并且在浏览器中访问 127.0.0.1:8001/hello
$ go run helloGin.go

Gin特性示例

抽了四个代表性的示例:

使用 HTTP 方法

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
func main() {
// 禁用控制台颜色
// gin.DisableConsoleColor()

// 使用默认中间件(logger 和 recovery 中间件)创建 gin 路由
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)

// 默认在 8080 端口启动服务,除非定义了一个 PORT 的环境变量。
router.Run()
// router.Run(":3000") hardcode 端口号
}

func getting(c *gin.Context) {
c.JSON(200, gin.H{
"message": "Hello Gin",
})
}

使用中间件

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
27
28
29
30
31
32
33
34
35
func main() {
// 新建一个没有任何默认中间件的路由
r := gin.New()

// 全局中间件
// Logger 中间件将日志写入 gin.DefaultWriter,即使你将 GIN_MODE 设置为 release。
// By default gin.DefaultWriter = os.Stdout
r.Use(gin.Logger())

// Recovery 中间件会 recover 任何 panic。如果有 panic 的话,会写入 500。
r.Use(gin.Recovery())

// 你可以为每个路由添加任意数量的中间件。
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)

// 认证路由组
// authorized := r.Group("/", AuthRequired())
// 和使用以下两行代码的效果完全一样:
authorized := r.Group("/")
// 路由组中间件! 在此例中,我们在 "authorized" 路由组中使用自定义创建的
// AuthRequired() 中间件
authorized.Use(AuthRequired())
{
authorized.POST("/login", loginEndpoint)
authorized.POST("/submit", submitEndpoint)
authorized.POST("/read", readEndpoint)

// 嵌套路由组
testing := authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}

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

在中间件中使用 Goroutine

当在中间件或 handler 中启动新的 Goroutine 时,不能使用原始的上下文,必须使用只读副本。

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
func main() {
r := gin.Default()

r.GET("/long_async", func(c *gin.Context) {
// 创建在 goroutine 中使用的副本
cCp := c.Copy()
go func() {
// 用 time.Sleep() 模拟一个长任务。
time.Sleep(5 * time.Second)

// 请注意您使用的是复制的上下文 "cCp",这一点很重要
log.Println("Done! in path " + cCp.Request.URL.Path)
}()
})

r.GET("/long_sync", func(c *gin.Context) {
// 用 time.Sleep() 模拟一个长任务。
time.Sleep(5 * time.Second)

// 因为没有使用 goroutine,不需要拷贝上下文
log.Println("Done! in path " + c.Request.URL.Path)
})

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

AsciiJSON

使用 AsciiJSON 生成具有转义的非 ASCII 字符的 ASCII-only JSON。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
r := gin.Default()

r.GET("/someJSON", func(c *gin.Context) {
data := map[string]interface{}{
"lang": "GO语言",
"tag": "<br>",
}

// 输出 : {"lang":"GO\u8bed\u8a00","tag":"\u003cbr\u003e"}
c.AsciiJSON(http.StatusOK, data)
})

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

参考资料:

Gin Web Framework

欢迎关注我的其它发布渠道