最主要的package : gin

最主要的struct: Engine

Engine 是整个framework的实例,它包含了muxer, middleware, configuration settings. 通过New() 或者Default()来创建一个Engine 的实例。

type Engine struct {
RouterGroup // Enables automatic redirection if the current route can't be matched but a
// handler for the path with (without) the trailing slash exists.
// For example if /foo/ is requested but a route only exists for /foo, the
// client is redirected to /foo with http status code 301 for GET requests
// and 307 for all other request methods.
RedirectTrailingSlash bool // If enabled, the router tries to fix the current request path, if no
// handle is registered for it.
// First superfluous path elements like ../ or // are removed.
// Afterwards the router does a case-insensitive lookup of the cleaned path.
// If a handle can be found for this route, the router makes a redirection
// to the corrected path with status code 301 for GET requests and 307 for
// all other request methods.
// For example /FOO and /..//Foo could be redirected to /foo.
// RedirectTrailingSlash is independent of this option.
RedirectFixedPath bool // If enabled, the router checks if another method is allowed for the
// current route, if the current request can not be routed.
// If this is the case, the request is answered with 'Method Not Allowed'
// and HTTP status code 405.
// If no other Method is allowed, the request is delegated to the NotFound
// handler.
HandleMethodNotAllowed bool
ForwardedByClientIP bool // #726 #755 If enabled, it will thrust some headers starting with
// 'X-AppEngine...' for better integration with that PaaS.
AppEngine bool // If enabled, the url.RawPath will be used to find parameters.
UseRawPath bool // If true, the path value will be unescaped.
// If UseRawPath is false (by default), the UnescapePathValues effectively is true,
// as url.Path gonna be used, which is already unescaped.
UnescapePathValues bool // Value of 'maxMemory' param that is given to http.Request's ParseMultipartForm
// method call.
MaxMultipartMemory int64 delims render.Delims
secureJsonPrefix string
HTMLRender render.HTMLRender
FuncMap template.FuncMap
allNoRoute HandlersChain
allNoMethod HandlersChain
noRoute HandlersChain
noMethod HandlersChain
pool sync.Pool
trees methodTrees
}

获取一个gin Engin的实例:r := gin.Default()

查看gin.Default()方法的实现:

// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New() #实例化一个engine
engine.Use(Logger(), Recovery())
return engine
}

  查看New()的实现:

// New returns a new blank Engine instance without any middleware attached.
// By default the configuration is:
// - RedirectTrailingSlash: true
// - RedirectFixedPath: false
// - HandleMethodNotAllowed: false
// - ForwardedByClientIP: true
// - UseRawPath: false
// - UnescapePathValues: true
func New() *Engine {
debugPrintWARNINGNew()
engine := &Engine{
RouterGroup: RouterGroup{
Handlers: nil,
basePath: "/",
root: true,
},
FuncMap: template.FuncMap{},
RedirectTrailingSlash: true,
RedirectFixedPath: false,
HandleMethodNotAllowed: false,
ForwardedByClientIP: true,
AppEngine: defaultAppEngine,
UseRawPath: false,
UnescapePathValues: true,
MaxMultipartMemory: defaultMultipartMemory,
trees: make(methodTrees, 0, 9),
delims: render.Delims{Left: "{{", Right: "}}"},
secureJsonPrefix: "while(1);",
}
engine.RouterGroup.engine = engine
engine.pool.New = func() interface{} { //这里定义了engine.pool.New方法,所以在Get()的时候,如果为nil,那么直接执行New 方法
return engine.allocateContext()
}
return engine
}

 如果engine.pool.New被执行,那么将返回一个*Context类型的指针。

func (engine *Engine) allocateContext() *Context {
return &Context{engine: engine}
}

然后调用r.Run(":8080"), 在本地网卡上监听8080端口,等待连接。实际上调用的是:http.ListenAndServe(address, engine)

查看http.ListenAndServe方法:

func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}

 它且将addr 和handler作为参数实例化了一个Server, 然后调用server.ListenAndServe()方法等待连接。

查看Handler的定义:

type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

 它是一个interface, 那么也就是说它作为参数的话,那么这个struct必须实现ServeHTTP(ResponseWriter, *Request) 这个方法。

在gin.go中查看ServeHTTP方法的定义:

// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := engine.pool.Get().(*Context) 返回的是New()里面定义的func,然后执行。
c.writermem.reset(w)
c.Request = req
c.reset() engine.handleHTTPRequest(c) engine.pool.Put(c)
}

 这里的engine.pool.Get().(*Context) 方法,实际上执行的是上面的New方法,所以得到的是一个Context类型的指针。

分析到这里,也就是说,如果有一个HTTP请求到来,那么会先触发ServeHTTP方法得到一个Context请求上下文,然后调用engine.handleHTTPRequest(C),处理这个请求,同时将处理的内容写入到http.ResponseWriter中。

关于engine.handleHTTPRequest()如何实现的,参考gin 路由表的设计

处理完以后为什么还要执行engine.pool.Put(c)呢?

因为:engine.pool需要一个buffer来存储内容,当下一个请求到达的时候,就可以直接来使用,避免又调用一次New函数,节省了内存。

go web framework gin 启动流程分析的更多相关文章

  1. go web framework gin 路由表的设计

    在上一篇go web framework gin 启动流程分析这一篇文章中,我分析了go gin启动的过程,在这一篇文章中我将继续上面的分析,讨论gin 中路由表是如何设计的? 首先查看engine. ...

  2. go web framework gin middleware 设计原理

    场景:一个middleware可以具体为一个函数,而由前面的gin 路由分析可得,每一个路径都对有一个HandlersChain 与其对应. 那么实际上增加一个middleware的过程,就是将每一个 ...

  3. SpringBoot启动流程分析(五):SpringBoot自动装配原理实现

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  4. SpringBoot启动流程分析(六):IoC容器依赖注入

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  5. SpringBoot启动流程分析(一):SpringApplication类初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  6. SpringBoot启动流程分析(二):SpringApplication的run方法

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  7. u-boot启动流程分析(2)_板级(board)部分

    转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...

  8. GEF入门实例_总结_04_Eclipse插件启动流程分析

    一.前言 本文承接上一节:GEF入门实例_总结_03_显示菜单和工具栏 注意到app目录下的6个类文件. 这6个文件对RCP应用程序而言非常重要,可能我们现在对这几个文件的理解还是云里雾里,这一节我们 ...

  9. Android5 Zygote 与 SystemServer 启动流程分析

    Android5 Zygote 与 SystemServer 启动流程分析 Android5 Zygote 与 SystemServer 启动流程分析 前言 zygote 进程 解析 zygoterc ...

随机推荐

  1. 使用quartz数据库锁实现定时任务的分布式部署

    ,1.根据项目引用的quartz依赖版本,确定下载的quartz-distribution安装包,我项目引用的信息如下图所示: 2.解压,在\quartz-2.2.3-distribution\qua ...

  2. Spring 集成 Swagger UI

    <!-- Spring --> <dependency> <groupId>org.springframework.boot</groupId> < ...

  3. 根据MAC地址获取网络地址及ZDP_NwkAddrReq函数的用法

    1..对于设备需要获取本设备的网络地址和MAC地址: NLME_GetShortAddr()——返回本设备的16位网络地址 NLME_GetExtAddr()——  返回本设备的64位扩展地址 2.使 ...

  4. vue常见前端UI库

    vue常见前端UI库 VUE资源汇总:https://github.com/RuMengkai/awesome-vue VUX 项目主页:https://vux.li/#/ github地址:http ...

  5. Python基础(六)_全局变量声明、可变参数、关键字参数

    1. global声明全局变量 #声明name这个变量为全局变量,只是写在函数里面 #写代码时,尽量不要用全局变量,会一直占用内存.       ------->{'name':'abc','s ...

  6. LNMP 如何安装mongodb

    wget -c http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.4.tgztar -zxvf mongodb-linux-x86_64 ...

  7. 自制操作系统Antz(3)——进入保护模式 (中) 直接操作显存

    Antz系统更新地址: https://www.cnblogs.com/LexMoon/category/1262287.html Linux内核源码分析地址:https://www.cnblogs. ...

  8. win7 64位下redis的安装

    1.下载Redis安装包. 下载地址 https://github.com/MSOpenTech/redis,找到Release,点击前往下载页面,点击Redis-x64-3.2.100.msi下载. ...

  9. 使用C#加密及解密字符串

    using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Util ...

  10. Anaconda安装mysqldb模块

    在anaconda里mysqldb是封在mysql-python里的,所以要先在anaconda prompt里运行 conda install mysql-python.(注意要右键选管理员身份)有 ...