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 框架死死锁定。

相关推荐
Go_error1 天前
Go channel 数据聚合
后端·go
stark张宇1 天前
Go 语言实现安全的分享链接:AES 加密 + SHA256 签名 + 过期防重放
后端·go
我叫黑大帅1 天前
Golang中的map的key可以是哪些类型?可以嵌套map吗?
后端·面试·go
用户095367515831 天前
Go :如何声明变量(var)与常量(const)
后端·go
FelixBitSoul1 天前
Go 语言面试深度全攻略:从工程化到底层原理,一文通杀
后端·go
你有医保你先上2 天前
Elasticsearch Go 客户端
后端·elasticsearch·go
Vale3652 天前
[Go]字符串 比较
go
UIUV3 天前
Go语言入门到精通学习笔记
后端·go·编程语言
littleschemer3 天前
Go异步持久化如何防止炸服
go·map并发崩溃