最主要的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. Web基础学习---HTML 第一天

    Web基础学习---HTML 第一天 1 HTML标签 2.CSS Web开发基础HTML好吧离开Python几天...如何学好前端?? 多去看别人的网站.多看.多写.多练,(知乎.36Kr.)多练就 ...

  2. oracle 死锁

    oracle 死锁 --查用户名,查客户端机器 SELECT distinct s.username,s.MACHINE, s.sid||','||s.serial# FROM gv$session ...

  3. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  4. 各种数据库连接字符串 -- c#

    sqlite : connectionString="Data Source=|DataDirectory|\databasename.db;Pooling=true;FailIfMissi ...

  5. python的优点

    在当下编程语言繁多,选择python是因为他存在这许多的优点: Python是一种效率极高的语言:相比于众多其他的语言,使用Python编写时,程序包含的代码行更少.Python的语法也有助于创建整洁 ...

  6. MVC设计思路

    MVC 学会重复.学会总结.学会预习和练习 前端页面  <---->   服务器(控制层.业务层.DAO层) <--->  DB 说明:无论是框架还是servletJSP,用的 ...

  7. Java实现简单的RPC框架

    一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用) ...

  8. LINQ之路15:LINQ Operators之元素运算符、集合方法、量词方法

    本篇继续LINQ Operators的介绍,包括元素运算符/Element Operators.集合方法/Aggregation.量词/Quantifiers Methods.元素运算符从一个sequ ...

  9. 获取经纬度之间两点间真实距离(适用于GoogleMap,BaiduMap,Amap等)

    如何获取经纬度之间两点间真实距离(适用于GoogleMap,BaiduMap,Amap等)  目标:使用百度定位sdk开发实时移动距离计算功能,根据经纬度的定位,计算行驶公里数并实时刷新界面显示.大家 ...

  10. js 字符串,new String() 与 String()

    function showCase(value) { switch(value) { case 'A': console.log('Case A'); break; case 'B': console ...