news 2026/6/14 15:54:55

Gin源码解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Gin源码解析

结构

Engine
RouterGroup
HandlersChain
Context

Engine的结构为

typeEnginestruct{RouterGroup routeTreesUpdated sync.Once RedirectTrailingSlashboolRedirectFixedPathboolHandleMethodNotAllowedboolForwardedByClientIPboolAppEngineboolUseRawPathboolUseEscapedPathboolUnescapePathValuesboolRemoveExtraSlashboolRemoteIPHeaders[]stringTrustedPlatformstringMaxMultipartMemoryint64UseH2CboolContextWithFallbackbooldelims render.Delims secureJSONPrefixstringHTMLRender render.HTMLRender FuncMap template.FuncMap allNoRoute HandlersChain allNoMethod HandlersChain noRoute HandlersChain noMethod HandlersChain pool sync.Pool trees methodTrees maxParamsuint16maxSectionsuint16trustedProxies[]stringtrustedCIDRs[]*net.IPNet}

allNoRoute:没有找到路由时的处理链
allNoMethod:方法没有找到时的处理链
RouterGroup结构为

typeRouterGroupstruct{Handlers HandlersChain basePathstringengine*Engine rootbool}

HandlersChain为函数切片

typeHandlerFuncfunc(*Context)typeHandlersChain[]HandlerFunc

Context为处理中的关键数据结构

