golangjob.cn /d/41-go-router

你应该如何去选择Go router?

8-10 minutes

平时你是不是也纠结该用哪个router呢?土拨鼠带来一篇router比较的文章,希望大家在选择router的时候能提供一些参考意见,本文主要翻译自https://www.alexedwards.net/blog/which-go-router-should-i-use。另外作者也出书了。书名《Let’s Go》《Let’s Go Further》。主要介绍了如何去使用 Go 构建专业的生产级 web 应用程序和 api。感兴趣的同学可以看看。


当你开始使用 Go 构建 web 应用程序时,你可能会问的第一个问题就是“我应该使用哪个router?”.

这也不是一个容易回答的问题。可能有超过100种不同的router,它们都有不同的 api、特性和行为。因此,在这篇博客文章中,评估了30个受欢迎的案例,并评估出了一个最佳选项的名单列表,以及一个流程图,可以用来帮助指导你作出选择。

在我们开始之前,有几个关于术语的注意事项:

注意: 从软件工程的角度来看,路由冲突并不是件好事。它可能就是 bug 和混乱的来源,我们应该在应用程序中尽量避免它们。

入围的router

有四种不同的router进入了入围名单。它们是 http.ServeMux, julienschmidt/httprouter, go-chi/chigorilla/mux. 。这四个router都经过了充分的测试,文档也写得很友好,并且到现在还在积极地维护中。它们(大多数)有稳定的 api,并且与 http.Handler, http.HandlerFunc 兼容。标准库的中间件模式

在性能方面,所有四个router对于(几乎)每个应用程序来说都足够快,建议你可以根据需要的特定功能而不是性能来选择它们。我个人曾不同时间在生产应用程序中使用过这四个router,并且对它们感到非常满意。

http.ServeMux

我首先要说的是,如果你可以使用 http.ServeMux,就近可能应该使用它。

作为 Go 标准库的一部分,它经过了严格的实战测试并有详细的文档记录。使用它意味着不需要导入任何第三方依赖项,而且大多数其他 Go 开发人员也会熟悉它的工作原理。Go 1 兼容性承诺还意味着应该能够http.ServeMux长期依靠相同的方式工作。所有这些在应用程序维护方面都是很大的积极因素。

与其他大多数router不同,它还支持基于主机的路由,传入请求的 url 会自动清理,并且它匹配路由的方式也很聪明: 较长的路由模式总是优先于较短的路由。这是一个很好的副作用,您可以以任何顺序注册,并且它不会改变应用程序的行为。

两个主要限制http.ServeMux的是它不支持基于方法的路由URL 路径中的变量。但是缺乏对基于方法的路由的支持并不总是避免使用它的好理由——可以使用下面这样的代码解决:

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", index)

    err := http.ListenAndServe(":3000", mux)
    log.Fatal(err)
}

func index(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }

    // Common code for all requests can go here...

    switch r.Method {
    case http.MethodGet:
        // Handle the GET request...

    case http.MethodPost:
        // Handle the POST request...

    case http.MethodOptions:
        w.Header().Set("Allow", "GET, POST, OPTIONS")
        w.WriteHeader(http.StatusNoContent)

    default:
        w.Header().Set("Allow", "GET, POST, OPTIONS")
        http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
    }
}

在上面几行代码中就可以实现了基于方法的路由,以及定制的404和405响应和对 OPTIONS 请求的支持。

随着时间的推移,我逐渐意识到这http.ServeMux有很多优秀的地方,而且在很多情况下已经足够了。事实上,我唯一建议不要使用它的时候是需要支持 URL 路径中的变量或自定义路由规则。在这些情况下,尝试使用http.ServeMux可能会有点麻烦,我认为选择第三方router通常会更好。

julienschmidt/httprouter

我认为这julienschmidt/httprouter的行为和对 HTTP 规范的合规性方面,是任何第三方router最接近“完美”的。它支持基于方法的路由和动态 URL。它还自动处理OPTIONS请求并正确地发送405响应码,而且允许为404405响应设置自定义的handler。

