一款Go语言Gin框架MVC脚手架,满足大部分场景
一个开箱即用的 MVC(Model-View-Controller)Go 脚手架,基于 Gin + RocketMQ,包含双数据库、统一响应、中间件与事件驱动示例。
这是什么
Gin-Framework-MVC 是一个面向 Go 语言的 MVC 工程脚手架,帮你快速搭建分层清晰的 Web 服务。项目内置用户与订单示例、RocketMQ 生产/消费、邮件通知示例、统一响应与中间件,适合作为团队工程模板,用于代码初始化,适用于大多数场景。
功能与 practice-projects/gin-ddd一致。有别于DDD架构,MVC架构更加简洁清晰,可以对比下DDD与MVC工程目录结构的差异,根据业务需要选择DDD或者MVC架构。
为什么要用 MVC?
很多人会在 Go 项目里直接把路由、业务、数据访问写在一起,小项目可以跑得很快,但模块一多就容易失控。MVC 的价值在于把职责拆开:Controller 负责 HTTP 交互,Service 承载业务规则,Repository 专注数据访问,Model 维护核心状态与行为。
总之,是否采用 MVC 和语言无关,重点在于业务复杂度与团队协作成本。对于中小型到中大型业务系统,MVC 能在“足够清晰”和“实现成本”之间取得很好平衡。
源码地址:https://github.com/microwind/design-patterns/tree/main/practice-projects/gin-mvc
项目目录:gin-mvc/
核心特点
- 清晰 MVC 分层:Controller、Service、Repository、Model
- Gin Web 框架:高性能 HTTP 服务
- 事件驱动:业务事件 + RocketMQ 生产者/消费者
- 双数据库支持:用户库 + 订单库可独立配置(默认 MySQL + PostgreSQL)
- 统一响应格式:Response 封装,错误码按业务域划分
- 全局中间件:请求 ID、日志、恢复、跨域
- 可选邮件通知:订单创建事件驱动 SMTP 邮件发送
技术栈
技术版本说明Go1.21+语言版本Gin1.9+HTTP 框架RocketMQ5.3+事件消息队列MySQL8.0+用户库默认PostgreSQL14+订单库默认YAML-配置文件格式工程结构
工程结构图
flowchart LR Client[客户端] subgraph Web["Web 入口"] Router[Gin Router] Middleware[Middleware] end subgraph MVC["MVC 核心"] Controller[Controller] Service[Service] Model[Model] View[View JSON/Template ] end subgraph Repo["数据访问"] Repository[Repository] UserDB[(MySQL 用户库)] OrderDB[(PostgreSQL 订单库)] end subgraph Event["事件与通知"] Producer[RocketMQ Producer] Topic[(RocketMQ Topic)] Consumer[RocketMQ Consumer] Handler[Event Handler] Mail[SMTP Mail] end Client --> Router Router --> Middleware Middleware --> Controller Controller --> Service Service --> Model Service --> Repository Repository --> UserDB Repository --> OrderDB Controller --> View View --> Client Service -.发布事件.-> Producer Producer --> Topic Topic --> Consumer Consumer --> Handler Handler --> Mail工程结构列表
- gin-mvc/
- ├── cmd/main.go # 启动入口,装配各层并启动 HTTP + MQ
- ├── config/config.yaml # 应用配置
- ├── docs/
- │ ├── init_user_mysql.sql # MySQL 用户库初始化脚本
- │ └── init_order_postgres.sql # PostgreSQL 订单库初始化脚本
- ├── internal/
- │ ├── controllers/ # Controller 层(HTTP 处理)
- │ │ ├── home/home_controller.go
- │ │ ├── order/order_controller.go
- │ │ └── user/user_controller.go
- │ ├── services/ # Service 层(业务编排)
- │ │ ├── order/order_service.go # 订单服务(状态流转 + 发布事件)
- │ │ ├── user/user_service.go # 用户服务
- │ │ ├── event/order_handler.go # 事件消费处理
- │ │ └── notification/mail_service.go # 邮件服务接口
- │ ├── repository/ # Repository 层(数据访问与外部依赖)
- │ │ ├── db/ # DB 连接与方言占位符
- │ │ ├── order/
- │ │ │ ├── order_repository.go
- │ │ │ └── order_sql_repository.go
- │ │ ├── user/
- │ │ │ ├── user_repository.go
- │ │ │ └── user_sql_repository.go
- │ │ ├── mq/ # RocketMQ 实现
- │ │ │ ├── rocketmq_producer.go
- │ │ │ └── rocketmq_consumer.go
- │ │ └── mail/smtp_mail_repository.go # SMTP 邮件实现
- │ ├── models/ # Model 层(核心模型与事件)
- │ │ ├── order/order.go
- │ │ ├── user/user.go
- │ │ └── event/
- │ │ ├── event.go
- │ │ ├── order_event.go
- │ │ └── user_event.go
- │ ├── middleware/ # Gin 中间件
- │ │ ├── request_id.go
- │ │ ├── logging.go
- │ │ ├── recovery.go
- │ │ ├── cors.go
- │ │ └── context.go
- │ └── config/config.go # 配置加载与校验
- ├── pkg/
- │ ├── logger/logger.go # 日志工具
- │ └── response/response.go # 统一响应
- └── web/templates/order.tmpl # 示例页面模板
复制代码 各层职责说明
层级位置职责关键原则Model 层internal/models/核心业务对象、状态机与事件模型聚焦业务语义,不依赖 HTTP/DB 细节Service 层internal/services/编排业务流程、状态流转、事件发布业务规则集中,避免散落到 ControllerRepository 层internal/repository/DB 访问、MQ/SMTP 等外部系统集成只做 IO 与持久化,不承载业务规则Controller 层internal/controllers/HTTP 请求解析、参数校验、响应输出轻量薄层,不直接操作数据库快速开始
1. 环境准备
- Go 1.21+
- MySQL 8.0+ 与 PostgreSQL 14+(或自行选择其一)
- RocketMQ 5.3+(可选)
- SMTP 邮箱(可选,推荐 QQ 邮箱)
2. 初始化数据库
默认配置使用双数据库:
- 用户库:MySQL(默认库名 gin_mvc_user)
- 订单库:PostgreSQL(默认库名 gin_mvc_order)
执行初始化脚本:- mysql -u root -p < docs/init_user_mysql.sql
- psql -U postgres -f docs/init_order_postgres.sql
复制代码 数据库适配注意:
- 当前仓储已同时支持 MySQL 与 PostgreSQL 占位符
- 切换驱动时,确保 config/config.yaml 的 database.user.driver 与 database.order.driver 正确
3. 配置应用
编辑 config/config.yaml,至少配置数据库与 RocketMQ:- server:
- host: "0.0.0.0"
- port: 8080
- mode: "debug"
- database:
- user:
- driver: "mysql"
- host: "localhost"
- port: 3306
- username: "root"
- password: "your_password"
- database: "gin_mvc_user"
- order:
- driver: "postgres"
- host: "localhost"
- port: 5432
- username: "postgres"
- password: "your_password"
- database: "gin_mvc_order"
- rocketmq:
- enabled: true
- nameserver: "localhost:9876"
- group_name: "gin-mvc-group"
- instance_name: "gin-mvc-instance"
- topics:
- order_event: "order-event-topic"
复制代码 说明:
- rocketmq.enabled: true 才会初始化生产者与消费者
- rocketmq.topics.order_event 不能为空,否则配置校验会失败
- 若暂不使用 MQ,可设置 rocketmq.enabled: false
最小可运行配置(本地联调推荐):
- database.user 和 database.order 配置正确可连通
- rocketmq.enabled: false(如果暂不使用消息)
- mail.enabled: false(如果暂不发邮件)
4. 启动 RocketMQ(可选)
- sh bin/mqnamesrv
- sh bin/mqbroker -n localhost:9876
复制代码 5. 启动应用
- go mod tidy
- go run cmd/main.go
复制代码 6. 验证接口
- curl http://localhost:8080/health
- curl http://localhost:8080/api/users
- curl http://localhost:8080/api/orders
复制代码 API 一览
用户接口
- POST /api/users
- GET /api/users
- GET /api/users/:id
- PUT /api/users/:id/email
- PUT /api/users/:id/phone
- DELETE /api/users/:id
- GET /api/users/:id/orders
示例:- curl -X POST http://localhost:8080/api/users \
- -H "Content-Type: application/json" \
- -d '{"name":"张三","email":"zhangsan@example.com","phone":"13800138000"}'
复制代码 订单接口
- POST /api/orders
- GET /api/orders
- GET /api/orders/:id
- PUT /api/orders/:id/pay
- PUT /api/orders/:id/ship
- PUT /api/orders/:id/deliver
- PUT /api/orders/:id/cancel
- PUT /api/orders/:id/refund
示例:- curl -X POST http://localhost:8080/api/orders \
- -H "Content-Type: application/json" \
- -d '{"user_id":1,"total_amount":99.99}'
复制代码 配置说明
config/config.yaml 主要分区:
- server:主机、端口、Gin 模式、超时
- database.user:用户库连接
- database.order:订单库连接
- log:日志级别与输出格式(text/json)
- rocketmq:开关、nameserver、group、topic
- mail:SMTP 开关与账号配置
如何基于脚手架开发新功能
示例:新增“商品管理”模块
步骤 1:新增模型 internal/models/product/product.go- package product
- import "time"
- type Product struct {
- ID int64
- Name string
- Price float64
- Stock int
- CreatedAt time.Time
- UpdatedAt time.Time
- }
复制代码 步骤 2:新增仓储接口 internal/repository/product/product_repository.go- package product
- import (
- "context"
- "gin-mvc/internal/models/product"
- )
- type Repository interface {
- Create(ctx context.Context, p *product.Product) error
- Update(ctx context.Context, p *product.Product) error
- FindByID(ctx context.Context, id int64) (*product.Product, error)
- FindAll(ctx context.Context) ([]*product.Product, error)
- }
复制代码 步骤 3:新增仓储实现 internal/repository/product/product_sql_repository.go- package product
- import (
- "context"
- "database/sql"
- "gin-mvc/internal/models/product"
- )
- type SQLRepository struct {
- db *sql.DB
- }
- func NewSQLRepository(db *sql.DB) *SQLRepository {
- return &SQLRepository{db: db}
- }
- func (r *SQLRepository) Create(ctx context.Context, p *product.Product) error {
- _, err := r.db.ExecContext(ctx,
- `INSERT INTO products (name, price, stock, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`,
- p.Name, p.Price, p.Stock, p.CreatedAt, p.UpdatedAt,
- )
- return err
- }
复制代码 步骤 4:新增业务服务 internal/services/product/product_service.go- package product
- import (
- "context"
- "time"
- "gin-mvc/internal/models/product"
- productRepo "gin-mvc/internal/repository/product"
- )
- type Service struct {
- repo productRepo.Repository
- }
- func New(repo productRepo.Repository) *Service {
- return &Service{repo: repo}
- }
- func (s *Service) Create(ctx context.Context, name string, price float64, stock int) error {
- p := &product.Product{
- Name: name,
- Price: price,
- Stock: stock,
- CreatedAt: time.Now(),
- UpdatedAt: time.Now(),
- }
- return s.repo.Create(ctx, p)
- }
复制代码 步骤 5:新增 Controller 和路由
将 Controller 放到 internal/controllers/product/,并在 cmd/main.go 中注册路由组 api.Group("/products")。
步骤 6:新增数据库表- CREATE TABLE IF NOT EXISTS products (
- id BIGINT AUTO_INCREMENT PRIMARY KEY,
- name VARCHAR(100) NOT NULL,
- price DECIMAL(10, 2) NOT NULL,
- stock INT NOT NULL DEFAULT 0,
- created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
- );
复制代码 事件驱动与 RocketMQ
事件类型
订单事件:
- order.created
- order.paid
- order.shipped
- order.delivered
- order.cancelled
- order.refunded
用户事件:
- user.created
- user.deleted
消息流转
- HTTP 请求 -> Controller -> Service -> Model/Repository
- -> 发布 DomainEvent -> RocketMQ Producer
- -> RocketMQ Broker -> Consumer
- -> 事件处理 -> 发送邮件/触发后续流程
复制代码 订单创建场景(更具体):- HTTP 请求
- -> OrderController
- -> OrderService(入库后发布事件)
- -> RocketMQ Producer
- -> RocketMQ Topic(order-event-topic)
- -> RocketMQ Consumer
- -> event handler
- -> SMTP MailService(order.created 时发送确认邮件)
复制代码 事件发布与消费关键点
- 订单创建、支付、取消流程会尝试发布订单事件(发布失败不会中断主业务)
- 消费端按 Tag 前缀解析消息:order.* 映射 OrderEvent,user.* 映射 UserEvent
- 订单邮件通知仅在 order.created 且启用邮件时触发
邮件发送配置(QQ 邮箱)
在 config/config.yaml 中开启邮件配置:- mail:
- enabled: true
- host: "smtp.qq.com"
- port: 465
- username: "your@qq.com"
- password: "你的SMTP授权码"
- from_email: "your@qq.com"
- from_name: "订单系统"
复制代码 注意事项:
- 必须使用 SMTP 授权码,不是 QQ 登录密码
- 端口 465 使用 TLS,端口 587 使用 STARTTLS
- 收件人取自用户表中的 email 字段
常见问题排查
- 开启了 RocketMQ 但没有消息发布
- 检查 rocketmq.enabled、NameServer/Broker 连接、topics.order_event 配置
- 订单事件已消费但邮件未发送
- 检查 mail.enabled、SMTP 授权码、用户邮箱字段是否正确
- 消费者没有收到消息
- 检查 Topic 与 Tag 是否匹配、Consumer Group 是否正常
- 数据库报占位符或驱动错误
- 检查 database.*.driver 与目标数据库是否匹配
开发规范
命名建议:
- 模型:名词,如 Order、User
- 服务:Service 或 XxxService
- 仓储接口:Repository
- 仓储实现:SQLRepository
- 控制器:Controller 或 XxxController
分层原则:
- Controller 只处理 HTTP 参数与响应
- Service 负责业务规则、流程编排与事件发布
- Repository 负责数据访问与外部依赖调用
- Model 负责领域状态和对象行为
对比 DDD 版本
和 practice-projects/gin-ddd 对比:
- 功能面保持一致:用户/订单/MQ/邮件/双库
- 分层方式改为 MVC:更易理解和教学展示
- 依赖注入在 cmd/main.go 统一装配,便于快速定位启动流程
常用命令
源码地址
MVC架构:
https://github.com/microwind/design-patterns/tree/main/practice-projects/gin-mvc
DDD架构:
https://github.com/microwind/design-patterns/tree/main/practice-projects/gin-ddd
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |