• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Go小课03Gin Simple Demo解读

武飞扬头像
南华Coder
帮助1

一、概述

1、简介
  • Go官方为了支持Web开发,提供了net/http工具包;但是在实际项目中,团队还是会选择更加高效,更便捷的Web框架,如GinEcho,Beego等;
  • 在这些团队中,很多团队选择了Gin这个框架,它在net/http 的基础上做了优化;对比其他主流框架,它更好的性能更快的路由
2、Gin的优点
  • 快速:基于Radix树的路由,性能非常强大。

  • 支持中间件:内置许多中间件,如Logger,Gzip,Authorization等。

  • 崩溃恢复:可以捕捉panic引发的程序崩溃,使Web服务可以一直运行。

  • JSON验证:可以验证请求中JSON数据格式。

  • 路由分组:支持路由分组(RouteGroup),可以更方便组织路由。

  • 错误管理机制:可以收集程序中的错误

  • 多种数据渲染方式:支持HTMLJSONYAMLXML等数据格式的响应。

  • 扩展性:非常简单扩展中间件。

  • 数据验证器:支持数据验证器且可以自定义。

3、Gin Simple Demo
package main

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

func setupRouter() *gin.Engine {

	r := gin.Default()
	// Ping test
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"status" : 0,
			"msg" 	 : "success",
			"data"   :  gin.H {
				"content" : "pong",
			},
		})
	})
	return r
}

func main() {
   r := setupRouter()
   r.Run() 
}

二、Gin Simple Demo 解读

从Demo Code可以看出,使用Gin的体验非常顺滑,定义处理Web请求就四步:导入包定义路由编写 Handler监听端口

1. 导入包
import "github.com/gin-gonic/gin"
2. 定义路由
  • gin.Engine是路由引擎,一般使用gin.Default()方法创建并返回gin.Engine实例.
r := gin.Default() //r默认使用了Logger和Recovery两个中间件

说明:可以用gin.New()方法创建并返回一个不包含任何中间件的gin.Engine实例

3. 编写 Handler

通过默认路由,我们可以创建处理HTTP请求的方法,示例中使用GET方法:

// Ping test
r.GET("/ping", func(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
			"status" : 0,
			"msg" 	 : "success",
			"data"   :  gin.H {
				"content" : "pong",
		},
	})
})
  • Get方法底层实现是调用RouterGrouphandle方法, 请求的处理是使用HandlerFunc类型方法
// GET is a shortcut for router.Handle("GET", path, handle).
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle("GET", relativePath, handlers)
}

// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)
  • 说明:Gin支持所有通用的HTTP请求方法,如GET,POST,PUT,PATCH,OPTIONS,HEAD,DELETE
4. 监听端口
  • 定义好请求之后,使用Run()方法便可监听端口,开始接受HTTP请求,如果Run()方法没有传入参数的话,则默认监听8080端口。
r.Run() 
  • Run方法的底层实现关键是:http.ListenAndServe,其中:http来自net/http包。
func (engine *Engine) Run(addr ...string) (err error) {
	defer func() { debugPrintError(err) }()

	address := resolveAddress(addr)
	debugPrint("Listening and serving HTTP on %s\n", address)
	//
	err = http.ListenAndServe(address, engine)
	return
}

三、Gin中重要数据结构

​ 在Gin Simple Demo Code中,我们发现了三个重要的Go数据结构:gin.Enginegin.Contextgin.RouterGroup

1、gin.Engine
  • gin.Engine 是框架的入口;我们通过 Engine 对象来定义服务路由信息、组装插件、运行服务,整个 Web 服务的都是由它来驱动的。
// Engine is the framework's instance, it contains the muxer, middleware and configuration settings.
// Create an instance of Engine, by using New() or Default()
type Engine struct {
	RouterGroup
	
	//....
}
  • gin.Engine本质是对内置的 HTTP 服务器的包装,让它使用起来更加便捷。
  • gin.Default() 函数会生成一个默认的 Engine 对象,里面包含了 2 个默认的常用插件,分别是 Logger 和 Recovery,Logger 用于输出请求日志,Recovery 确保单个请求发生 panic 时记录异常堆栈日志,输出统一的错误响应(推荐使用)。
