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

Go世界里最流行的Web框架,Github上有32K+star。 基于httprouter开发的Web框架。 中文文档齐全,简单易用的轻量级框架。

Gin的安装与使用

安装

命令行输入
go get -u github.com/gin-gonic/gin

使用,一个helloworld例子

import (
    "net/http"

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

func main() {
    // 1.创建路由
   r := gin.Default()
   // 2.绑定路由规则,执行的函数
   // gin.Context,封装了request和response
   r.GET("/", func(c *gin.Context) {
      c.String(http.StatusOK, "hello World!")
   })
   // 3.监听端口,默认在8080
   // Run("里面不指定端口号默认为8080") 
   r.Run(":8000")
}

将上面的代码保存并编译执行,然后使用浏览器打开127.0.0.1:8080/hello就能看到一串JSON字符串。

RESTful API

REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。

简单来说,REST的含义就是客户端与Web服务器之间进行交互的时候,使用HTTP协议中的4个请求方法代表不同的动作。

  • GET用来获取资源
  • POST用来新建资源
  • PUT用来更新资源
  • DELETE用来删除资源。
r.GET("/book", func(c *gin.Context){
    c.JSON(200, gin.H{
        "method":"GET"    
    })    
})
r.POST("/book",func(c *gin.Context){
    c.JSON(200, gin.H{
        "method":"POST"    
    })    
})
r.PUT("/book",func(c *gin.Context){
    c.JSON(200, gin.H{
        "method":"PUT"    
    })    
})
r.DELETE("/book",func(c *gin.Context){
    c.JSON(200, gin.H{
        "method":"DELETE"    
    })    
})

只要API程序遵循了REST风格,那就可以称其为RESTful API。目前在前后端分离的架构中,前后端基本都是通过RESTful API来进行交互。

template

Go语言内置了文本模板引擎text/template和用于HTML文档的html/template。它们的作用机制可以简单归纳如下:

  1. 模板文件通常定义为.tmpl和.tpl为后缀(也可以使用其他的后缀),必须使用UTF8编码。
  2. 模板文件中使用{{和}}包裹和标识需要传入的数据。
  3. 传给模板这样的数据就可以通过点号(.)来访问,如果数据是复杂类型的数据,可以通过{ { .FieldName }}来访问它的字段。
  4. 除{{和}}包裹的内容外,其他内容均不做修改原样输出。

HTML渲染

gin框架中使用LoadHTMLGlob() 或者LoadHTMLFiles()方法进行HTML模板渲染

//r.LoadHTMLFiles("templates/posts/index.html", "templates/users/index.html")
	r.GET("/posts/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "posts/index.html", gin.H{
			"title": "posts/index",
		})
	})

	r.GET("users/index", func(c *gin.Context) {
		c.HTML(http.StatusOK, "users/index.html", gin.H{
			"title": "users/index",
		})
	})

静态文件处理、

当我们渲染的HTML文件中引用了静态文件时,我们只需要在渲染页面前调用gin.Static 方法即可

func main() {
	r := gin.Default()
	r.Static("/static", "./static")
	r.LoadHTMLGlob("templates/**/*")
   // ...
	r.Run(":8080")
}

JSON渲染

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

   //加载静态文件
   //r.Static("/static","./statics")
   r.GET("/someJSON",func(c *gin.Context){
      //方式一:自己拼接json
      c.JSON(http.StatusOK, gin.H{
         "message": "Hello world",
      })
   })
   r.GET("/moreJSON", func(c *gin.Context){
      var msg struct{
         Name string `json:"user"`
         Message string
         Age int
      }
      msg.Name="hhh"
      msg.Message="Helloworld!"
      msg.Age = 18
      c.JSON(http.StatusOK,msg)
   })
   r.Run(":8080")
}

XML渲染

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

   //加载静态文件
   //r.Static("/static","./statics")
   r.GET("/someXML",func(c *gin.Context){
      //方式一:自己拼接json
      c.XML(http.StatusOK, gin.H{
         "message": "Hello world",
      })
   })
   r.GET("/moreXML", func(c *gin.Context){
      type msg struct{
         Name string 
         Message string
         Age int
      }
      var message msg
      message.Name="hhh"
      message.Message="Helloworld!"
      message.Age = 18
      c.XML(http.StatusOK,message)
   })
   r.Run(":8080")
}

除此之外还有YMAL渲染和上边的两种方法的使用方式相差不多

获取path参数

请求的参数通过URL路径传递

func main() {
	//Default返回一个默认的路由引擎
	r := gin.Default()
	r.GET("/user/search/:username/:address", func(c *gin.Context) {
		username := c.Param("username")
		address := c.Param("address")
		//输出json结果给调用方
		c.JSON(http.StatusOK, gin.H{
			"message":  "ok",
			"username": username,
			"address":  address,
		})
	})

	r.Run(":8080")
}

参数绑定

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了 .ShouldBind()强大的功能,它能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象。

ShouldBind会按照下面的顺序解析请求中的数据完成绑定:

  1. 如果是 GET 请求,只使用 Form 绑定引擎(query)。
  2. 如果是 POST 请求,首先检查 content-type 是否为 JSON 或 XML,然后再使用 Form(form-data)。

重定向

HTTP重定向

HTTP 重定向很容易。 内部、外部重定向均支持。

r.GET("/test", func(c *gin.Context) {
	c.Redirect(http.StatusMovedPermanently, "http://www.sogo.com/")
})

路由重定向

路由重定向,使用HandleContext:

r.GET("/test", func(c *gin.Context) {
    // 指定重定向的URL
    c.Request.URL.Path = "/test2"
    r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
    c.JSON(http.StatusOK, gin.H{"hello": "world"})
})

Gin路由

普通路由‘

r.Any("/test", func(c *gin.Context){...})

Any方法可以匹配所有的请求方法

为没有配置处理函数的路由添加处理程序,默认情况下它返回404代码,下面的代码为没有匹配到路由的请求都返回

views/404.html页面。

r.NoRoute(func(c *gin.Context) {
		c.HTML(http.StatusNotFound, "views/404.html", nil)
	})

路由原理

Gin框架中的路由使用的是httprouter这个库。

其基本原理就是构造一个路由地址的前缀树。

中间件

Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

定义中间件

Gin中的中间件必须是一个gin.HandlerFunc类型

func indexHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "msg": "index",
   })
}

func main(){
   r := gin.Default()
   r.GET("index", indexHandler)
   r.Run()
}

注册中间件

在gin框架中,我们可以为每个路由添加任意数量的中间件。

 r.GET("index",m1,... indexHandler)

c.Next() 调用后续的处理函数

c.Abort() 阻止调用后续的处理函数

//计算执行程序花费的时间
func m1(c *gin.Context){
   start := time.Now()
   c.Next()
   cost := time.Since(start)
   fmt.Println("cost:%v\n",cost)
}
//

gin默认中间件

gin.Default()默认使用了Logger和Recovery中间件,其中:

  • Logger中间件将日志写入gin.DefaultWriter,即使配置了GIN_MODE=release。
  • Recovery中间件会recover任何panic。如果有panic的话,会写入500响应码。

如果不想使用上面两个默认的中间件,可以使用gin.New()新建一个没有任何默认中间件的路由。

gin中间件中使用goroutine

当在中间件或handler中启动新的goroutine时,不能使用原始的上下文(c *gin.Context),必须使用其只读副本(c.Copy())。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