大家好,我是程序员幽鬼。

用 Go 编写 API 服务,许多语言新手问的第一件事是:“我应该使用哪个框架?”。

那些来自 Ruby 或 Python 等语言的人可能熟悉大多数开发人员(例如 Rails、Django 或 Flask)使用的单一 Web 框架。Go 有点不同,因为实际上没有一个框架是社区中最受欢迎的。虽然有几个可用的框架,其中许多框架我将在这篇文章中讨论,但 Go 社区似乎并没有就构建 API 服务时的“首选”框架(如果有的话)达成一致。

虽然我不会在这篇文章中比较或推荐任何特定的框架,但我将尝试通过介绍为 Go 中的下一个 API 项目选择框架时应该考虑的四个关键事项给你参考。

01 你真的需要框架吗

在尝试确定在 Go 中构建 API 后端服务时应该使用哪个框架时,你应该问自己的第一件事是,你是否需要一个框架?

Go 标准库非常棒,它提供了许多开箱即用的世界级 API 所需的组件!我在 Go 中架构和构建了一项服务,该服务仅使用 Go 标准库 + router/mux 即可每天处理数百万个请求。

两个最流行的 routers 是:

  • gorilla/mux[1]
  • chi[2]

这两个库都提供基于 URL 主机、路径、headers、HTTP 方法和查询值等内容的快速请求路由,同时允许你定义自己的“自定义”匹配器。

