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的重置

  • EngineServeHTTP方法中,从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对象,其中包括逻辑处理链参数注册的路由
    • nodeValueparams赋给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被回收
相关推荐
架构师沉默4 分钟前
程序员如何避免猝死?
java·后端·架构
椰奶燕麦22 分钟前
Windows PackageManager (winget) 核心故障排错与通用修复指南
后端
zjjsctcdl1 小时前
springBoot发布https服务及调用
spring boot·后端·https
zdl6861 小时前
Spring Boot文件上传
java·spring boot·后端
世界哪有真情1 小时前
哇!绝了!原来这么简单!我的 Java 项目代码终于被 “拯救” 了!
java·后端
RMB Player1 小时前
Spring Boot 集成飞书推送超详细教程:文本消息、签名校验、封装工具类一篇搞定
java·网络·spring boot·后端·spring·飞书
重庆小透明2 小时前
【搞定面试之mysql】第三篇 mysql的锁
java·后端·mysql·面试·职场和发展
武超杰2 小时前
Spring Boot入门教程
java·spring boot·后端
IT 行者2 小时前
Spring Boot 集成 JavaMail 163邮箱配置详解
java·spring boot·后端
gelald3 小时前
JVM - 运行时内存模型
java·jvm·后端