Context結(jié)構(gòu)
Context結(jié)構(gòu)定義
type Context struct {
// responseWriter對(duì)ResponseWriter封裝
writermem responseWriter
// http請(qǐng)求及響應(yīng)writer
Request *http.Request
Writer ResponseWriter
// 鍵值對(duì)切片類型
Params Params
// HandlerFunc切片類型
handlers HandlersChain
index int8
fullPath string
// 當(dāng)前上下文屬于哪個(gè)引擎
engine *Engine
// 每個(gè)請(qǐng)求上下文專用鍵值對(duì)
Keys map[string]interface{}
// *Error切片類型汤善,Error封裝error類型
//所有使用當(dāng)前上下文的handlers/middlewares對(duì)應(yīng)的出錯(cuò)信息都存放在這里
Errors errorMsgs
// Accepted defines a list of manually accepted formats for content negotiation.
Accepted []string
// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
queryCache url.Values
// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
// or PUT body parameters.
formCache url.Values
}
url.Values
類型定義
// key類型為string枕赵,value類型為[]string牌柄,一個(gè)key對(duì)應(yīng)多個(gè)value
type Values map[string][]string
方法集
// 通過(guò)key獲取對(duì)應(yīng)的value,如果存在,總會(huì)返回v[key][0],否則為""
func (v Values) Get(key string) string
// 設(shè)置鍵值對(duì)key/[]string{value}丑慎,若key之前有數(shù)據(jù),會(huì)被替換掉
func (v Values) Set(key, value string)
// 給key的value列表增加數(shù)據(jù)value
func (v Values) Add(key, value string)
// 刪除key及對(duì)應(yīng)的所有values
func (v Values) Del(key string)
有HTTP請(qǐng)求時(shí)瓤摧,gin處理流程:
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)
}
func (engine *Engine) handleHTTPRequest(c *Context) {
httpMethod := c.Request.Method
rPath := c.Request.URL.Path
unescape := false
if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
rPath = c.Request.URL.RawPath
unescape = engine.UnescapePathValues
}
rPath = cleanPath(rPath)
// 通過(guò)給定的HTTP請(qǐng)求方法找到方法樹(shù)
t := engine.trees
for i, tl := 0, len(t); i < tl; i++ {
if t[i].method != httpMethod {
continue
}
root := t[i].root
// 找到樹(shù)中的路由
value := root.getValue(rPath, c.Params, unescape)
if value.handlers != nil {
c.handlers = value.handlers
c.Params = value.params
c.fullPath = value.fullPath
c.Next()
c.writermem.WriteHeaderNow()
return
}
if httpMethod != "CONNECT" && rPath != "/" {
if value.tsr && engine.RedirectTrailingSlash {
redirectTrailingSlash(c)
return
}
if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) {
return
}
}
break
}
if engine.HandleMethodNotAllowed {
for _, tree := range engine.trees {
if tree.method == httpMethod {
continue
}
if value := tree.root.getValue(rPath, nil, unescape); value.handlers != nil {
c.handlers = engine.allNoMethod
serveError(c, http.StatusMethodNotAllowed, default405Body)
return
}
}
}
c.handlers = engine.allNoRoute
serveError(c, http.StatusNotFound, default404Body)
}