这些 routers 比内置的 http.ServeMux[3] 提供更好的体验,因为它们允许将你的请求路由到不同的处理程序,而无需复杂的if 或 switch语句块,例如:

  1. func (b *bookServer) bookHandler(w http.ResponseWriter, req *http.Request) { 
  2.  // how you'd have to implement method based routing if using only the stdlib 
  3.  if req.URL.Path == "/books/" { 
  4.    if req.Method == http.MethodPost { 
  5.      b.createBook(w, req) 
  6.    } else if req.Method == http.MethodGet { 
  7.      b.getAllBooks(w, req) 
  8.    } else if req.Method == http.MethodDelete { 
  9.      b.deleteAllBooks(w, req) 
  10.    } else { 
  11.      http.Error(w, fmt.Sprintf("expect method GET, DELETE or POST at /books/, got %v", req.Method), http.StatusMethodNotAllowed) 
  12.      return 
  13.    } 
  14.  } 

Eli Bendersky 有一个很棒的系列[4],在 Go 中构建 REST API,首先从标准库开始,然后引入路由器(例如 gorilla[5] 或 chi[6]),最后切换到使用完整的 Web 框架。本系列展示了完全坚持使用标准库的一些缺点,以及额外的库(例如上面的两个路由器包)如何非常有用。

虽然这两个 routers 都带有中间件,用于处理基本身份验证、CORS 协商、请求日志记录等内容,同时还允许你轻松集成自己的路由器,但它们仍然不是框架。

如果你的 API 足够简单,或者特别是如果你或你的团队刚刚开始使用 Go,我建议从仅使用标准库 + 路由器/多路复用器开始,在使用完整框架之前,看看能使用多久。这种方法将使你能够学习基础知识,而不会被更复杂框架的细微差别所困扰。

02 你自己的选择

如果你决定仍希望为新服务使用 Web 框架,有几个较流行的选择,包括:

  • echo[7]
  • gin[8]
  • buffalo[9]

这些项目可以被描述为完整的 Web 框架,因为它们处理的不仅仅是路由和中间件。它们为服务的其他方面提供内置和预配置的功能,例如:

  • 日志记录
  • 模板
  • 国际化
  • 数据验证
  • asset 服务
  • 数据库访问和 ORM
  • 等等

如果你只想开始编写应用程序的业务逻辑而不担心其中的一些实现细节,这将非常有用,但它确实有代价:你极大可能被框架的选择所困扰。不喜欢 echo[10] 格式化日志的方式?想要使用与 buffalo[11] 选择的路由器不同的路由器?

我并不是说在使用这些框架时交换依赖项是不可能的,但是这可能会很困难,因为框架的全部意义几乎就是为你做出这些选择。如果你或你的团队对框架选择的依赖项感到满意,那么它可能非常适合你的场景,事实上,它可以提高生产力。但是,如果你是喜欢选择依赖项并不时调整或更换它们的个人或团队类型,你可能很快就会发现框架不是你的最佳选择。也就是说,你喜欢 DIY~

03 项目脉冲(Pulse)视图

GitHub 上项目的未解决 issue 数量以及项目维护人员对这些 issue 和 PR 的响应程度也是需要牢记的重要“软”指标。虽然有大量未解决的 issue 并不一定意味着项目不好,但这可能意味着某些功能或内部工作不清楚并且没有尽可能地记录。

**注意:**情况并非总是如此,因为这也可能意味着该项目正在获得动力,人们对贡献新功能感到兴奋。打开 issue 和 PR 以了解项目发生的情况。

但是,如果项目维护者似乎与社区没有建立良好的关系,或者他们不经常对问题或讨论做出回应,这可能意味着你可能会发现自己正在等待答案或错误修复被合并你选择那个特定的框架。GitHub 有点被忽视的 pulse 视图[12]可以帮助显示项目的活跃程度以及 issue 打开和关闭的频率。

大多数流行的框架也会有一个专用的 Gitter、Discord 或 Slack,因此也可能值得一试,看看社区对新手有多大帮助。

04 未来

最后,将你选择的框架的流行度与其他框架进行比较可能是值得的,因为流行度下降可能意味着随着社区转向另一个解决方案,该项目可能会被放弃或停滞不前。虽然 GitHub 上的星星数量是项目受欢迎程度的一个不错的指标,但这并不能告诉你趋势如何像谷歌趋势搜索那样变化。这是一个谷歌趋势搜索的例子,比较了过去一年美国对 golang echo 和 golang buffalo[13] 的兴趣。

Golang Echo vs Golang Buffalo search trends

在 r/golang[14] 上搜索你选择的框架也可能会给你与社区中其他人对项目的有用性和潜在未来的一些不同意见。

虽然这不是完全证明,也没有人知道未来,但是如果框架开始消亡或仍然强大,这种策略以及如上所述观察项目的脉冲应该会给你一个相对好的想法。如果你代表你的团队为工作项目选择框架,这一点尤其重要,因为我们中的许多人都处于不幸的境地,不得不维护构建在不再收到任何错误修正或安全性的框架之上的应用程序更新。

还值得查看框架的文档,看看它是否是最新的,以及是否有任何最近发布的使用相同框架和主要版本的教程。如果没有人在网上写它,这可能表明它不像以前那样好。

这是选择标准库而不是第三方框架的优势所在,因为标准库永远不会消失,也不会发生太大变化。

关于性能

总结一下,我认为框架作者过度[15] 推崇的[16]一个“功能”是性能。虽然性能很重要,但我不认为选择一个 web 框架主要是因为它是“性能”最好的,尤其是在 Go 中。Go 已经非常快了,你的框架代码很可能不会成为应用程序的瓶颈。在你需要开始分析和优化你的框架之前,数据库、网络或仅仅是自己的应用程序代码通常会成为你的服务性能问题的根源。

虽然知道你选择的框架比另一个框架更快,这可能会让人感觉很好,但快 10ms,你的用户可能永远不会注意。

结论

简而言之,选择适合你或你团队的框架(或不选择),因为没有适合所有人的“正确”答案。如果你决定确实要使用一个框架,我建议你至少选择两个并在两者中实现相同的简单 CRUD API,以查看你更喜欢哪个。

你同意还是不同意这篇文章中的观点?你和你的团队尝试过哪些框架?你最喜欢哪一个,为什么?

原文链接:https://dev.to/markphelps/4-things-to-consider-when-choosing-a-go-api-framework-4bei

参考资料

[1]gorilla/mux: https://github.com/gorilla/mux

[2]chi: https://github.com/go-chi/chi

[3]http.ServeMux: https://pkg.go.dev/net/http#ServeMux

[4]很棒的系列: https://eli.thegreenplace.net/2021/rest-servers-in-go-part-1-standard-library/

[5]gorilla: https://github.com/gorilla/mux

[6]chi: https://github.com/go-chi/chi

[7]echo: https://github.com/labstack/echo

[8]gin: https://github.com/gin-gonic

[9]buffalo: https://github.com/gobuffalo/buffalo

[10]echo: https://github.com/labstack/echo

[11]buffalo: https://github.com/gobuffalo/buffalo

[12]pulse 视图: https://github.com/gin-gonic/gin/pulse/monthly

[13]golang echo 和 golang buffalo: https://trends.google.com/trends/explore?geo=US&q=golang%20echo,golang%20buffalo

[14]r/golang: https://www.reddit.com/r/golang

[15]过度: https://github.com/gin-gonic/gin#benchmarks

[16]推崇的: https://github.com/labstack/echo#benchmarks