gin02:gin路径中的参数

本文来探讨gin是如何获取路径中的参数

gin获取路径中参数的示例

go 复制代码
func main() {
    router := gin.Default()

    router.GET("/user/:name", func(c *gin.Context) {
       name := c.Param("name")
       c.String(http.StatusOK, "hello %s", name)
    })
    router.GET("/user/:name/*action", func(context *gin.Context) {
       name := context.Param("name")
       action := context.Param("action")
       meesage := name + " is " + action
       context.String(http.StatusOK, meesage)
    })
    router.POST("/user/:name/*action", func(context *gin.Context) {
       b := context.FullPath() == "/user/:name/*action"
       context.String(http.StatusOK, "%t", b)
    })

    router.GET("/user/groups", func(context *gin.Context) {
       context.String(http.StatusOK, "可用的用户组是[...]")
    })
    router.Run("localhost:9090")
}

gin能够通过context.Param()就非常简单的获取了路径中的参数,接下来探讨它是怎么做到的。

Params

在gin.Context的结构体中有一个Params字段,其实际是[] Param类型

bash 复制代码
type Params []Param

而Param的结构体十分简单

go 复制代码
type Param struct {
    Key   string
    Value string
}

这就是底层参数的存储的数据结构,在调用context.Param()获取参数的时

go 复制代码
func (c *Context) Param(key string) string {
    return c.Params.ByName(key)
}

实际是调用了c.Params.ByName()

go 复制代码
func (ps Params) ByName(name string) (va string) {
    va, _ = ps.Get(name)
    return
}

而其底层是通过Get获取value

go 复制代码
func (ps Params) Get(name string) (string, bool) {
    for _, entry := range ps {
       if entry.Key == name {
          return entry.Value, true
       }
    }
    return "", false
}

这里可以看出,实际获取参数的操作,就是循环遍历了一遍底层的Param切片。默认返回空字符串""

Params的生命周期

在探讨了底层是如何获得参数的问题之后,现在有一个新的问题,Params的生命周期历程。 1.Params的重置

  • 在Engine的ServeHTTP方法中,从Context池中创建或者拿出一个Context
  • 调用Context.reset()针对它进行初始化
ini 复制代码
func (c *Context) reset() {
    c.Writer = &c.writermem
    c.Params = c.Params[:0]
    c.handlers = nil
    c.index = -1

    c.fullPath = ""
    c.Keys = nil
    c.Errors = c.Errors[:0]
    c.Accepted = nil
    c.queryCache = nil
    c.formCache = nil
    c.sameSite = 0
    *c.params = (*c.params)[:0]
    *c.skippedNodes = (*c.skippedNodes)[:0]
}
  1. Params的设置
    • 在根据请求方法获取到对应的路由树之后
    • 调用root.getValue(),传入请求的路径,和c.params
    • 获得一个nodeValue对象,其中包括逻辑处理链 ,参数 ,注册的路由
    • 将nodeValue的params赋给Context.Params
csharp 复制代码
root := t[i].root
// Find route in tree
value := root.getValue(rPath, c.params, c.skippedNodes, unescape)
if value.params != nil {
    c.Params = *value.params
}
  1. Context被回收
相关推荐
孙启超13 分钟前
【AI开发之Rust】第 21 课:双端集成与出包 —— Android(.so→AAR)与 iOS(xcframework)
开发语言·后端·rust
IT_陈寒21 分钟前
Java的HashMap线程安全问题让我深夜掉光了头发
前端·人工智能·后端
AINative软件工程22 分钟前
LLM 应用的 Chaos Engineering 工程实践:给 AI 系统下毒,才能知道它有多抗造
后端·llm·ai编程
JavaEdge.36 分钟前
Redis 连接断开后的自动重连操作
spring boot·redis·后端·lettuce·tcp keepalive
EatFan9 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
波力海苔夹心脆67511 小时前
C# 序列化与反序列化详解:System.Text.Json、Newtonsoft.Json、XmlSerializer 用法、特性选项与安全实践
经验分享·后端·c#·json·.net
JavaGuide12 小时前
NVIDIA 又开源了!这次给 AI Agent 加上权限管控
前端·后端
excel12 小时前
prisma 如何处理数据库竞态
前端·数据库·后端
IT_陈寒14 小时前
Java线程池这破玩意,差点让我周末加班排查到凌晨
前端·人工智能·后端