Gin框架通过net/http 网络库实现的来一个请求,开一个携程的处理方式
go c.serve(connCtx)
其中间件的运行与控制器的业务,按照顺序放入handle切片中,循环处理。
func (c *Context) Next() { c.index++ for s := int8(len(c.handlers)); c.index < s; c.index++ { c.handlers[c.index](c) } }
对于中间件中有调用Next()方法的,会先执行下一个handle,在继续Next()后面的代码。
如下是gin启动的一个web请求的流程。
// gin.go
gin.Run() // gin启动
http.ListenAndServe(address, engine)
// server.go
server := &Server{Addr: addr, Handler: handler}
server.ListenAndServe()
ln, err := net.Listen("tcp", addr) // 网络监听
srv.Serve(ln)
c := srv.newConn(rw) // 网络连接
c := &conn{
server: srv,
rwc: rwc,
}
go c.serve(connCtx) // 开启协程处理请求
serverHandler{c.server}.ServeHTTP(w, w.req)
// engine 实现了ServeHTTP 方法
// gin.go
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的数据结构
gin 框架
type Engine struct {
RouterGroup
RedirectTrailingSlash bool
RedirectFixedPath bool
HandleMethodNotAllowed bool
ForwardedByClientIP bool
AppEngine bool
UseRawPath bool
UnescapePathValues bool
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
}
allocateContext() *Context
Delims(left string, right string) *Engine
SecureJsonPrefix(prefix string) *Engine
LoadHTMLGlob(pattern string)
LoadHTMLFiles(files ...string)
SetHTMLTemplate(templ *template.Template)
SetFuncMap(funcMap template.FuncMap)
NoRoute(handlers ...HandlerFunc)
NoMethod(handlers ...HandlerFunc)
Use(middleware ...HandlerFunc) IRoutes // 将中间件,控制器,塞到handle切片中,逐一处理
rebuild404Handlers()
rebuild405Handlers()
addRoute(method string, path string, handlers HandlersChain)
Routes() (routes RoutesInfo)
Run(addr ...string) (err error)
RunTLS(addr string, certFile string, keyFile string) (err error)
RunUnix(file string) (err error)
ServeHTTP(w http.ResponseWriter, req *http.Request) // 实现Handler接口
HandleContext(c *Context)
handleHTTPRequest(c *Context)
// server := &Server{Addr: addr, Handler: handler}
// net/http server
type Server struct {
Addr string
Handler Handler
TLSConfig *tls.Config
ReadTimeout time.Duration
ReadHeaderTimeout time.Duration
WriteTimeout time.Duration
IdleTimeout time.Duration
MaxHeaderBytes int
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
ConnState func(net.Conn, ConnState)
ErrorLog *log.Logger
BaseContext func(net.Listener) context.Context
ConnContext func(ctx context.Context, c net.Conn) context.Context
inShutdown atomicBool
disableKeepAlives int32
nextProtoOnce sync.Once
nextProtoErr error
mu sync.Mutex
listeners map[*net.Listener]struct{}
activeConn map[*conn]struct{}
doneChan chan struct{}
onShutdown []func()
}
newConn(rwc net.Conn) *conn
maxHeaderBytes() int
initialReadLimitSize() int64
getDoneChan() <-chan struct{}
getDoneChanLocked() chan struct{}
closeDoneChanLocked()
Close() error
Shutdown(ctx context.Context) error
RegisterOnShutdown(f func())
numListeners() int
closeIdleConns() bool
closeListenersLocked() error
ListenAndServe() error
shouldConfigureHTTP2ForServe() bool
Serve(l net.Listener) error
ServeTLS(l net.Listener, certFile string, keyFile string) error
trackListener(ln *net.Listener, add bool) bool
trackConn(c *conn, add bool)
idleTimeout() time.Duration
readHeaderTimeout() time.Duration
doKeepAlives() bool
shuttingDown() bool
SetKeepAlivesEnabled(v bool)
logf(format string, args ...interface{})
ListenAndServeTLS(certFile string, keyFile string) error
setupHTTP2_ServeTLS() error
setupHTTP2_Serve() error
onceSetNextProtoDefaults_Serve()
onceSetNextProtoDefaults()
ExportAllConnsIdle() bool
// 连接信息
type conn struct {
server *Server
cancelCtx context.CancelFunc
rwc net.Conn
remoteAddr string
tlsState *tls.ConnectionState
werr error
r *connReader
bufr *bufio.Reader
bufw *bufio.Writer
lastMethod string
curReq atomic.Value
curState struct {
atomic uint64
}
mu sync.Mutex
hijackedv bool
}
hijacked() bool
hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error)
readRequest(ctx context.Context) (w *response, err error)
finalFlush()
close()
closeWriteAndWait()
setState(nc net.Conn, state ConnState)
getState() (state ConnState, unixSec int64)
serve(ctx context.Context)