找回密码
 立即注册
首页 业界区 业界 一款Go语言Gin框架DDD脚手架,适合快速搭建项目 ...

一款Go语言Gin框架DDD脚手架,适合快速搭建项目

姚梨素 7 天前
一款Go语言Gin框架DDD脚手架,适合快速搭建项目

一个开箱即用的 DDD(领域驱动设计)Go 脚手架,基于 Gin + RocketMQ,包含双数据库、统一响应、中间件与事件驱动示例。
这是什么

Gin-Framework-DDD 是一个面向 Go 语言的 DDD 工程脚手架,帮你快速搭建符合 DDD 分层规范的 Web 服务。项目内置用户与订单示例、领域事件与 RocketMQ 生产/消费、邮件通知示例、统一响应与中间件,适合作为团队工程模板或教学示例。
为什么要用DDD?

很多人认为 Go 语言没必要用 DDD,毕竟它和 Python、JS 一样轻巧灵活,用 MVC 就足够了。确实,大多数场景下 MVC 完全够用。工程化无非是把接口处理、业务逻辑、数据处理区分开,让各部分各司其职,方便维护和扩展。DDD 相对更适合中大型项目:如果项目有几十个模块、上百个接口,用 DDD 设计会更合适;模块少、接口不多的话,简单分层就够了。
总之,是否采用 DDD 和语言无关,只跟业务规模有关。一个东西变复杂了,就需要用一些机制去规范它,才能更好掌控。
源码地址:https://github.com/microwind/design-patterns/tree/main/practice-projects/gin-ddd
项目目录:gin-ddd/
核心特点


  • 严格 DDD 四层架构:领域层、应用层、基础设施层、接口层
  • Gin Web 框架:高性能 HTTP 服务
  • 事件驱动:领域事件 + RocketMQ 生产者/消费者
  • 双数据库支持:用户库 + 订单库可独立配置(默认 MySQL + PostgreSQL)
  • 统一响应格式:Response 封装,错误码集中管理
  • 全局中间件:日志、恢复、跨域
  • 可选邮件通知:订单创建事件驱动 SMTP 邮件发送
技术栈

技术版本说明Go1.21+语言版本Gin1.9+HTTP 框架RocketMQ5.3+事件消息队列MySQL8.0+用户库默认PostgreSQL14+订单库默认YAML-配置文件格式工程结构

工程结构图

flowchart TB    subgraph 接口层        Handler[HTTP Handler / 路由]    end    subgraph 应用层        AppService[应用服务]    end    subgraph 领域层        DomainService[领域服务]        Model[聚合根/实体]        RepoInterface[仓储接口]        NotificationInterface[通知接口]    end    subgraph 基础设施层        RepoImpl[仓储实现]        Mail[邮件服务]        MQ[消息队列]        DB[(数据库)]    end    Handler --> AppService    AppService --> DomainService    AppService --> RepoInterface    DomainService --> Model    DomainService --> NotificationInterface    RepoInterface -.实现.-> RepoImpl    NotificationInterface -.实现.-> Mail    RepoImpl --> DB    AppService -.发布事件.-> MQ工程结构列表
  1. gin-ddd/
  2. ├── cmd/server/main.go                            # 启动入口,装配各层并启动 HTTP + MQ
  3. ├── config/config.yaml                            # 应用配置
  4. ├── docs/init.sql                                 # MySQL 初始化脚本(示例)
  5. ├── internal/
  6. │   ├── domain/                                   # 领域层
  7. │   │   ├── model/
  8. │   │   │   ├── order/order.go                    # 订单聚合根
  9. │   │   │   └── user/user.go                      # 用户聚合根
  10. │   │   ├── repository/                           # 仓储接口
  11. │   │   │   ├── order/order_repository.go
  12. │   │   │   └── user/user_repository.go
  13. │   │   ├── event/                                # 领域事件
  14. │   │   │   ├── domain_event.go
  15. │   │   │   ├── order_event.go
  16. │   │   │   ├── user_event.go
  17. │   │   │   └── event_publisher.go
  18. │   │   ├── notification/mail_service.go          # 通知领域接口(邮件)
  19. │   │   └── service/                              # 领域服务(预留)
  20. │   ├── application/                              # 应用层
  21. │   │   ├── dto/
  22. │   │   │   ├── order/order_dto.go
  23. │   │   │   └── user/user_dto.go
  24. │   │   └── service/
  25. │   │       ├── order/order_service.go            # 订单应用服务(发布事件)
  26. │   │       └── user/user_service.go              # 用户应用服务
  27. │   ├── infrastructure/                           # 基础设施层
  28. │   │   ├── config/                               # 配置与 DB 初始化
  29. │   │   ├── persistence/                          # 仓储实现
  30. │   │   │   ├── order/order_repository_impl.go
  31. │   │   │   └── user/user_repository_impl.go
  32. │   │   ├── mq/                                   # RocketMQ 实现
  33. │   │   │   ├── rocketmq_producer.go
  34. │   │   │   └── rocketmq_consumer.go
  35. │   │   ├── mail/                                 # SMTP 邮件实现
  36. │   │   ├── middleware/                           # Gin 中间件
  37. │   │   ├── common/response.go                    # 统一响应
  38. │   │   └── constants/error_code.go               # 错误码
  39. │   └── interfaces/                               # 接口层
  40. │       ├── handler/                              # HTTP 处理器
  41. │       ├── router/                               # 路由配置
  42. │       └── vo/                                   # 请求/响应对象
  43. └── pkg/utils/                                    # 日志等工具
