专栏首页飞雪无情的博客Golang Gin 实战(三)| 路由参数

Golang Gin 实战(三)| 路由参数

在 上一篇 Golang Gin 实战(二)| 简便的Restful API 实现 文章中,我们留了一个疑问,假如我们有很多用户,我们要为他们一个个注册路由(路径)吗?

路由路径

如下URL:

/users/123
/users/456
/users/23456

以上等等,我们有很多用户,如果我们都一个个为这些用户注册这些路由(URL),那么我们是很难注册完的,而且我们还会有新注册的用户,可见这种办法不行。

我们观察这些路由(URL),发现它们具备一定的规则:前面都是users,后面是usersid。这样我们就可以把这些路由归纳为:

/users/id

这样我们就知道只有id这部分是可以变的,前面的users是不变的。可变的id可以当成我们API服务输入的参数,这样我们就可以通过这个id参数,获取对应的用户信息,这种URL匹配的模式,我们称之为路由参数。

路由参数

Gin中,要实现以上路由参数非常简单:

func main() {
	r := gin.Default()

	r.GET("/users/:id", func(c *gin.Context) {
		id := c.Param("id")
		c.String(200, "The user id is  %s", id)
	})
	r.Run(":8080")
}

我们运行如上代码,打开浏览器,输入http://localhost:8080/users/123,就可以看到如下信息:

The user id is  123

我们可以更换http://localhost:8080/users/123中的id 123 为其他字符串,会发现都可以正常打印,这就是路由匹配、路由正则,或者路由参数。

Gin的路由采用的是httprouter,所以它的路由参数的定义和httprouter也是一样的。

/users/:id 就是一种路由匹配模式,也是一个通配符,其中:id就是一个路由参数,我们可以通过c.Param("id")获取定义的路由参数的值,然后用来做事情,比如打印出来。

/users/:id这种匹配模式是精确匹配的,只能匹配一个,我们举几个例子说明:

Pattern: /users/:id

/users/123          匹配
/users/哈哈        匹配
/users/123/go      不匹配
/users/             不匹配

这里我故意写了/users/哈哈,并且是匹配的,意思就是对于Gin路径中的匹配都是字符串,它是不区分数字、字母和汉字的,都匹配。

这里还需要说明的是,Gin的路由是单一的,不能有重复。比如这里我们注册了/users/:id,那么我们就不能再注册匹配/users/:id模式的路由,比如:

r.GET("/users/list", func(c *gin.Context) {
	//省略无关代码
})

这时候我们运行程序的话,会出现如下提示:

panic: 'list' in new path '/users/list' conflicts with existing wildcard ':id' in existing prefix '/users/:id'

通配符重复了,路由必须要唯一。Gin内部使用的路由是httprouter,我这里前段时间正好有一篇关于httprouter的详细分析,可以看下。Go语言经典库使用分析(七)| 高性能可扩展 HTTP 路由 httprouter

星号路由参数

上面我们介绍的是:号的路由参数,这种路由参数最常用。还有一种不常用的就是*号类型的参数,表示匹配所有。

/users/*id为例:

Pattern: /users/*id

/users/123         匹配
/users/哈哈        匹配
/users/123/go      匹配
/users/            匹配

我们把上面的例子改下:

func main() {
	r := gin.Default()

	r.GET("/users/*id", func(c *gin.Context) {
		id := c.Param("id")
		c.String(200, "The user id is  %s", id)
	})
	r.Run(":8080")
}

现在我们运行,浏览器里访问http://localhost:8080/users/123,会看到如下信息:

The user id is  /123

是否发现区别了,我们获取到的id不是123了,而是/123,多了一个/

同样的你试试http://localhost:8080/users/123/go会发现显示的信息是:

The user id is  /123/go

是一个/开头的路径字符串。

这里要特别说明一点的是,如果你用浏览器访问http://localhost:8080/users,会被重定向到http://localhost:8080/users/,然后显示的信息如下:

The user id is  /

重定向的根本原因在于/users没有匹配的路由,但是有匹配/users/的路由,所以就会被重定向到/users/。现在我们注册一个/users来验证下这个猜测:

r.GET("/users", func(c *gin.Context) {
	c.String(200, "这是真正的/users")
})

现在再访问http://localhost:8080/users,会看到显示的信息变成了:

这是真正的/users

这也间接证明了/users/*id/users这两个路由是不冲突的,可以被Gin注册。

以上自动重定向的原理,得益于gin.RedirectTrailingSlash 等于true的配置。如果我们把它改为false就不会自动重定向了。

func main() {
	r := gin.Default()

	r.RedirectTrailingSlash = false
	r.GET("/users/*id", func(c *gin.Context) {
		id := c.Param("id")
		c.String(200, "The user id is  %s", id)
	})

	r.Run(":8080")
}

现在我们运行程序,访问http://localhost:8080/users发现显示的信息是404 page not found

小结

这一篇主要介绍路由参数,并且基于这种参数,我们可以很灵活的实现我们的API,并且从路径中获取相应的参数进行操作。对于*号参数,不建议使用,因为匹配的太多,会导致我们自己搞不清楚哪些路由被注册了。

除了路由参数,还有URL的query参数,也就是?a=b&c=d这样的格式,下一篇文章我们再介绍。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Golang Gin 实战(十二)| ProtoBuf 使用和源码分析原理实现

    ProtoBuf最近几年也算比较流行,它是一种语言无关,平台无关,并且可以扩展,并结构数据序列化的方法。相比JSON/XML这类文本格式的,ProtoBuf是二...

    飞雪无情
  • Golang Gin 实战(五)| 接收数组和 Map

    在 上一篇 Golang Gin 实战(四)| URL查询参数的获取和原理分析 文章中,因为文章篇幅问题,QueryArray和QueryMap没有介绍,这篇文...

    飞雪无情
  • Golang Gin 实战(一)| 快速安装入门

    Gin 是一个非常优秀的Golang Web Framework,它不光API友好,性能也非常高,并且设计简洁,便于入门。所以它(Gin)非常受欢迎,在Gith...

    飞雪无情
  • Golang Gin 实战(四)| URL查询参数的获取和原理分析

    在 上一篇 Golang Gin 实战(三)| 路由参数 文章中,主要介绍了路由通配符、路由参数,让我们有了一种可以从URL路径中获取参数的方式,同时又不是重复...

    飞雪无情
  • Go框架解析-Gin

    今天是我golang框架阅读系列第三篇文章,今天我们主要看看gin的框架执行流程。关于golang框架生命周期源码阅读下面是我的计划:

    用户1093396
  • Gin框架核心源码走读

    | 导语 最近考虑给SCF简单封一层web库,提供cgi的http协议处理、上下文、拦截器、html渲染等能力。很自然就想到了Gin框架,基于golang且框架...

    王昂
  • Golang Gin 实战(十)| XML渲染

    虽然当前基于XML的API应用不多,但是Gin也提供了便捷的XML生成,可以把这些用于需要XML的地方,比如网站的sitemap,rss订阅的atom等。

    飞雪无情
  • Golang Gin 实战(七)| 分组路由源代码分析

    以上等等,这些路由最前面的部分/admin/是相同的,如果我们一个个写也没问题,但是不免会觉得琐碎、重复,无用劳动,那么有没有一种更好的办法来解决呢?Gin为我...

    飞雪无情
  • Gin-Web-Framework官方指南中文(上篇)

    Gin是一个用Golang写的HTTP web框架。它具有类似于Martini的API,性能更高-快40倍。 如果需要很好的性能,那么肯定是推荐现在使用Gin。

    小诚信驿站

扫码关注云+社区

领取腾讯云代金券