Gin 框架学习实录 · 第6篇:构建通用响应模块(统一结构体 + 错误码 + 分页封装)

前言

在前面几篇中,我们已经完成了用户模块的注册、查询、更新、删除,以及分页查询接口。过程中我们也写了分页结构体、统一的接口返回方法,看起来也还挺顺手的。

但写着写着就会发现,有些东西我们在每个接口里都在重复写,比如:

  • 分页的 page/page_size/total/list,接口一多就得一遍遍写
  • 接口返回结构也差不多,都是 code + msg + data,还不如封一下
  • 错误信息如果不统一,前端调用时也不太好处理

所以今天我们就来干脆一步到位:

把分页结构、响应结构、错误码这些**"所有接口都绕不开的东西"**,统一抽出来封装成一个响应模块。

模板结构:core/response 模块

我们将通用的响应逻辑提取到一个独立模块,命名为:

bash 复制代码
core/response

模块职责非常明确:

  • 管理所有接口响应结构(code/msg/data)
  • 提供 Success / Fail / WithCode 等统一返回方法
  • 封装错误码常量与提示信息映射
  • 提供分页响应结构 PageData

项目结构如下:

go 复制代码
gin-learn-notes/
└── core/
    └── response/
        ├── code.go        // ✅ 错误码常量与提示信息
        ├── response.go    // ✅ 通用响应结构体 + 返回方法
        └── page.go        // ✅ 分页响应结构封装(PageData)

如果我们后续如果需要扩展,比如加 trace_id、响应耗时统计、多语言支持,也可以继续在这个模块里扩展,结构非常灵活。

第一步:创建响应模块目录 & 错误码定义

创建目录

我们先在项目中创建响应模块的存放路径:

bash 复制代码
mkdir -p core/response

编写 core/response/code.go

在这个文件中我们统一管理所有的错误码。先定义一些常用的通用错误码:

go 复制代码
package response

const (
	CodeSuccess  = 0      // 成功
	ParamError   = 10001  // 参数错误
	NotFound     = 10002  // 数据不存在
	DBError      = 10003  // 数据库错误
	Unauthorized = 10004  // 未授权/未登录
	ServerError  = 10005  // 服务内部错误
)

