前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go web 开发框架 - Gin 简述

Go web 开发框架 - Gin 简述

作者头像
张云飞Vir
发布2020-04-16 17:38:08
2.3K0
发布2020-04-16 17:38:08
举报
文章被收录于专栏:写代码和思考写代码和思考

0. 背景

Go 语言开发框架很多,本文介绍Gin。

Go web 开发框架 - Gin 简述

Gin 的英文意思是 杜松子酒,在它的官方介绍中提到了它的API 风格是 和 martini 相像的( martini-like )。而 martini 也是一个web框架,有意思的是 martini 的英文是 “马提尼”,也是一种鸡尾酒。

1. 简介

Go 是最快的全功能web框架之一,清澈,简洁。它的性能更好,速度快了40倍(相比于 martini 框架)。 Gin 是面向高性能和良好的生产力的选择。

总结就是:

  • 简洁,晶莹剔透
  • 性能好

特点:

  • 快: 内存占用小。没有反射。
  • 支持中间件: 通过中间件扩展能力。例如:Logger、授权、GZIP。
  • 故障和恢复:Gin可以捕获HTTP请求期间发生的panic并恢复它。
  • JSON验证: Gin可以解析和验证请求的JSON
  • 路由分组:通过分组方便管理,比如控制授权与不需要授权,不同的API版本等。
  • 错误管理:方便的收集HTTP请求期间发生的所有错误,可以通过中间件可以将它们写入日志文件、数据库并通过网络发送。
  • 内置的视图呈现: 支持MVC,为JSON、XML和HTML呈现提供API。
  • 可扩展:创建新中间件非常简单。

2. 开始之前

2.1 安装

代码语言:javascript
复制
go get -u github.com/gin-gonic/gin

2.2 导入包

代码语言:javascript
复制
import "github.com/gin-gonic/gin"

2.3 一个快速示例

简单步骤:

  • 构建一个服务对象,通过 gin.Default()
  • 启动服务,通过 r.Run()

示例如下:

代码语言:javascript
复制
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")
}

2.4 构建时注意事项

Gin使用encoding/json作为默认的json包,但是您可以通过从其他标记构建来更改为jsoniter。

代码语言:javascript
复制
$ go build -tags=jsoniter .

3. 使用示例

3.1 GET, POST,PUT 示例

形式如 router.GET("/someGet", getting),第一个参数是 url 相对路径,第二个参数是 你的 hadler 处理器。

hadler 处理器的函数签名是:func(c *gin.Context) { }

代码语言:javascript
复制
func main() {
    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)

    router.Run()
}

3.2 处理URL路径中的参数(比如:/user/:name)

代码语言:javascript
复制
Parameters in path
func main() {
    router := gin.Default()

    // 匹配 /user/john
    router.GET("/user/:name", func(c *gin.Context) {
        name := c.Param("name")
        c.String(http.StatusOK, "Hello %s", name)
    })

    // However, this one will match /user/john/ and also /user/john/send
    // If no other routers match /user/john, it will redirect to /user/john/
    router.GET("/user/:name/*action", func(c *gin.Context) {
        name := c.Param("name")
        action := c.Param("action")
        message := name + " is " + action
        c.String(http.StatusOK, message)
    })

    // For each matched request Context will hold the route definition
    router.POST("/user/:name/*action", func(c *gin.Context) {
        c.FullPath() == "/user/:name/*action" // true
    })

    router.Run(":8080")
}

3.3 读取URL中的查询字符串

使用: c.DefaultQuery(), 或者 c.Query() 方法。

代码语言:javascript
复制
func main() {
    router := gin.Default()

    // welcome?firstname=Jane&lastname=Doe
    router.GET("/welcome", func(c *gin.Context) {
        firstname := c.DefaultQuery("firstname", "Guest")
        lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")

        c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
    })
    router.Run(":8080")
}

3.4 读取URL中的查询字符串

使用: c.PostForm() 方法

