在 Go Go POS 中使用六边形架构构建 RESTful API

2025-05-25

使用 Go 中的六边形架构构建 RESTful API

前往 POS

一段时间以来,我一直在学习如何使用不同的框架和语言构建 Web 应用程序,例如采用 MVC 架构的Laravel和遵循“Hapi.js 方式”的Node.js。当我尝试使用 Go 创建一个新的作品集项目时,我发现自己开始思考理想的项目结构。我想要一个不仅符合标准 Go 项目布局 的架构,还要使代码易于编写和理解的结构。就在那时,我偶然发现了六边形架构的概念,正如Netflix 的工程博客中所展示的那样。以最少的代码更改无缝切换基础架构的想法让我着迷,于是我决定在我的新项目中实现它。

现在,剩下的问题是:“我应该构建什么?”幸运的是,当我随意浏览 YouTube 视频时,我偶然发现了Asdita Prasetya制作的这个隐藏的精品视频,名为“Ide Project untuk Upgrade Portfolio Backend Engineer”。他建议开发一个 RESTful 的销售点 API 服务。我觉得这是一个将我新学到的架构知识付诸实践的完美项目。于是,我准备好咖啡和键盘,开始了这段激动人心的学习之旅!

六边形架构

创建无需 UI 或数据库即可运行的应用程序,以便您可以针对应用程序运行自动回归测试,在数据库不可用时继续工作,并且无需任何用户参与即可将应用程序链接在一起。

六边形架构(也称为端口和适配器架构)是构建解耦软件系统的几种方法之一。它由Alistair Cockburn推广,他被誉为软件开发敏捷运动的创始人之一。这种组织软件的方式非常适合开发易于操作且易于修改的应用程序。

六边形架构的核心思想是将应用程序的核心业务逻辑与外部内容(例如数据库、用户界面和其他外部服务)分离。它提倡一种简洁、模块化的结构,使应用程序的测试、维护和扩展更加容易。

六边形架构

核心是应用程序的核心所在。它包含应用程序的基本业务逻辑和规则。它负责处理订单、管理用户账户以及执行应用程序的所有任务。核心应该独立于任何外部技术或框架,从而实现高度的可移植性和可重用性。

六边形架构中还有另外两个重要概念:“端口”和“适配器”。这两个概念规定了“核心”如何与外部组件交互。

端口

将端口视为契约或接口。它们定义了应用程序如何与外部系统或服务通信。例如,端口可以指定连接数据库、与其他 Web 服务交互或处理用户界面的规则。端口属于核心,因为核心定义了实现业务逻辑目标所需的操作。

适配器

适配器负责实现端口定义的契约或接口。适配器负责确保应用程序能够与数据库、Web 服务或其他对象进行交互。它们处理技术细节。

驾驶员演员

驱动 Actor 是与核心通信的发起者。它们会联系核心来请求特定的服务。驱动 Actor 的例子可以是 HTTP 请求或命令行界面 (CLI)。

驱动 Actor

驱动 Actor 是由核心触发的 Actor。如果核心需要外部服务,它会向适配器发送请求,指示其执行特定操作。例如,如果核心需要将数据存储到 Postgres 数据库中,它会触发与 Postgres 客户端的通信以执行 INSERT 查询。在这种情况下,核心会发起通信。

执行

要求

Asdita 非常贴心地提供了数据库架构设计Postman API 文档。所以我只需按照六边形架构原则构建我的应用程序,然后开始编写代码即可。

技术栈

为了构建 RESTful 销售点服务 API,我考虑并选择了多种能够无缝协作的技术组合。对于处理 HTTP 请求和响应,使用Gin HTTP Web 框架是合理的,因为我认为它在 Go 社区中功能完善且广受欢迎。为了确保数据完整性和持久性,我使用PostgreSQL数据库,并以pgx作为数据库驱动程序。之所以选择 PostgreSQL,是因为它是生产环境中最流行的关系数据库,并且能够高效地与 Go 集成。我还使用go-redis客户端库中的Redis实现了缓存功能,该库提供了强大的内存数据存储功能。

数据库架构

Go-POS 模式

  • users:存储用户信息,包括姓名、电子邮件、密码、角色(管理员或收银员)以及创建和更新的时间戳。
  • payments:存储各种付款方式。它跟踪付款类型、名称、标识以及创建和更新的时间戳。
  • categories:存储产品类别,跟踪类别名称以及创建和更新的时间戳。
  • products:存储基本产品数据,包括类别 ID、SKU、名称、库存水平、价格、图像以及创建和更新的时间戳。
  • orders:存储订单详细信息,例如用户 ID、付款 ID、客户姓名、总价、付款、退货、收据代码以及创建和更新的时间戳。
  • order_products:存储每笔订单中包含的产品记录。它记录订单和产品 ID、数量、总价以及创建和更新的时间戳。

应用程序架构

Go-POS六边形架构

该应用程序遵循六边形架构,以六边形表示。core其中心domain包含service业务逻辑。

核心左侧有一个driver port,是驱动适配器的入口,右侧有2个driven ports,是核心与驱动适配器交互的门。

围绕核心,adapters连接核心与外部世界。左侧HTTP adapter负责处理传入的 HTTP 请求。右侧有两个适配器:DB adapter一个连接到 PostgreSQL,另一个Cache adapter与 Redis 配合使用。

位于应用程序外部。左侧的 Nginx 充当 HTTP 服务器,driver actors右侧的 PostgreSQL 和 Redis 代表响应核心请求。driven actorsdriver actordriven actors

项目结构



.
├── bin
├── cmd
│   └── http
├── docs
└── internal
    ├── adapter
    │   ├── cache
    │   │   └── redis
    │   ├── handler
    │   │   └── http
    │   ├── repository
    │   │   └── postgres
    │   │       └── migrations
    │   └── token
    │       └── paseto
    └── core
        ├── domain
        ├── port
        ├── service
        └── util

21 directories



Enter fullscreen mode Exit fullscreen mode
  • bin:用于存储已编译的可执行二进制文件的目录。
  • docs:用于存储项目文档的目录,例如 swagger 静态文件。
  • cmd:应用程序主入口点或命令的目录。http子目录包含主 HTTP 服务器入口点。
  • internal:包含不应暴露给外部包的应用程序代码的目录。
  • core:包含应用程序的核心业务逻辑的目录。其中包含 4 个子目录。
    • domain:包含代表核心业务概念的域模型/实体的目录。
    • port:包含适配器必须遵循的已定义接口或契约的目录。
    • service:包含应用程序的业务逻辑或服务的目录。
    • util:包含在包中重复使用的实用函数的目录service
  • adapters:用于包含与应用程序核心交互的外部服务的目录。本应用程序使用了 4 个外部服务。
    • handler/http:包含 HTTP 请求和响应处理程序的目录。
    • repository/postgres:包含 PostgreSQL 数据库适配器的目录。
    • cache/redis:包含 Redis 缓存适配器的目录。
    • token/paseto:包含使用 Paseto 的令牌生成和验证适配器的目录。

开发工具

我在开发过程中使用过一些工具来简化流程。这些工具以不同的方式提供帮助。

Podman

Podman是一个类似于Docker的容器化工具,用于管理应用程序的容器。它简化了容器的构建、运行和维护等任务。它是创建隔离的开发环境(例如 PostgreSQL 和 Redis 实例)的理想选择。

DBDocs

DBDocs是一个数据库文档生成器。它自动生成数据库模式的文档,帮助理解和管理数据库结构,尤其是在使用 PostgreSQL 等关系数据库时。

任务文件

Taskfile是一款用于简化重复性开发任务的工具。它有助于自动化构建、测试和部署应用程序等活动。与Makefile不同,Taskfile 使用 YAML 进行配置,使其更具可读性和用户友好性。

Golang-migrate

Golang-migrate是一款专为 Go 应用程序设计的数据库迁移工具。它可以帮助管理和应用随着应用程序的增长而对数据库模式进行的更改,确保代码和数据库结构保持同步。

空气

Air是一款 Go 应用的自动重启工具,它可以监测代码变化并自动重启应用,从而提高开发效率。

斯瓦戈

Swaggo是一款为 Go API 创建 Swagger 文档的工具。它使 API 端点的文档编写更加简单,从而帮助开发人员理解和使用 API。

Golangci-lint

Golangci-lint是一款用于检查 Go 代码质量、查找问题、错误和代码风格问题的工具。它有助于保持代码整洁且易于维护。

Github Actions

GitHub Actions是一个与 GitHub 存储库链接的平台,用于自动执行构建、测试和部署应用程序等任务。它简化了开发并确保了代码质量。

部署

我创建了一个 GitHub Action 工作流来自动化应用程序的容器化过程,并将其上传到GitHub 容器注册表。然后,我手动将其部署到我的个人 VPS 上,并使用Nginx作为反向代理。我可能会考虑再写一篇博客文章来解释我的 VPS 设置。

您可以通过以下 URL 浏览该应用程序的 Swagger 文档:https://gopos.bagashiz.me/docs/index.html

Go-POS Swagger 实时文档

源代码

我不想让这篇文章太长。所以如果你感兴趣,请在我的GitHub 仓库中查看该项目的完整源代码。你可以访问和探索代码库,查看应用程序的结构,甚至为其开发做出贡献。

GitHub 徽标 bagashiz / go-pos

用 Go 编写的简单 RESTful 销售点 (POS) 服务 API,使用了 Gin Web 框架、PostgreSQL 数据库和 Redis 缓存。本文提供了用 Go 实现六边形架构的概念验证。

前往 POS

描述

一个用 Go 编程语言编写的简单 RESTful 销售点 (POS) Web 服务。这个项目是我学习Go六边形架构过程的一部分。

它使用Gin作为 HTTP 框架,PostgreSQL作为数据库,pgx作为驱动程序,Squirrel作为查询构建器。它还使用Redis作为缓存层,go-redis作为客户端。

该项目构想的灵感来自Asdita Prasetya在 YouTube 上发布的“Ide Project untuk Upgrade Portfolio Backend Engineer”视频,该视频为其开发提供了宝贵的指导和启发。

入门

  1. 如果您不使用 devcontainer,请确保您的机器上安装了Go 1.23 或更高版本和Task :

    go version && task --version
    Enter fullscreen mode Exit fullscreen mode
  2. 创建该文件的副本.env.example并将其重命名为.env

    cp .env.example .env
    Enter fullscreen mode Exit fullscreen mode

    根据需要更新配置值。

  3. 安装所有依赖项,运行docker…





改进

我承认这个项目还有一些地方有待改进:

  • 截至目前,单元测试尚未实施。
  • 该项目目前使用slog标准库中的包进行日志记录。但切换到更高级的记录器(例如),zap可以提供更多灵活性和功能。
  • 与其直接使用来访问环境变量os.Getenv(),不如集成一个配置处理程序,这样viper可能会使其更易于维护。

参考

文章来源:https://dev.to/bagashiz/building-restful-api-with-hexagonal-architecture-in-go-1mij
PREV
10 个开发工具,助您改善开发人员的日常生活
NEXT
5 个很棒的 HTML 和 CSS 项目(附 Codepen 预览)