它不支持基于主机的路由、自定义路由规则或 regexp 路由模式。需要注意的是,httprouter 也不允许有冲突的路由,比如/post/create/post/:id。这在客观上是一件好事,因为它有助于避免 bug,但如果您需要使用冲突的路由(例如与现有系统使用的路由保持一致) ,则可能会出现问题。

httprouter的一个缺点是,API和文档有点混乱。这个包是在Go 1.7中引入请求上下文之前就已发布,很多当前的API仍然存在,以支持这些旧版本的Go。现在,你可以使用常规的http.Handlerhttp.HandlerFunc签名来写你的handler,你所需要的是要注册router.Handler()router.HandlerFunc()方法。例如:

func main() {
    router := httprouter.New()

    router.HandlerFunc("GET", "/", indexGet)
    router.HandlerFunc("POST", "/", indexPost)

    err := http.ListenAndServe(":3000", mux)
    log.Fatal(err)
}

func indexGet(w http.ResponseWriter, r *http.Request) {
    // Handle the GET request...
}

func indexPost(w http.ResponseWriter, r *http.Request) {
    // Handle the POST request...
}

go-chi/chi

go-chi/chi支持基于方法的路由、 URL 路径中的变量和 regexp 路由模式。像 · 一样,它也允许你为404和405个响应设置自定义handler。

但我最喜欢的是,在chi中可以创建使用特定中间件的路由 "组",比如下面的代码片段。这对于有很多中间件和路由需要管理的大型应用来说非常有用。

r := chi.NewRouter()

// Middleware used on all routes
r.Use(exampleMiddlewareOne)
r.Use(exampleMiddlewareTwo)

r.Get("/one", exampleHandlerOne)

r.Group(func(r chi.Router) {
    // Middleware only used in this route group
    r.Use(exampleMiddlewareThree)

    r.Get("/two", exampleHandlerTwo)
})

值得注意的是,chi允许冲突的路由,路由是按照声明的顺序进行匹配的。

chi的两个缺点是它不能自动处理OPTIONS请求而且它不能在405响应中设置Allow header。如果你正在建立一个网络应用程序或私人API,那么这些东西可能不是一个大问题--但如果你正在建立一个公共API,这就是需要注意的事情了。和httprouter一样,它也不支持基于主机的路由.

值得注意的是,在过去的6年里,chi 已经有了5个主要的版本增量,其中大部分都包含了破坏性的变化。历史并不一定能预测未来,但确实表明,对于 chi 来说,向后兼容性和不进行性更改并不像这个短名单上的其他一些router那么重要。相比之下,httproutergorilla/mux 在这段时间里并没有做出任何突破性的改变。

值得注意的是,在过去的6年中,chi已经有5个主要的版本增量--其中大部分都包括重大变化。历史不一定是未来的预测,但确实表明,与这个入围名单上的其他一些路由器相比,向后兼容和不做破坏性的修改对chi来说不是那么重要。相比之下,httproutergorilla/mux在这段时间内没有做任何破坏性的改动。

gorilla/mux

gorilla/mux包可能是最著名的Go router,这是有原因的。它包括了各种功能,包括支持基于方法的路由、动态URL、regexp路由模式和基于主机的路由。重要的是,它是这个入围名单上唯一支持自定义路由规则和路由 "反转 "的router(就像你在Django、Rails或Laravel中看到的那样)。它还允许你为404和405响应设置自定义handler。

它的缺点基本上和 chi 一样ーー它不会像 httprouter 那样自动处理 OPTIONS 请求,也不会在405响应中包含 Allow header。同样,和 chi 一样,它也允许相互冲突的路由,会按声明的顺序进行匹配。

鉴于chigorilla/mux的缺点很相似,在两者之间你可以直接选择:如果你需要支持自定义路由规则、基于主机的路由或路由 "反转",选择gorilla/mux。如果你不需要这些 "高级 "功能,那么最好选择chi,因为它有很好的管理中间件的功能,特别是如果你正在构建一个大型应用。

荣誉提名 bmizerany/pat 和 matryer/way

我认为值得一提的另外两个router是bmizerany/patmatryer/way。我对这两个都情有独钟,因为它们都是故意简单化的。它们拥有很小的 api 和非常清晰易懂的代码,这使得我们可以很容易准确地掌握router在幕后是如何工作的。尤其是matryer/way背后的代码,非常值得一读。

