如何在现实世界的Go项目中分离路由、处理程序、第三方接口和业务逻辑



在阅读了关于如何构建项目的官方指南并经历了各种(1,2,3,仅举几例)示例和项目后,我不禁想知道我构建REST-API服务器应用程序的方法是否结构合理

API是用来做什么的?

POST /auth/sign-in

接收usernamepassword并发出JWT (JSON Web Token)。

GET /auth/sign-out

将JWT加入黑名单,使授权会话无效。

GET /resources

检索所有资源的列表。

POST /resources(需要有效的JWT认证)

接受JSON主体,创建一个新资源,并向每个人发送关于新资源的电子邮件和通知。

我的项目是什么样子的

目前我没有创建任何库。所有东西都在主包中,包括服务器设置和路由等,都在main.go中完成。我没有选择Rails或Django的MVC模式,以避免过于复杂的事情。此外,我的印象是,它并不真正符合上面已经提到的指南中所描述的命令和库的推荐结构。

auth.go # generates, validates JWT, etc
auth-handler.go # Handles sign-in/out requests; includes middleware for required authentication
mailer.go # Provides methods to send out transactional email, loads correct template etc.
main.go # set up routes, runs server; inits mailer and notification instance for the request context
models.go # struct definition for User, Resource
notifications.go # Provides methods to publish push notifications
resource-handler.go # Handles request for resources, uses mailer and notifications instances for the POST request

应该是什么样子?

路由应该分开吗?中间件呢?您如何处理与第三方代码的接口——想象一下,在概述的示例应用程序中,mailer.go与Mandrill对话,notifications.go与亚马逊AWS SNS对话?

我可以分享一点我自己的经验。

  1. 应用程序代码:

    • 与库代码相反,将包和子包分开是不太重要的——只要你的代码不太复杂就行。我主要将应用设计为集成自包含库,所以应用代码本身通常相当小。一般来说,如果你真的不需要它,尽量避免包分离。但是不要把大量的代码放在一个包里——这也是不好的。

    • 但是没有像"util"这样的通用包装,他们很快就会开始堆积行李并吮吸。对于跨项目可重用的通用实用程序,我有一个单独的仓库,在它下面,每个实用程序API都是一个子包。例:github.com/me/myutils/countrycodes, github.com/me/myutils/set, github.com/me/myutils/whatevs

  2. 无论包结构如何,最重要的是将内部api与处理程序代码分开。处理程序代码应该是一个非常薄的层,用于处理输入,并调用内部的自包含API,可以在没有处理程序或绑定到其他处理程序的情况下进行测试。看来你要这么做了。然后你可以将你的内部API分离到另一个包中,这并不重要。

  3. 当你决定哪些部分的代码应该被分离到库中时,从代码重用的角度考虑。

  4. 我喜欢将与第三方api的集成封装在二级包中定义的接口中。例如,如果您有使用AWS SES发送电子邮件之类的东西,我会创建一个名为github.com/my_org/mailer的包,带有一个抽象接口,并在其下面创建一个实现SES集成的github.com/my_org/mailer/ses包。应用程序代码导入mailer包及其接口,只有在main中,我才以某种方式注入SES的使用并将它们集成在一起。

  5. re middleware -我通常将它与API本身放在同一个包中。

相关内容

最新更新