gin 路由设置出现冲突

关于go框架gin的静态托管和api同时使用报错的问题

地址:https://segmentfault.com/q/1010000020593317/a-1020000020596003

标签:Go

详情描述

代码截图和注释,使用了静态/就不能用接口了,我百度了很久找不到原因。

package main

import "github.com/gin-gonic/gin"

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

    // 单独使用下面的静态托管能在http://localhost:2019/看到正确的html
    router.Static("/", "./www")
    
    // 但是下面的接口就不能使用了,必须注释掉上面一句,下面接口才能使用
    router.GET("/hello", func(c *gin.Context) {
        c.String(200, `hello golang.`)
    })
    router.Run(":2019")
}

报错如下:

[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /hello                    --> main.main.func1 (3 handlers)
[GIN-debug] GET    /*filepath                --> github.com/gin-gonic/gin.(*RouterGroup).createStaticHandler.func1 (3 handlers)
panic: wildcard route '*filepath' conflicts with existing children in path '/*filepath'

goroutine 1 [running]:
github.com/gin-gonic/gin.(*node).insertChild(0xc00009ac60, 0xc0001dfc01, 0xc0001b6a91, 0x9, 0xc0001b6a90, 0xa, 0xc0000d7d20, 0x3, 0x3)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/tree.go:280 +0x72e
github.com/gin-gonic/gin.(*node).addRoute(0xc00009ac60, 0xc0001b6a90, 0xa, 0xc0000d7d20, 0x3, 0x3)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/tree.go:237 +0x218
github.com/gin-gonic/gin.(*Engine).addRoute(0xc00020e000, 0x16ddc7a, 0x3, 0xc0001b6a90, 0xa, 0xc0000d7d20, 0x3, 0x3)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/gin.go:257 +0x12a
github.com/gin-gonic/gin.(*RouterGroup).handle(0xc00020e000, 0x16ddc7a, 0x3, 0xc0001b6a60, 0xa, 0xc0000ce550, 0x1, 0x1, 0x3, 0x3)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/routergroup.go:75 +0x1c5
github.com/gin-gonic/gin.(*RouterGroup).GET(...)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/routergroup.go:103
github.com/gin-gonic/gin.(*RouterGroup).StaticFS(0xc00020e000, 0x16dd8e5, 0x1, 0x17d0600, 0xc0001c6a70, 0x6, 0xc0000c2300)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/routergroup.go:180 +0x1e0
github.com/gin-gonic/gin.(*RouterGroup).Static(0xc00020e000, 0x16dd8e5, 0x1, 0x16de886, 0x5, 0xc0000ca030, 0x1)
	/Users/polo/.gvm/pkgsets/go1.12/global/pkg/mod/github.com/gin-gonic/gin@v1.4.0/routergroup.go:167 +0xa8
main.main()
	/Users/polo/gomodules/test/main.go:15 +0xe5
exit status 2

我的回答

你可以理解为,这是 gin 中的限制,gin 中每个路由的规则是不能有交集的,比如这里的 //web 是有交集的,即 /web 也满足是 / 的情况。可以看看一个 github issue 中的关于问题的这个描述。

那这个问题该怎么解决呢?

我想到的是,静态页面 / 修改为 /static。如果是某些特殊的效果,可以在 nginx 反向代理之上做一层转化,将所有 / 指向 /static,nginx 的 location 规则还是比较丰富的。

说实话,我也不知道 gin 为什么这么做?或许是为了降低复杂度,降低出错的可能吧。

通常,我们在用的其他 web 框架时,都是会根据 router 设置优先级的顺序决定启动那个路由,自动进行前后的覆盖。