代码语言:javascript
复制
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")
}

3.5 处理文件上传

获得文件: file, _ := c.FormFile("file") 保存文件: c.SaveUploadedFile(file, dst)

代码语言:javascript
复制
func main() {
    router := gin.Default()
    // Set a lower memory limit for multipart forms (default is 32 MiB)
    // router.MaxMultipartMemory = 8 << 20  // 8 MiB
    router.POST("/upload", func(c *gin.Context) {
        // single file
        file, _ := c.FormFile("file")
        log.Println(file.Filename)

        // Upload the file to specific dst.
        // c.SaveUploadedFile(file, dst)

        c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
    })
    router.Run(":8080")
}

3.6 路由分组

使用 router.Group("/v1") 实现 路由分组。

代码语言:javascript
复制
Grouping routes
func main() {
    router := gin.Default()

    // Simple group: v1
    v1 := router.Group("/v1")
    {
        v1.POST("/login", loginEndpoint)
        v1.POST("/submit", submitEndpoint)
        v1.POST("/read", readEndpoint)
    }

    // Simple group: v2
    v2 := router.Group("/v2")
    {
        v2.POST("/login", loginEndpoint)
        v2.POST("/submit", submitEndpoint)
        v2.POST("/read", readEndpoint)
    }

    router.Run(":8080")
}

3.7 呈现 HTML 视图 ( HTML rendering )

通过 LoadHTMLGlob() 或者 LoadHTMLFiles() 加载模板 通过 c.HTML(http.StatusOK, "index.tmpl", gin.H{ "title": "Main website", })

第一个参数是 http 状态码,第二个参数是模板名,第三个参数是传入的参数值。

代码语言:javascript
复制
func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/*")
    //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")
    router.GET("/index", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.tmpl", gin.H{
            "title": "Main website",
        })
    })
    router.Run(":8080")
}

templates/index.tmpl

代码语言:javascript
复制
<html>
    <h1>
        {{ .title }}
    </h1>
</html>

3.8 自定义中间件(Custom Middleware)

中间件是个函数,签名格式: func(c *gin.Context) {} 通过 c.Next() 表达继续在 链条中传递。

代码语言:javascript
复制
func Logger() gin.HandlerFunc {
    return func(c *gin.Context) {
        t := time.Now()

        // Set example variable
        c.Set("example", "12345")

        // before request

        c.Next()

        // after request
        latency := time.Since(t)
        log.Print(latency)

        // access the status we are sending
        status := c.Writer.Status()
        log.Println(status)
    }
}

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

    r.GET("/test", func(c *gin.Context) {
        example := c.MustGet("example").(string)

        // it would print: "12345"
        log.Println(example)
    })

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

更多内容,请参阅 官方Github

4. 参考

官网 https://gin-gonic.com/

官方github https://github.com/gin-gonic/gin

官方github 的 readme 翻译 https://www.jianshu.com/p/98965b3ff638/

多款 Go 语言开发框架 介绍(含对比) https://github.com/speedwheel/awesome-go-web-frameworks/blob/master/README.md#popularity

Martini是一个强大为了编写模块化Web应用而生的GO语言框架. https://github.com/go-martini/martini/blob/master/translations/README_zh_cn.md

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0. 背景
  • 1. 简介
  • 2. 开始之前
    • 2.1 安装
      • 2.2 导入包
        • 2.3 一个快速示例
          • 2.4 构建时注意事项
          • 3. 使用示例
            • 3.1 GET, POST,PUT 示例
              • 3.2 处理URL路径中的参数(比如:/user/:name)
                • 3.3 读取URL中的查询字符串
                  • 3.4 读取URL中的查询字符串
                    • 3.5 处理文件上传
                      • 3.6 路由分组
                        • 3.7 呈现 HTML 视图 ( HTML rendering )
                          • 3.8 自定义中间件(Custom Middleware)
                          • 4. 参考
                          相关产品与服务
                          消息队列 TDMQ
                          消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档