第二步:统一响应结构封装(response.go

创建文件:

bash 复制代码
touch core/response/response.go

然后我们定义一个标准的响应结构体 Result,并提供常用的响应函数:

go 复制代码
package response

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type Result struct {
	Code int         `json:"code"`           // 状态码
	Msg  string      `json:"msg"`            // 提示信息
	Data interface{} `json:"data,omitempty"` // 返回数据(可选)
}

通用响应方法

go 复制代码
// JSON 是最底层响应封装方法
func JSON(c *gin.Context, code int, msg string, data interface{}) {
    c.JSON(http.StatusOK, Result{
       Code: code,
       Msg:  msg,
       Data: data,
    })
}

// Success 成功响应(含数据)
func Success(c *gin.Context, data interface{}) {
    JSON(c, CodeSuccess, "success", data)
}

// Fail 失败响应(含错误码与信息)
func Fail(c *gin.Context, code int, msg string) {
    JSON(c, code, msg, nil)
}

第三步:提取分页响应结构体(page.go)

在上一篇中我们在 utils/paginate.go 中写了分页响应结构体:

go 复制代码
type PageData struct {
	List     interface{} `json:"list"`
	Total    int64       `json:"total"`
	Page     int         `json:"page"`
	PageSize int         `json:"page_size"`
}

它用于标准化所有分页接口的返回结果,避免每个接口都重复写 list + total + page + page_size

提取到 core 模块

现在我们将它挪到统一响应模块中,新建文件:

bash 复制代码
touch core/response/page.go

内容如下:

go 复制代码
package response

type PageData struct {
	List     interface{} `json:"list"`      // 数据列表
	Total    int64       `json:"total"`     // 总数
	Page     int         `json:"page"`      // 当前页
	PageSize int         `json:"page_size"` // 每页条数
}

使用示例

go 复制代码
response.Success(c, response.PageData{
	List:     users,
	Total:    total,
	Page:     req.Page,
	PageSize: req.PageSize,
})

这样所有分页接口就可以统一使用 PageData,无需在 controller 中重复拼接,接口响应结构也更加统一、易读、标准化 .

示例:如何在控制器中使用统一响应模块

统一封装完响应结构之后,我们在控制器中就可以这样调用,非常清爽、标准:

go 复制代码
import (
	"gin-learn-notes/core/response"
	"github.com/gin-gonic/gin"
)

成功响应(带数据)

go 复制代码
response.Success(c, gin.H{
	"user_id": user.ID,
})

返回示例:

json 复制代码
{
  "code": 0,
  "msg": "success",
  "data": {
    "user_id": 1
  }
}

失败响应(带错误码 + 提示)

go 复制代码
response.Fail(c, response.CodeParamError, "参数不合法")

返回示例:

json 复制代码
{
  "code": 10001,
  "msg": "参数不合法",
  "data": null
}

模块可复用性 & 扩展性

我们现在封装的这个 core/response/ 模块,其实并不只属于当前这个项目。

我们甚至可以把它整个目录 复制粘贴到任何一个 Gin 项目中直接使用,完全不依赖业务代码,极其通用。

甚至我们也可以将其提取为自己的 Git 子模块或私有模块,比如:

bash 复制代码
github.com/myname/gin-core/response

以后每个新项目 go get 一下,直接引用,响应结构、错误码、分页一应俱全,开箱即用。

项目结构继续演进(集成响应模块)

go 复制代码
gin-learn-notes/
├── config/
│   └── database.go                   // 数据库连接配置
│
├── controller/
│   ├── hello.go
│   ├── index.go
│   └── user.go                       // 用户模块控制器
│
├── core/
│   └── response/                     // ✅ 响应模块(统一响应结构、错误码、分页结构体)
│       ├── code.go                   // 错误码定义
│       ├── page.go                   // 分页响应结构体
│       └── response.go               // 通用响应结构体 + 返回方法
│
├── model/
│   └── user.go                       // 用户数据模型
│
├── request/
│   ├── page_request.go              // 通用分页请求结构体
│   └── user_request.go              // 用户模块请求结构体
│
├── router/
│   └── router.go                    // 路由注册
│
├── service/
│   └── user_service.go              // 用户业务逻辑处理
│
├── utils/
│   ├── paginate.go                  // 泛型分页方法
│   ├── response.go                  // 已封装的通用响应(可逐步迁移至 core/response)
│   └── validator.go                 // 参数校验错误翻译
│
├── main.go                          // 项目入口
├── go.mod
├── .gitignore
└── README.md

最后

到目前为止,我们已经围绕 Gin 框架完成了多个模块的实战开发与封装,包括:

  • ✅ 用户模块的增删改查接口(全 POST 实现)
  • ✅ 通用分页请求参数与分页响应结构的封装
  • ✅ 统一响应格式结构体 + 错误码管理模块
  • ✅ 控制器职责划分清晰、代码结构逐步模块化

在拥有了结构清晰的项目基础后,下一步我们将实现日志模块的封装与接入。

日志是后端系统不可或缺的模块,它直接影响到问题排查与系统可观测性,我们将继续秉持"可复用"的思路,把日志模块也封装成一个独立组件,服务整个项目。

本篇对应代码提交记录

commit: 6bc8562fb0d6d2b818aef48f722fddc087c58e85

👉 GitHub 源码地址:github.com/luokakale-k...

相关推荐
用户20066144472415 小时前
MySQL 慢查询日志开启与问题排查指南
go
喵个咪1 天前
Ent代码生成工具链
后端·go
洛卡卡了1 天前
Gin 框架学习实录 · 第9篇:实现 Redis 缓存模块封装与应用
go
洛卡卡了1 天前
Gin 框架学习实录 · 第10篇:实现用户登录功能与 JWT Token 签发及中间件验证
go
CHSnake1 天前
设计HTTP和gRPC错误码.md
后端·go
一个热爱生活的普通人1 天前
GO 扩展库: semaphore 实现原理与使用
后端·go
CyberTM1 天前
终端党的福音!开源Git命令速查工具Git Cheat Sheet TUI
git·python·go
Vespeng1 天前
Go-SJSON 组件,JSON 动态修改新方案
go
Wo3Shi4七1 天前
双向列队
数据结构·go
addaduvyhup2 天前
从 Java 的 Spring Boot MVC 转向 Go 语言开发的差异变化
java·spring boot·go·mvc