在 Gin v1.12.0 里实测路由树的节点:源码里 node 结构体的 8 个字段和 4 种 nodeType;8 条路由注册后树只有 12 个节点,wildChild、indices 和 :id 的位置;*filepath 要用两个 catchAll 节点;参数怎么取出;1000 条静态路由 1100 个节点、带 :id 则 2100 个。
在 Gin v1.12.0 里实测节点优先级:priority 是子树里的路由条数,注册时让条数多的子节点冒泡到 indices 前面(平局不交换);对一条路由发 20 万次请求后树逐字节不变;26 个兄弟节点里排在末位比排在首位多约 8 ns。
在 Gin v1.12.0 里实测 :id 与 *path 的差别::id 只匹配一段且不能为空,*path 匹配剩余的全部且值以斜杠开头;10 种注册组合里 8 种会在注册时 panic;/files/:name 默认匹配不了带 %2F 的名字,开 UseRawPath 后才行。
在 Gin v1.12.0 里把 18 组路由注册组合逐个试一遍,列出 panic 的原文:10 组 panic,静态与参数两个顺序都能共存;panic 发生在注册路由的那一行;静态与参数共存时请求先走静态分支,走不通再回溯到参数分支。
在 Gin v1.12.0 里实测 Group:11 种路径拼法的结果(path.Join 化简斜杠和 ..,结尾斜杠保留);嵌套 Group 里一条路由最终的 handler 个数;handler 链在注册那一刻拼好,之后再 Use 不影响已注册的路由和已创建的子组;Group.Use 不会让 404 经过组中间件。
在 Gin v1.12.0 里实测 RedirectTrailingSlash:路由与请求在结尾斜杠上不一致时,GET 返回 301、其他方法(含 HEAD)返回 307、CONNECT 直接 404,query 原样保留;X-Forwarded-Prefix 会进 Location 并过滤特殊字符;真实 HTTP 客户端遇到 307 时重发 POST 且 body 不丢。
在 Gin v1.12.0 里实测 RedirectFixedPath(默认 false):打开后 10 种写错的 URL(大小写、重复斜杠、./、../、结尾斜杠)全部 301 到规范路径;POST 是 307;命中路由的耗时不变,但 404 请求的耗时从约 36 ns 涨到约 137 ns。
在 Gin v1.12.0 里实测 405:HandleMethodNotAllowed 默认 false,方法不对只是 404;打开后返回 405 与 Allow 头(HEAD、OPTIONS 也不会自动处理);判定方式是到其它方法的树里查同一路径;Allow 的顺序是方法树的创建顺序;405 只做精确匹配,不做尾斜杠修正。
在 Gin v1.12.0 里实测 NoRoute 与 NoMethod:serveError 的流程;6 种 NoRoute 写法里只有只设头不写正文时才保留默认正文 404 page not found;NoRoute 的链是全局中间件加 NoRoute handler,404 时 FullPath 为空;NoMethod 需要打开 HandleMethodNotAllowed;Static 的 404 也走 NoRoute。
在 Gin v1.12.0 里实测每个 HTTP 方法一棵树:methodTrees 是线性扫描的切片;树的顺序是方法第一次被注册的顺序;r.Any 一次创建 9 棵树;Handle 要求方法名全是大写英文字母;26 棵方法树里,找第 26 棵比找第 1 棵慢约 62 ns。
在 Gin v1.12.0 里实测 c.FullPath():返回注册时的路由模板,在中间件里 Next 之前就能取到;404 与被重定向的请求为空;用它做监控标签,16000 个不同 URL 只产生 3 个标签值;r.Routes() 里 Handler 取的是链上最后一个函数的名字。
在 Gin v1.12.0 里实测路由数量从 10 条增长到 10 万条时匹配耗时的变化:静态路由随机命中一条从 41 ns 增长到 123 ns(约 3 倍),404 始终 37 ns;10 万条路由注册 43.5 ms、堆增加 22.8 MB;同一路径重复查询几乎不变(39 → 44 ns),变慢主要出现在访问不同路径时。