复制代码
各层职责说明

层级位置职责关键原则领域层internal/domain/领域模型、规则与事件不依赖框架、业务逻辑内聚应用层internal/application/编排领域对象、事务边界薄而清晰,不实现业务规则基础设施层internal/infrastructure/DB、MQ、邮件等技术细节向上提供实现,细节下沉接口层internal/interfaces/HTTP 请求/响应与路由处理外部交互,不含业务规则快速开始

1. 环境准备


  • Go 1.21+
  • MySQL 8.0+ 与 PostgreSQL 14+(或自行选择其一)
  • RocketMQ 5.3+(可选)
2. 初始化数据库

默认配置使用双数据库:

  • 用户库:MySQL
  • 订单库:PostgreSQL
MySQL 用户库示例(可直接用 docs/init.sql 作为起点):
  1. CREATE DATABASE IF NOT EXISTS gin_ddd CHARACTER SET utf8mb4;
  2. USE gin_ddd;
  3. CREATE TABLE IF NOT EXISTS users (
  4.     id BIGINT AUTO_INCREMENT PRIMARY KEY,
  5.     name VARCHAR(50) NOT NULL UNIQUE,
  6.     email VARCHAR(100) NOT NULL UNIQUE,
  7.     phone VARCHAR(20),
  8.     created_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  9.     updated_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
  10. );
复制代码
PostgreSQL 订单库示例(与当前订单仓储字段一致):
  1. CREATE DATABASE seed;
  2. \c seed;
  3. CREATE TABLE IF NOT EXISTS orders (
  4.     id BIGSERIAL PRIMARY KEY,
  5.     order_no VARCHAR(50) NOT NULL UNIQUE,
  6.     user_id BIGINT NOT NULL,
  7.     total_amount DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
  8.     status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
  9.     created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  10.     updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  11. );
复制代码
数据库适配注意:

  • 若订单库改为 MySQL,需要将 SQL 占位符从 $1 形式改为 ?
  • 若用户库改为 PostgreSQL,需要将插入 ID 获取逻辑改为 RETURNING id
3. 配置应用

编辑 config/config.yaml,至少配置数据库与 RocketMQ:
  1. server:
  2.   host: "0.0.0.0"
  3.   port: 8080
  4.   mode: "debug"
  5. database:
  6.   user:
  7.     driver: "mysql"
  8.     host: "localhost"
  9.     port: 3306
  10.     username: "root"
  11.     password: "your_password"
  12.     database: "gin_ddd"
  13.   order:
  14.     driver: "postgres"
  15.     host: "localhost"
  16.     port: 5432
  17.     username: "postgres"
  18.     password: "your_password"
  19.     database: "seed"
  20. rocketmq:
  21.   enabled: true
  22.   nameserver: "localhost:9876"
  23.   group_name: "gin-ddd-group"
  24.   instance_name: "gin-ddd-instance"
  25.   topics:
  26.     order_event: "order-event-topic"
复制代码
说明:

  • rocketmq.enabled: true 才会初始化生产者与消费者
  • 当前订单事件 Topic 在代码中使用固定值 order-event-topic,需与配置保持一致
4. 启动 RocketMQ(可选)
  1. sh bin/mqnamesrv
  2. sh bin/mqbroker -n localhost:9876
复制代码
5. 启动应用
  1. go mod tidy
  2. go run cmd/server/main.go
复制代码
6. 验证接口
  1. curl http://localhost:8080/health
  2. curl http://localhost:8080/api/users
  3. curl http://localhost:8080/api/orders
复制代码
如何基于脚手架开发新功能

示例:新增“商品管理”模块
步骤 1:新增领域模型 internal/domain/model/product/product.go
  1. package product
  2. import "time"
  3. type Product struct {
  4.         ID        int64
  5.         Name      string
  6.         Price     float64
  7.         Stock     int
  8.         CreatedAt time.Time
  9.         UpdatedAt time.Time
  10. }
复制代码
步骤 2:新增仓储接口 internal/domain/repository/product/product_repository.go
  1. package product
  2. import (
  3.         "context"
  4.         "gin-ddd/internal/domain/model/product"
  5. )
  6. type ProductRepository interface {
  7.         Create(ctx context.Context, p *product.Product) error
  8.         Update(ctx context.Context, p *product.Product) error
  9.         FindByID(ctx context.Context, id int64) (*product.Product, error)
  10.         FindAll(ctx context.Context) ([]*product.Product, error)
  11. }