虽然它们的功能不如入围名单中的其他router,但我认为它们的简单性使它们很适合用于教程(尤其是针对入门gopher的教程),如果你想建立自己的自定义router,可以把它们作为一个起点/灵感。

流程图

考虑到各种利弊和支持的功能,这个流程图应该可以帮助你在四个入围的router之间做出选择。

img

其他router

下面列出了评估的其他router,以及一个简短的说明,解释了为什么它们没有进入名单中。

注意: 使用这个问题“代码库是否包含 go.mod 文件?”作为一个代理来测量一个代码库当前是否在维护。这似乎是合理的——如果维护者仍然参与Go生态并关注代码,他们应该会在过去几年的某个时候使用modules来更新代码库。

| Repository | Notes |
| :----------------------------------------------------------- | :----------------------------------------------------------- |
| celrenheit/lion | 目前尚未维护 |
| claygod/Bxog | 目前尚未维护 |
| clevergo/clevergo | 使用自定义handler签名(不是 http.Handler 或 http.HandlerFunc)。 |
| dimfeld/httptreemux | 不完全支持 http.Handler。需要中间件来设置自定义 404/405 handler。 |
| donutloop/mux | 目前尚未维护 |
| gernest/alien | 目前尚未维护 |
| go-ozzo/ozzo-routing | 使用自定义handler签名(不是 http.Handler 或 http.HandlerFunc)。 |
| go-playground/lars | 目前尚未维护 |
| go-zoo/bone | 很好,但与 chi 有类似的用例(提供的更多)。但是测试不够完整的。 |
| go101/tinyrouter | 详细的路由说明。不会自动发送 405 响应。 |
| gocraft/web | 目前尚未维护 |
| goji/goji | 稍微有点不寻常但具备灵活的 API,支持自定义匹配程序。需要中间件来设置自定义 404/405 handler。也很好,但我认为 gorilla/mux 提供了类似的功能并且更易于使用。 |
| goroute/route | 使用自定义handler签名(不是 http.Handler 或 http.HandlerFunc)。 |
| gowww/router | 很好,但是有类似 chi 的用例(提供更多)。没有办法设置自定义405handler。 |
| GuilhermeCaruso/bellt | 无法设置自定义404或405 handlers. |
| husobee/vestigo | 目前尚未维护 只支持http.HandlerFunc. |
| naoina/denco | 目前尚未维护 |
| nbari/violetear | 很好,但是和 chi 有类似的用例(它提供更多)。wrap http.ResponseWriter 用自己的定制类型,这在某些情况下可能会出现问题。 |
| nbio/hitch | 缺乏文档 |
| nissy/bon | 目前尚未维护 |
| razonyang/fastrouter | 目前尚未维护 |
| rs/xmux | 目前尚未维护 使用自定义handler签名(不是 http.Handler 或 http.HandlerFunc)。 |
| takama/router | 目前尚未维护 |
| vardius/gorouter | 很好,但是和 chi 有类似的用例(它提供更多)。5年的4个主要版本表明这个 API 可能并不是很可靠。 |
| VividCortex/siesta | 很好,但是有类似 chi 的用例(提供更多)。没有办法设置自定义405handler。 |
| xujiajun/gorouter | 目前尚未维护 |

::...
免责声明:
当前网页内容, 由 大妈 ZoomQuiet 使用工具: ScrapBook :: Firefox Extension 人工从互联网中收集并分享;
内容版权归原作者所有;
本人对内容的有效性/合法性不承担任何强制性责任.
若有不妥, 欢迎评注提醒:

或是邮件反馈可也:
askdama[AT]googlegroups.com


订阅 substack 体验古早写作:


点击注册~> 获得 100$ 体验券: DigitalOcean Referral Badge

关注公众号, 持续获得相关各种嗯哼:
zoomquiet


自怼圈/年度番新

DU22.4
关于 ~ DebugUself with DAMA ;-)
粤ICP备18025058号-1
公安备案号: 44049002000656 ...::