Gin源码分析一:引擎 Engine
在完成 Gin 的基本使用之后,就一直打算自习看一下 gin 的源码,结果一拖就拖到现在。现在有时间把这个坑慢慢补上。
引擎(Engine)
gin/gin.go at master · gin-gonic/gin
大部分的 Go 的 HTTP 框架都是在重写路由部分,已实现更快的更准确的路由查找,减少路由解析过程中消耗的时间,来提高框架的处理速度。
标准库 HTTP 的处理
Go 语言标准库处理 HTTP 请求的流程大致如下:
启动 HTTP 服务器:使用 http.ListenAndServe 或 http.ListenAndServeTLS 函数启动 HTTP 服务器。
处理请求:当服务器接收到 HTTP 请求时,它会使用与路径相对应的 http.Handler 实现处理请求。
调用处理程序:服务器会调用 ServeHTTP
方法,并将请求相关的信息作为参数传递给该方法。
路由匹配:在 ServeHTTP
方法中,通过比较请求的路径和已注册的路由,找到与请求匹配的路由。
调用处理函数:如果找到了匹配的路由,则调用与该路由相关的处理函数。
写入响应:处理函数通过 ResponseWriter 接口写入响应数据,以返回给客户端。
Go 语言标准库中的主要方法有:http.Handle 和 http.HandleFunc 用于注册路由和处理函数;
http.ListenAndServe
和 http.ListenAndServeTLS
用于启动 HTTP 服务器;以及 http.ResponseWriter
和 http.Request
分别用于写入响应和处理请求。
ServeHTTP 方法
在 gin 中,通过 Engine
这个对象进行管理,这个对象是实现了 ServeHTTP
这个方法。这个方法是 Go 标准库 net/http
中声明的一个接口方法。通过该接口来做到路由的转发。
|
|
Gin 收到相关的请求,都会统一调用 ServeHTTP
方法,该方法会将接收到的参数等进行处理,例如寻找合适的处理器(Handler),最后返回统一的处理结果。
这个是整个 HTTP 框架的关键,是处理 HTTP 请求的入口也是出口。
|
|
找到了相关的入口,接下来可以分析整个处理流程,先看主要的对象 Engine
。
这也是我们使用 Gin 过程中第一使用的结构体。
这个结构体较为复杂,里面定义了大量的变量。根据我们之前看到的 ServeHTTP
方法中,首先使用到的变量有 pool
。
这里的 pool 使用的 sync.Pool
这个类型,主要是用来重复使用的 Context
。
这里直接从 pool 中取出 Context,并对 Context 的一些参数进行设置,最后调用 engine.handleHTTPRequest
方法。
engine.handleHTTPRequest
这个方法主要处理用户的 HTTP 请求,确定该请求的处理方法。简单的来说就:首先,获取请求的 HTTP 方法(如 GET 或 POST)和 URL 路径,并在需要时解码路径。然后,它搜索匹配该请求的处理树。如果找到了一个匹配的节点,它会将处理程序分配给请求的上下文(c),并写入 HTTP 响应头。如果未找到匹配的节点,则会写入 “405 Method Not Allowed” 或 “404 Not Found” 的错误响应。
这样基本就是一个简单的 http 请求的处理过程。在代码中可以看到很多事情其实是由上下文(Context) 进行处理的。
如何Run
那么 Gin 框架是如何运行起来的。
|
|
这里的三个方法基本就是 Gin 的主要方式,从这三个方法会看明白 Gin 的 engine 如何工作的。
Default()
在 Default()
方法中,主要还是使用了 New()
方法来创建。
New()
方法主要对 Engine 进行了初始化。
之后设置了两个中间件(Middleware),用于日志和异常的 Recovery。
都出事完成后返回 engine。
Run()
这个方法主要是在给定的地址上进行监听和创建相关的 HTTP 服务。
首先会判断是否为不安全的代理 isUnsafeTrustedProxies()
。
代码调用了 isTrustedProxy
方法,主要是对 trustedCIDRs
这个变量进行检查。这个变量在 New()
的时候就会进行初始化。
|
|
通过输入的 IP 会和 trustedCIDRs 进行比较,看看是否包含在其中。如果不包含就返回 false。默认的表达式为所有的 IPv4 和 IPv6 都符合。
另外通过 resolveAddress
方法进行地址解析,其实是指对端口解析。这个方法的输入为一个切片。如果用户不输入的时候,通过读取环境变量获取端口 os.Getenv("PORT")
。如果无法获取环境变量的端口,那么就默认为 8080
。当用户输入具体的端口后,采用用户的输入。用户输入的数据过长,那么就会报错。
当上述都满足的时候,通过 http.ListenAndServe(address, engine.Handler())
进行启动。
更多 http 标准库工作原理可以看 HTTP 标准库。
这样 Gin 框架就运行起来了。
相关内容
如果你觉得这篇文章对你有所帮助,欢迎赞赏~
赞赏