go web framework gin 启动流程分析
最主要的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 启动流程分析的更多相关文章
- go web framework gin 路由表的设计
在上一篇go web framework gin 启动流程分析这一篇文章中,我分析了go gin启动的过程,在这一篇文章中我将继续上面的分析,讨论gin 中路由表是如何设计的? 首先查看engine. ...
- go web framework gin middleware 设计原理
场景:一个middleware可以具体为一个函数,而由前面的gin 路由分析可得,每一个路径都对有一个HandlersChain 与其对应. 那么实际上增加一个middleware的过程,就是将每一个 ...
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(六):IoC容器依赖注入
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(一):SpringApplication类初始化过程
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(二):SpringApplication的run方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- u-boot启动流程分析(2)_板级(board)部分
转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...
- GEF入门实例_总结_04_Eclipse插件启动流程分析
一.前言 本文承接上一节:GEF入门实例_总结_03_显示菜单和工具栏 注意到app目录下的6个类文件. 这6个文件对RCP应用程序而言非常重要,可能我们现在对这几个文件的理解还是云里雾里,这一节我们 ...
- Android5 Zygote 与 SystemServer 启动流程分析
Android5 Zygote 与 SystemServer 启动流程分析 Android5 Zygote 与 SystemServer 启动流程分析 前言 zygote 进程 解析 zygoterc ...
随机推荐
- Flask最强攻略 - 跟DragonFire学Flask - 第十五篇 Flask-Script
其实本章就是为下一章做的铺垫啦,但是也要认真学习哦 Flask-Script 从字面意思上来看就是 Flask 的脚本 是的,熟悉Django的同学是否还记得Django的启动命令呢? python ...
- Python 两个星号(**)的 参数
将参数以字典的形式导入
- sparkStreaming 与fafka直接方式 进行消费者偏移量的保存如redis 里面 避免代码改变与节点重启后的数据丢失与序列化问题
import java.util import kafka.common.TopicAndPartition import kafka.message.MessageAndMetadata impor ...
- js 清空html input file的值
在做上传图片预览时,利用input onchange事件触发函数,但是type=file时,一定记得新建要清空原来的图片,因为原来的图片还存在在input里面,再选重复的图片没有change,故不会触 ...
- MySQL5.7 Dockerfile
#Dockerfile for mysql5.7 FROM centos COPY ["src","/src"] RUN groupadd -g 1003 my ...
- shell爬虫--抓取某在线文档所有页面
在线教程一般像流水线一样,页面有上一页下一页的按钮,因此,可以利用shell写一个爬虫读取下一页链接地址,配合wget将教程所有内容抓取. 以postgresql中文网为例.下面是实例代码 #!/bi ...
- Java(1)JDK安装
1.安装JDK开发环境 下载网站:http://www.oracle.com/ 开始安装JDK: 修改安装目录如下: 确定之后,单击"下一步". 注:当提示安装JRE时,可以选择不 ...
- redis编译问题
在编译redis时,出现以下问题 In file included from adlist.c:34:0: zmalloc.h:50:31: fatal error: jemalloc/jemallo ...
- Robot Framework问题记录
robotframework运行时后台报错UnicodeDecodeError UnicodeDecodeError :'utf-8' codec can't decode byte 0xb2 in ...
- 【NET Core】事务TransactionScope
.NET FrameWork时期: TransactionScope是FCL System.Transactions命名空间下的分布式事务组件,它默认为本地事务,当系统有需要时可以自动提升为分布式事务 ...