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 ...
随机推荐
- Vue系列之 => computed实现求值
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- spring boot + vue + element-ui全栈开发入门——主页面开发
目的 开发一个后台管理的前端,顶部是标题,左侧是菜单导航栏,中间是要显示的内容.而内容可以是各种图表,也可以是数据列表. 一.准备工作 1..修改App.vue文件 代码如下: <templat ...
- Nginx技术研究系列7-Azure环境中Nginx高可用性和部署架构设计
前几篇文章介绍了Nginx的应用.动态路由.配置.在实际生产环境部署时,我们需要同时考虑Nginx的高可用性和部署架构. Nginx自身不支持集群以保证自身的高可用性,商业版本的Nginx+推荐: T ...
- mysql插入数据报错1366
数据表插入中文数据报错 Warning Code : 1366 Incorrect string value: '\xE5\x9C\xA8' for column 'name' at row 1 原因 ...
- Docker Kubernetes 健康检查
Docker Kubernetes 健康检查 提供Probe探测机制,有以下两种类型: livenessProbe:如果检查失败,将杀死容器,然后根据Pod的重启策略来决定是否重启. readines ...
- vim自动补全头注释与说明
做个笔记吧. .vimrc autocmd BufNewFile *.c,*.cpp,*.sh,*.py,*.java exec ":call SetTitle()" " ...
- [c/c++] programming之路(20)、字符串(一)
一.字符串 #include<stdio.h> #include<stdlib.h> void main(){ ]="notepad"; printf(&q ...
- 【jvisualvm远程监控配置】
第一步:首先通过hostname -i 和ifconfig命令,查看一下IP地址是否一致 如果不一致,修改hosts的IP地址:vi /etc/hosts 把ip地址和ifconfig的地址修 ...
- socket实现文件传输
server:===========================================import socketimport structimport jsonsk = socket.s ...
- 近期Freecodecamp问题总结
最近没什么事,刷了freecodecamp的算法题,发现了自己基础的薄弱 1 where are thou 写一个 function,它遍历一个对象数组(第一个参数)并返回一个包含相匹配的属性-值对( ...