typeContextstruct{writermem responseWriter Request*http.Request Writer ResponseWriter Params Params handlers HandlersChain indexint8fullPathstringengine*Engine params*Params skippedNodes*[]skippedNode// This mutex protects Keys map.mu sync.RWMutex// Keys is a key/value pair exclusively for the context of each request.Keysmap[any]any// Errors is a list of errors attached to all the handlers/middlewares who used this context.Errors errorMsgs// Accepted defines a list of manually accepted formats for content negotiation.Accepted[]string// queryCache caches the query result from c.Request.URL.Query().queryCache url.Values// formCache caches c.Request.PostForm, which contains the parsed form data from POST, PATCH,// or PUT body parameters.formCache url.Values// SameSite allows a server to define a cookie attribute making it impossible for// the browser to send this cookie along with cross-site requests.sameSite http.SameSite}

创建

创建Engine是通过Default方法

  • 先使用New()创建Engine
  • 使用OptionFunc函数来配置Engine
funcDefault(opts...OptionFunc)*Engine{debugPrintWARNINGDefault()engine:=New()engine.Use(Logger(),Recovery())returnengine.With(opts...)}funcNew(opts...OptionFunc)*Engine{debugPrintWARNINGNew()engine:=&Engine{RouterGroup:RouterGroup{Handlers:nil,basePath:"/",root:true,},FuncMap:template.FuncMap{},RedirectTrailingSlash:true,RedirectFixedPath:false,HandleMethodNotAllowed:false,ForwardedByClientIP:true,RemoteIPHeaders:[]string{"X-Forwarded-For","X-Real-IP"},TrustedPlatform:defaultPlatform,UseRawPath:false,UseEscapedPath:false,RemoveExtraSlash:false,UnescapePathValues:true,MaxMultipartMemory:defaultMultipartMemory,trees:make(methodTrees,0,9),delims:render.Delims{Left:"{{",Right:"}}"},secureJSONPrefix:"while(1);",trustedProxies:[]string{"0.0.0.0/0","::/0"},trustedCIDRs:defaultTrustedCIDRs,}engine.engine=engine engine.pool.New=func()any{returnengine.allocateContext(engine.maxParams)}returnengine.With(opts...)}func(engine*Engine)With(opts...OptionFunc)*Engine{for_,opt:=rangeopts{opt(engine)}returnengine}

OptionFunc为函数别名

typeOptionFuncfunc(*Engine)

运行

是通过Run来执行

  • 在没有指定地址信息时,读取环境变量PORT端口号,没有则默认使用端口号8080
  • 内部创建http.Server,handler为engine.Handler(),执行http.Server的方法ListenAndServe,其中Engine是实现了http.Handler接口
func(engine*Engine)Run(addr...string)(errerror){deferfunc(){debugPrintError(err)}()ifengine.isUnsafeTrustedProxies(){debugPrint("[WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.\n"+"Please check https://github.com/gin-gonic/gin/blob/master/docs/doc.md#dont-trust-all-proxies for details.")}engine.updateRouteTrees()address:=resolveAddress(addr)debugPrint("Listening and serving HTTP on %s\n",address)server:=&http.Server{// #nosec G112Addr:address,Handler:engine.Handler(),}err=server.ListenAndServe()return}

Engine实现了http.Handler接口方法ServeHTTP,内部调用handleHTTPRequest,根据请求方法和请求url,找到对应的HandlersChain,执行Context的Next()方法,遍历处理链执行处理

func(engine*Engine)ServeHTTP(w http.ResponseWriter,req*http.Request){engine.routeTreesUpdated.Do(func(){engine.updateRouteTrees()})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:=falseifengine.UseEscapedPath{rPath=c.Request.URL.EscapedPath()unescape=engine.UnescapePathValues}elseifengine.UseRawPath&&len(c.Request.URL.RawPath)>0{rPath=c.Request.URL.RawPath unescape=engine.UnescapePathValues}ifengine.RemoveExtraSlash{rPath=cleanPath(rPath)}// Find root of the tree for the given HTTP methodt:=engine.treesfori,tl:=0,len(t);i<tl;i++{ift[i].method!=httpMethod{continue}root:=t[i].root// Find route in treevalue:=root.getValue(rPath,c.params,c.skippedNodes,unescape)ifvalue.params!=nil{c.Params=*value.params}ifvalue.handlers!=nil{c.handlers=value.handlers c.fullPath=value.fullPath c.Next()c.writermem.WriteHeaderNow()return}ifhttpMethod!=http.MethodConnect&&rPath!="/"{ifvalue.tsr&&engine.RedirectTrailingSlash{redirectTrailingSlash(c)return}ifengine.RedirectFixedPath&&redirectFixedPath(c,root,engine.RedirectFixedPath){return}}break}ifengine.HandleMethodNotAllowed&&len(t)>0{// According to RFC 7231 section 6.5.5, MUST generate an Allow header field in response// containing a list of the target resource's currently supported methods.allowed:=make([]string,0,len(t)-1)for_,tree:=rangeengine.trees{iftree.method==httpMethod{continue}ifvalue:=tree.root.getValue(rPath,nil,c.skippedNodes,unescape);value.handlers!=nil{allowed=append(allowed,tree.method)}}iflen(allowed)>0{c.handlers=engine.allNoMethod c.writermem.Header().Set("Allow",strings.Join(allowed,", "))serveError(c,http.StatusMethodNotAllowed,default405Body)return}}c.handlers=engine.allNoRouteserveError(c,http.StatusNotFound,default404Body)}func(c*Context)Next(){c.index++forc.index<safeInt8(len(c.handlers)){ifc.handlers[c.index]!=nil{c.handlers[c.index](c)}c.index++}}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 2:21:26

AI 加速新药研发:从 10 年到 2 年,成本降低 75% 的技术逻辑

一、传统新药研发的效率困局&#xff1a;时间与成本的双重枷锁新药研发曾是公认的 “高投入、长周期、低成功率” 行业。波士顿咨询数据显示&#xff0c;传统模式下一款新药从靶点发现到上市需 10-15 年&#xff0c;总成本超 20 亿美元&#xff0c;而最终成功率仅 2%-15%。这种…

作者头像 李华
网站建设 2026/6/12 19:54:56

PyTorch Geometric实战指南:7天精通图神经网络开发

想要快速掌握图神经网络开发却苦于无从下手&#xff1f;PyTorch Geometric&#xff08;PyG&#xff09;作为图神经网络领域的标杆工具库&#xff0c;为你提供了一条高效的学习路径。这个基于PyTorch构建的专业库&#xff0c;专门用于处理结构化数据的深度学习任务&#xff0c;让…

作者头像 李华
网站建设 2026/6/13 19:41:38

通达信主力拉高洗盘 源码

{}VAR1:REF((LOWOPENCLOSEHIGH)/4,1); VAR2:SMA(ABS(LOW-VAR1),13,1)/SMA(MAX(LOW-VAR1,0),10,1); VAR3:EMA(VAR2,10); VAR4:LLV(LOW,33); VAR5:EMA(IF(LOW<VAR4,VAR3,0),3); 主力进场:IF(VAR5>REF(VAR5,1),VAR5,0),COLORRED,NODRAW; 洗盘:IF(VAR5<REF(VAR5,1),VAR5,0…

作者头像 李华
网站建设 2026/6/13 20:19:09

Ocelot中间件扩展实战:从业务痛点到大厂架构的跨越

Ocelot中间件扩展实战&#xff1a;从业务痛点到大厂架构的跨越 【免费下载链接】Ocelot 项目地址: https://gitcode.com/gh_mirrors/oce/Ocelot 你是否遇到过这样的场景&#xff1a;业务方要求API网关支持JWT黑名单验证&#xff0c;但Ocelot默认认证中间件无法满足&…

作者头像 李华
网站建设 2026/6/13 15:10:49

堆排序详解

堆排序详解堆的简述堆排序概述堆排序的树状结构下标访问的前提准备建堆过程排序与调整过程堆排序的具体实现交换函数调整堆结构函数调用堆调整的排序主函数最后一个有子节点的父节点的下标关系小结堆的简述 堆是一种完全二叉树&#xff0c;并且满足&#xff1a; 大根堆每个节点…

作者头像 李华
网站建设 2026/6/13 11:39:24

17、《Python:系统管理与应用开发的全能之选》

《Python:系统管理与应用开发的全能之选》 1. Python在系统管理中的应用 系统管理在我们的计算环境中至关重要,无论是工作还是家庭场景。Linux作为基于UNIX的操作系统,拥有众多强大的内置工具和功能,如多种优秀的shell(Bash、csh、zsh等),然而,Python在系统管理中仍有…

作者头像 李华