func Default() *Engine {
   debugPrintWARNINGDefault()
   engine := New()
   engine.Use(Logger(), Recovery())
   return engine
}
  • gin.New()函数会生成一个默认的 Engine 对象,不包含任何中间件的gin.Engine实例。
2、gin.Context
  • 请求的上下文信息对象,它是所有请求Handler的入口参数。gin.Context的结构定义如下:
// Context允许我们在中间件之间传递变量,管理流程,验证请求的JSON,并返回JSON
type Context struct {
	//请求对象
	Request   *http.Request
    
    // 用来响应 
    writermem responseWriter
	Writer    ResponseWriter
 	// URL里面的参数,比如:/xx/:id  
	Params   Params
	
     // 参与的处理者(中间件   请求处理者列表)
    handlers HandlersChain
    // 当前处理到的handler的下标
    index    int8

	fullPath string
	
    // Engine单例
	engine *Engine

	// 在context可以设置的值
	Keys map[string]interface{}

	// 一系列的错误
	Errors errorMsgs

	//为内容协商定义一组手动接受的格式。
	Accepted []string

	// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
	queryCache url.Values

	// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
	// or PUT body parameters.
	formCache url.Values
}
  • Context这个上下文对象不是每次生成,而是从对象池里面取出来的;而请求的真正处理核心在handleHTTPRequest函数中。
  • handleHTTPRequest函数中的核心逻辑:根据请求方法和请求的URI,找到并调用 处理的函数数组(包括我们定义的处理函数,还有中间层的处理函数)。
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {

	// 从对象池中获取一个context对象
	c := engine.pool.Get().(*Context)

	// 初始化上下文对象,因为从对象池取出来的数据,有脏数据,故要初始化。
	c.writermem.reset(w)
	c.Request = req
	c.reset()

    //处理web请求 (http请求处理)
	engine.handleHTTPRequest(c)

	//将Context对象扔回对象池了
	engine.pool.Put(c)
}
3、gin.RouterGroup
  • RouterGroup是路由分组,是对路由树的包装,所有的路由规则最终都是由它来进行管理。Engine 结构体继承了 RouterGroup ,所以 Engine 直接具备了 RouterGroup 所有的路由管理功能。
// RouterGroup is used internally to configure router, a RouterGroup is associated with
// a prefix and an array of handlers (middleware).
type RouterGroup struct {
	Handlers HandlersChain
	basePath string
	engine   *Engine
	root     bool
}

// HandlersChain defines a HandlerFunc array.
type HandlersChain []HandlerFunc
  • RouteGroup 对象中主要包括:basePath(前缀路径)、Engine 指针Handlers(处理函数数组)。

  • RouterGroup 实现了 IRouter 接口定义的一系列路由方法;这些方法最终都是通过调用 Engine.addRoute 方法将请求处理器挂接到路由树中。

  • RouterGroup 内部有一个前缀路径属性,它会将所有的子路径都加上这个前缀再放进路由树中。有了这个前缀路径,就可以实现 URL 分组功能。Engine 对象内嵌的 RouterGroup 对象的前缀路径是 /,它表示根路径。RouterGroup 支持分组嵌套,使用 Group 方法就可以让分组下面再挂分组。

    v1 := r.Group("/api/v1")
    {
    	v1.POST("/submit",submit)
    	v1.GET("/list",list)
    }
    // Engine对象中RouterGroup对象是第一层分组(根分组),v1是根分组的子分组。
    
4、gin.H
  • gin.H 是 map[string]interface{} 的一个快捷名称.
type H map[string]interface{}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhbebjfb
系列文章
更多 icon
同类精品
更多 icon
继续加载