GO分层架构【2】使用GIN与GORM

现在大家都使用的的GIN和GORM开发架构是怎么样的?

目前在 Go 社区中,基于 Gin 和 GORM 的主流微服务开发架构,最推崇的是 "工程化分层"。它在你的基础上,通过引入 Logic/Service 层 和 Repository 层,彻底解决代码臃肿和难以测试的问题。

以下是目前最流行的标准架构拆解:

1. 核心分层架构图

数据流向遵循:请求 → Handler → Logic → Repository → Database。

复制代码
internal/
├── handler/       # (入口层) 负责 Gin 的参数绑定、简单校验、返回 JSON
├── logic/         # (业务层) 核心是大脑!组合业务步骤,不涉及具体 SQL
├── repository/    # (持久层) 只有这里出现 GORM,负责具体的增删改查
├── model/         # (模型层) 定义 GORM 结构体(Table Schema)
└── middleware/    # (中间件) 权限校验、日志记录

2. 各层代码示例(以"用户充值"为例)

第一层:model (定义表结构)

复制代码
package model

type User struct {
    ID      uint   `gorm:"primaryKey"`
    Balance int64  `gorm:"column:balance"` // 余额
}

第二层:repository (数据操作 - 只有它认识 GORM)

复制代码
package repository

import "your-project/internal/model"
import "gorm.io/gorm"

type UserRepo struct {
    db *gorm.DB
}

func (r *UserRepo) UpdateBalance(id uint, amount int64) error {
    // 纯粹的数据库操作
    return r.db.Model(&model.User{}).Where("id = ?", id).
        Update("balance", gorm.Expr("balance + ?", amount)).Error
}

第三层:logic (业务核心 - 这里处理复杂逻辑)

复制代码
package logic

import "your-project/internal/repository"

type UserLogic struct {
    repo *repository.UserRepo
}

func (l *UserLogic) Recharge(userId uint, money int64) error {
    // 1. 这里处理业务规则:比如充值不能小于 0
    if money <= 0 { return errors.New("金额错误") }
    
    // 2. 调用数据层
    return l.repo.UpdateBalance(userId, money)
}

第四层:handler (Gin 入口 - 只管翻译)

复制代码
package handler

import "your-project/pkg/res" // 你之前定义的统一返回

func RechargeHandler(c *gin.Context) {
    var req struct { UserId uint; Amount int64 }
    c.ShouldBindJSON(&req) // 参数解析

    // 调用 Logic 层
    err := logic.NewUserLogic().Recharge(req.UserId, req.Amount)

    if err != nil {
        c.JSON(200, res.Error(500, err.Error()))
        return
    }
    c.JSON(200, res.Success(nil)) // 统一格式返回
}

3. 为什么这是主流?

  1. GORM 不外溢:GORM 的代码只出现在 repositoryinfra。如果你哪天想换 sqlxent,只需要改底层,不需要动 logichandler
  2. Logic 层可复用:
    • API 调用:通过 handlerlogic
    • 定时任务:通过 cronlogic
    • 自检脚本:通过 test/clientlogic
  3. 并发安全与事务:主流做法是在 logic 层通过闭包或 Context 处理事务,确保业务的原子性。

4. 针对你现状的调整建议

  • infra 细化:你现在的 infra 可能只是初始化 DB 连接。建议在 infra 下建一个 repository 子目录,专门写 GORM 的查询。
  • 增加 logic 文件夹:把你 handler 里那些复杂的 if-else、计算、多步 SQL 写入全部挪到 logic 里。
  • 统一返回:继续使用你放在 pkg/res 下的结构体,这是非常地道的做法。

避坑指南:在 GORM 开发中,千万不要把 *gin.Context 传进 logic 层或数据库层,这会导致你的业务逻辑和 HTTP 框架死死锁定。

相关推荐
ylj_dev9 小时前
从 0 构建 AI Workload Platform(七):可观测性、故障注入与性能验证
go·prometheus·可观测性·opentelemetry·故障注入
我的div丢了肿么办12 小时前
go语言中基本数据类型的转换
后端·go
newerp1 天前
语法分析与 AST:Parser 与 go/ast
后端·程序员·go
newerp1 天前
Go 编译过程全景
后端·程序员·go
stark张宇2 天前
Go语言runtime全景图:从编译到GC,带你彻底吃透Go的底层血脉
后端·go
名字还没想好☜2 天前
Go 用 slices/maps 标准库泛型函数:告别手写 Contains、Sort、去重(Go 1.21)
开发语言·后端·算法·golang·go
运维开发笔记3 天前
5.2 Go 数组进阶学习笔记(多维、排序、搜索)
go
newerp3 天前
Redis 操作与缓存策略
后端·程序员·go
newerp3 天前
GORM ORM 基础
后端·程序员·go
newerp3 天前
CRUD 操作与预处理语句
后端·程序员·go