行业动态

我是如何在 Go 中组织包的

构建项目跟写代码相同具有挑战性。而且有许多种办法。运用过错的办法或许会让人很苦楚,但若要重构则又会十分耗时。别的,要想在一开端就规划出完美的程序几乎是不或许的。更重要的是,有些处理办法只适用于某特定巨细的程序,可是程序的巨细又是跟着时刻改变和增加的。所以咱们的软件应该跟着呈现过处理过的问题一同生长。 我首要从事微服务的开发,这种架构十分合适我。其他范畴或其他根底架构的项目或许需求不同的办法。请在下面的谈论中告诉我您的规划和最有含义的当地。 ## 包及其依靠 在开发微服务时,按组件拆分服务很有用。每个组件都应该是独立的,理论上,假如需求,能够将其提取到外部服务。怎么了解和完成呢? 假定咱们有一个服务,它处理与订单相关的一切作业,比方发送电子邮件的承认、将信息保存到数据库、连接到付出供给商等。每个包都应该有一个称号,该称号清楚地说明晰它的用处,而且恪守命名规范。 ![] 这仅仅咱们有 3 个包的项目的一个比如:**confemails**,**payproviders**和**warehouse**。包名应尽量简略并能让人一望而知。 每个包都有自己的 Setup函数。该函数只接纳能让该包运转的最基本的参数。例如,假如包对外供给 HTTP 服务,那么 Setup 函数则仅需求承受一个相似 mux route 的 HTTP route。当包需求拜访数据库时,Setup 函数也是只承受 sql.DB 参数就能够了。当然,这个包也或许需求依靠另一个包。 ## 包内的组成 知道了模块的外部依靠,下一步咱们就能够专心于如安在模块内安排代码。在最开端,这个包包括以下文件: setup.go - 其间包括 Setup函数, service.go - 它是逻辑文件, repository.go - 它是在读取/保存数据到数据的的文件。 Setup函数担任构建模块的每个构建块,即服务、存储库、注册事情处理程序或 HTTP 处理程序等等。这是运用这种办法的实践出产代码的一个比如。 ```go func Setup { h := httpHandler{ logger: logger, requestClaims: jwtutil.NewHTTPRequestClaims, service: service{client: httpClient}, auth.CreateRoute 以上代码中,它构建了 JWT 中间件,这是一个处理一切事务逻辑并注册 HTTP 处理程序的服务。正因为如此,模块是十分独立的,而且能够转移到独自的微服务中,而不需求做太多作业。最终,一切的包都在 main 函数中装备。 有时,咱们需求一些处理程序或数据库驱动。例如,一些信息能够被存储在数据库中,然后经过事情发送到渠道的不同部分。运用像 saveToDb这样的办法将数据只保存在同一个库中是很不便利的。一切相似的元素都应该由以下功用切割:repository_order.go 或 service_user.go。假如目标的类型超越 3 种,则将其移动到独自的子文件夹中。 ![] ## 测验 提到测验,我坚持一些准则。首要,在 Setup函数中运用接口。这些接口应该尽或许小。在上面的比如中,有一个 httpGetter 接口。接口中只要**Get**函数。 ```go type httpGetter interface { Get 谢天谢地,我只需求模仿一个办法。接口的界说需求尽或许地挨近它的用处。 其次,测验编写更少的测验用例的一起能够掩盖到更多的代码。关于每个主函数的决议计划/操作,一个成功的测验用例和一个失利的测验用例应该满足掩盖大约 80% 的代码。有时,程序中有一些要害部分,这部分能够被独自的测验用例掩盖。 最终,在以 `_test` 为后缀的独自包中编写测验,并将其放入模块中。把一切的东西都放在一个当地是很有用的。 当您想要测验整个应用程序时,请在主函数周围的**setup**函数中准备好每个依靠项。它将为出产环境和测验环境供给相同的设置,能够为您防止一些 bug。测验应该重用 setup函数,而且只模仿那些不易模仿的依靠项。 ## 总结 一切其他文件都保存在项目根目录中。这让我对整个项目有了一个明晰的知道。让我知道在哪里能够找到主文件,在哪里能够找到与根底结构相关的文件,而且没有混合在一同。不然,项目的主文件夹就会变得一团糟。 正如我在介绍中所说,我知道并非一切项目都能从中获益,可是像 microservices 这样的小型程序会发现它十分有用。