心特点清晰 MVC 分层Controller、Service、Repository、ModelGin Web 框架高性能 HTTP 服务事件驱动业务事件 RocketMQ 生产者/消费者双数据库支持用户库 订单库可独立配置默认 MySQL PostgreSQL统一响应格式Response 封装错误码按业务域划分全局中间件请求 ID、日志、恢复、跨域可选邮件通知订单创建事件驱动 SMTP 邮件发送技术栈技术版本说明Go1.21语言版本Gin1.9HTTP 框架RocketMQ5.3事件消息队列MySQL8.0用户库默认PostgreSQL14订单库默认YAML-配置文件格式工程结构工程结构图事件与通知数据访问MVC 核心Web 入口发布事件客户端Gin RouterMiddlewareControllerServiceModelView JSON/TemplateRepositoryMySQL 用户库PostgreSQL 订单库RocketMQ ProducerRocketMQ TopicRocketMQ ConsumerEvent HandlerSMTP 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.21MySQL 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.sqlpsql -U postgres -f docs/init_order_postgres.sql数据库适配注意当前仓储已同时支持 MySQL 与 PostgreSQL 占位符切换驱动时确保config/config.yaml的database.user.driver与database.order.driver正确3. 配置应用编辑config/config.yaml至少配置数据库与 RocketMQserver:host: 0.0.0.0port: 8080mode: debugdatabase:user:driver: mysqlhost: localhostport: 3306username: rootpassword: your_passworddatabase: gin_mvc_userorder:driver: postgreshost: localhostport: 5432username: postgrespassword: your_passworddatabase: gin_mvc_orderrocketmq:enabled: truenameserver: localhost:9876group_name: gin-mvc-groupinstance_name: gin-mvc-instancetopics: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/mqnamesrvsh bin/mqbroker -n localhost:98765. 启动应用go mod tidygo run cmd/main.go6. 验证接口curl http://localhost:8080/healthcurl http://localhost:8080/api/userscurl http://localhost:8080/api/ordersAPI 一览用户接口POST /api/usersGET /api/usersGET /api/users/:idPUT /api/users/:id/emailPUT /api/users/:id/phoneDELETE /api/users/:idGET /api/users/:id/orders示例curl -X POST http://localhost:8080/api/users \-H Content-Type: application/json \-d {name:张三,email:zhangsanexample.com,phone:13800138000}订单接口POST /api/ordersGET /api/ordersGET /api/orders/:idPUT /api/orders/:id/payPUT /api/orders/:id/shipPUT /api/orders/:id/deliverPUT /api/orders/:id/cancelPUT /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/jsonrocketmq开关、nameserver、group、topicmailSMTP 开关与账号配置如何基于脚手架开发新功能示例新增“商品管理”模块步骤 1新增模型internal/models/product/product.gopackage productimport timetype Product struct {ID int64Name stringPrice float64Stock intCreatedAt time.TimeUpdatedAt time.Time}步骤 2新增仓储接口internal/repository/product/product_repository.gopackage productimport (contextgin-mvc/internal/models/product)type Repository interface {Create(ctx context.Context, p *product.Product) errorUpdate(ctx context.Context, p *product.Product) errorFindByID(ctx context.Context, id int64) (*product.Product, error)FindAll(ctx context.Context) ([]*product.Product, error)}步骤 3新增仓储实现internal/repository/product/product_sql_repository.gopackage productimport (contextdatabase/sqlgin-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.gopackage productimport (contexttimegin-mvc/internal/models/productproductRepo 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.createdorder.paidorder.shippedorder.deliveredorder.cancelledorder.refunded用户事件user.createduser.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 MailServiceorder.created 时发送确认邮件事件发布与消费关键点订单创建、支付、取消流程会尝试发布订单事件发布失败不会中断主业务消费端按 Tag 前缀解析消息order.*映射OrderEventuser.*映射UserEvent订单邮件通知仅在order.created且启用邮件时触发邮件发送配置QQ 邮箱在config/config.yaml中开启邮件配置mail:enabled: truehost: smtp.qq.comport: 465username: yourqq.compassword: 你的SMTP授权码from_email: yourqq.comfrom_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统一装配便于快速定位启动流程常用命令
一款Go语言Gin框架MVC脚手架,满足大部分场景
心特点清晰 MVC 分层Controller、Service、Repository、ModelGin Web 框架高性能 HTTP 服务事件驱动业务事件 RocketMQ 生产者/消费者双数据库支持用户库 订单库可独立配置默认 MySQL PostgreSQL统一响应格式Response 封装错误码按业务域划分全局中间件请求 ID、日志、恢复、跨域可选邮件通知订单创建事件驱动 SMTP 邮件发送技术栈技术版本说明Go1.21语言版本Gin1.9HTTP 框架RocketMQ5.3事件消息队列MySQL8.0用户库默认PostgreSQL14订单库默认YAML-配置文件格式工程结构工程结构图事件与通知数据访问MVC 核心Web 入口发布事件客户端Gin RouterMiddlewareControllerServiceModelView JSON/TemplateRepositoryMySQL 用户库PostgreSQL 订单库RocketMQ ProducerRocketMQ TopicRocketMQ ConsumerEvent HandlerSMTP 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.21MySQL 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.sqlpsql -U postgres -f docs/init_order_postgres.sql数据库适配注意当前仓储已同时支持 MySQL 与 PostgreSQL 占位符切换驱动时确保config/config.yaml的database.user.driver与database.order.driver正确3. 配置应用编辑config/config.yaml至少配置数据库与 RocketMQserver:host: 0.0.0.0port: 8080mode: debugdatabase:user:driver: mysqlhost: localhostport: 3306username: rootpassword: your_passworddatabase: gin_mvc_userorder:driver: postgreshost: localhostport: 5432username: postgrespassword: your_passworddatabase: gin_mvc_orderrocketmq:enabled: truenameserver: localhost:9876group_name: gin-mvc-groupinstance_name: gin-mvc-instancetopics: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/mqnamesrvsh bin/mqbroker -n localhost:98765. 启动应用go mod tidygo run cmd/main.go6. 验证接口curl http://localhost:8080/healthcurl http://localhost:8080/api/userscurl http://localhost:8080/api/ordersAPI 一览用户接口POST /api/usersGET /api/usersGET /api/users/:idPUT /api/users/:id/emailPUT /api/users/:id/phoneDELETE /api/users/:idGET /api/users/:id/orders示例curl -X POST http://localhost:8080/api/users \-H Content-Type: application/json \-d {name:张三,email:zhangsanexample.com,phone:13800138000}订单接口POST /api/ordersGET /api/ordersGET /api/orders/:idPUT /api/orders/:id/payPUT /api/orders/:id/shipPUT /api/orders/:id/deliverPUT /api/orders/:id/cancelPUT /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/jsonrocketmq开关、nameserver、group、topicmailSMTP 开关与账号配置如何基于脚手架开发新功能示例新增“商品管理”模块步骤 1新增模型internal/models/product/product.gopackage productimport timetype Product struct {ID int64Name stringPrice float64Stock intCreatedAt time.TimeUpdatedAt time.Time}步骤 2新增仓储接口internal/repository/product/product_repository.gopackage productimport (contextgin-mvc/internal/models/product)type Repository interface {Create(ctx context.Context, p *product.Product) errorUpdate(ctx context.Context, p *product.Product) errorFindByID(ctx context.Context, id int64) (*product.Product, error)FindAll(ctx context.Context) ([]*product.Product, error)}步骤 3新增仓储实现internal/repository/product/product_sql_repository.gopackage productimport (contextdatabase/sqlgin-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.gopackage productimport (contexttimegin-mvc/internal/models/productproductRepo 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.createdorder.paidorder.shippedorder.deliveredorder.cancelledorder.refunded用户事件user.createduser.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 MailServiceorder.created 时发送确认邮件事件发布与消费关键点订单创建、支付、取消流程会尝试发布订单事件发布失败不会中断主业务消费端按 Tag 前缀解析消息order.*映射OrderEventuser.*映射UserEvent订单邮件通知仅在order.created且启用邮件时触发邮件发送配置QQ 邮箱在config/config.yaml中开启邮件配置mail:enabled: truehost: smtp.qq.comport: 465username: yourqq.compassword: 你的SMTP授权码from_email: yourqq.comfrom_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统一装配便于快速定位启动流程常用命令