复制代码
步骤 3:新增仓储实现 internal/infrastructure/persistence/product/product_repository_impl.go
  1. package product
  2. import (
  3.         "context"
  4.         "database/sql"
  5.         "gin-ddd/internal/domain/model/product"
  6. )
  7. type ProductRepositoryImpl struct {
  8.         db *sql.DB
  9. }
  10. func NewProductRepository(db *sql.DB) *ProductRepositoryImpl {
  11.         return &ProductRepositoryImpl{db: db}
  12. }
  13. func (r *ProductRepositoryImpl) Create(ctx context.Context, p *product.Product) error {
  14.         _, err := r.db.ExecContext(ctx,
  15.                 `INSERT INTO products (name, price, stock, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`,
  16.                 p.Name, p.Price, p.Stock, p.CreatedAt, p.UpdatedAt,
  17.         )
  18.         return err
  19. }
复制代码
步骤 4:新增应用服务 internal/application/service/product/product_service.go
  1. package product
  2. import (
  3.         "context"
  4.         "time"
  5.         "gin-ddd/internal/domain/model/product"
  6.         productDomain "gin-ddd/internal/domain/repository/product"
  7. )
  8. type ProductService struct {
  9.         repo productDomain.ProductRepository
  10. }
  11. func NewProductService(repo productDomain.ProductRepository) *ProductService {
  12.         return &ProductService{repo: repo}
  13. }
  14. func (s *ProductService) Create(ctx context.Context, name string, price float64, stock int) error {
  15.         p := &product.Product{
  16.                 Name:      name,
  17.                 Price:     price,
  18.                 Stock:     stock,
  19.                 CreatedAt: time.Now(),
  20.                 UpdatedAt: time.Now(),
  21.         }
  22.         return s.repo.Create(ctx, p)
  23. }
复制代码
步骤 5:新增 HTTP Handler 和路由
将请求/响应对象放到 internal/interfaces/vo/product/,Handler 放到 internal/interfaces/handler/product/,并在 internal/interfaces/router/router.go 中注册路由。
步骤 6:新增数据库表
  1. CREATE TABLE IF NOT EXISTS products (
  2.     id BIGINT AUTO_INCREMENT PRIMARY KEY,
  3.     name VARCHAR(100) NOT NULL,
  4.     price DECIMAL(10, 2) NOT NULL,
  5.     stock INT NOT NULL DEFAULT 0,
  6.     created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  7.     updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  8. );
复制代码
事件驱动与 RocketMQ

事件类型

订单事件:

  • order.created
  • order.paid
  • order.shipped
  • order.delivered
  • order.cancelled
  • order.refunded
用户事件:

  • user.created
  • user.activated
  • user.deactivated
  • user.blocked
  • user.deleted
消息流转
  1. HTTP 请求 -> Application Service -> Domain Model
  2.             -> 发布 DomainEvent -> RocketMQ Producer
  3.             -> RocketMQ Broker -> Consumer
  4.             -> 事件处理 -> 发送邮件/触发后续流程
复制代码
事件发布与消费关键点


  • 订单创建后会发布 order.created 事件(发布失败不会影响主流程)
  • 消费端按 Tag 解析为 OrderEvent 或 UserEvent
  • 订单邮件通知仅在 order.created 且启用邮件时触发
邮件发送配置(QQ 邮箱)

在 config/config.yaml 中开启邮件配置:
  1. mail:
  2.   enabled: true
  3.   host: "smtp.qq.com"
  4.   port: 465
  5.   username: "your@qq.com"
  6.   password: "你的SMTP授权码"
  7.   from_email: "your@qq.com"
  8.   from_name: "订单系统"
复制代码
注意事项:

  • 必须使用 SMTP 授权码,不是 QQ 登录密码
  • 端口 465 使用 TLS,端口 587 使用 STARTTLS
  • 收件人取自用户表中的 email 字段
常见问题排查


  • 日志提示“事件发布器未初始化”:RocketMQ 未启用或初始化失败
  • 订单事件已发送但邮件未到:确认用户邮箱字段正确,且 SMTP 授权码可用
  • 消费者没有收到消息:确认 Topic 与 Tag 正确、Broker 启动正常
开发规范

命名建议:

  • 领域模型:名词,如 Order、User
  • 应用服务:XxxService
  • 仓储接口:XxxRepository
  • 仓储实现:XxxRepositoryImpl
  • Handler:XxxHandler
分层原则:

  • 领域层不依赖基础设施
  • 应用层只做编排与事务协调
  • 基础设施提供技术实现
  • 接口层只负责 HTTP 交互
常用命令
  1. go mod tidy
  2. go test ./...
复制代码
源码地址

https://github.com/microwind/design-patterns/tree/main/practice-projects/gin-ddd

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

7 天前

举报

您需要登录后才可以回帖 登录 | 立即注册