gin学习之context篇

Context结构

Context结构定义

type Context struct {
    // responseWriter对ResponseWriter封装
    writermem responseWriter

    // http请求及响应writer
    Request   *http.Request
    Writer    ResponseWriter

    // 键值对切片类型
    Params   Params

    // HandlerFunc切片类型
    handlers HandlersChain
    index    int8
    fullPath string

    // 当前上下文属于哪个引擎
    engine *Engine

    // 每个请求上下文专用键值对
    Keys map[string]interface{}

    // *Error切片类型,Error封装error类型
    //所有使用当前上下文的handlers/middlewares对应的出错信息都存放在这里
    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,一个key对应多个value
type Values map[string][]string

方法集

// 通过key获取对应的value,如果存在,总会返回v[key][0],否则为""
func (v Values) Get(key string) string

// 设置键值对key/[]string{value},若key之前有数据,会被替换掉
func (v Values) Set(key, value string)

// 给key的value列表增加数据value
func (v Values) Add(key, value string)

// 删除key及对应的所有values
func (v Values) Del(key string)

有HTTP请求时,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)

    // 通过给定的HTTP请求方法找到方法树
    t := engine.trees
    for i, tl := 0, len(t); i < tl; i++ {
        if t[i].method != httpMethod {
            continue
        }
        root := t[i].root
        // 找到树中的路由
        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)
}
  

你可能感兴趣的:(gin学习之context篇)