gin源码阅读【3】-httpServe

gin从本质上来讲就是扩展了 原生的http服务,所以网上也有很多改造gin来适配fasthttp之类的,其实就是替换掉原生的http服务。

1、Engine.Run()方法调用了http.ListenAndServe(address, engine.Handler())。

这个方法接触的贼拉多,有时候我们说启动一个东西直接说run起来。。。。。这里也是把一个httpserve run起来。

func (engine *Engine) Run(addr ...string) (err error) {
    defer func() { debugPrintError(err) }()

    if engine.isUnsafeTrustedProxies() {
       debugPrint("[WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.\n" +
          "Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
    }

    address := resolveAddress(addr)
    debugPrint("Listening and serving HTTP on %s\n", address)
    err = http.ListenAndServe(address, engine.Handler())
    return
}

2、ListenAndServe的第二个参数是handler接口,需要实现ServeHTTP方法,接口定义如下:

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

3、engine.Handler()实现了返回的一个engin实例,其中实现了ServeHTTP方法,完成了http.Handler的实现。

func (engine *Engine) Handler() http.Handler {
    if !engine.UseH2C {  //如果要不使用H2C的话,直接返回,默认就是这个
       return engine
    }

    h2s := &http2.Server{}
    return h2c.NewHandler(engine, h2s)
}

3、engine的SerHTTP方法

func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}

这里有一个比较有意思的点,就是engine.pool。engine.pool实际上是一个sync.Pool,我之前的文章 go并发编程常用的一些方法及解释

golang并发编程里面说到过的,他是一个不可靠的pool,虽然不可靠,但是用来做Context的池子也不错,避免了每次请求都要去创建Context的损耗。

4、最后engine.handleHTTPRequest(c)实现具体的路由分发,gin的路由分发有些复杂,下篇来讲。

如此这般就对接了golang的原生http。感觉挺简单的,理论上自己实现一套去实现ServeHTTP也不是什么很复杂度的事情,但是不能见识了巨人肩膀上的风景就觉得巨人不过如此呢。哈哈哈哈。

发布于
标记为