统一响应与错误码封装

接口返回如果不统一,前端每个接口都要写不同的解析分支。GoFrame v2 规范路由场景下,官方默认中间件 ghttp.MiddlewareHandlerResponse 已把响应收敛成 {code, message, data} 结构;本章讲清默认行为,并给出“自定义统一中间件 + 业务错误码”的封装思路。

默认响应结构

框架的默认响应体定义(源码可见):

// ghttp.DefaultHandlerResponse
type DefaultHandlerResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    any    `json:"data"`
}

默认中间件逻辑:handler 返回 err == nil 时输出 code=0data 为业务结果;err != nil 时从错误中取错误码(gerror.Code(err)),无错误码的错误按内部错误处理并输出错误信息。

自定义统一中间件

默认结构往往不够用:要把业务码映射为 HTTP 状态码、记录错误日志、避免内部细节泄露给客户端。自定义时官方提示用 r.GetHandlerResponse() 取业务结果:

package middleware
import (
    "github.com/gogf/gf/v2/errors/gerror"
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/ghttp"
)

type Response struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Data    any    `json:"data"`
}

// HandlerResponse 统一响应中间件(全局 s.Use 挂载)
func HandlerResponse(r *ghttp.Request) {
    r.Middleware.Next()
    if r.Response.BufferLength() > 0 { // 业务已自行写回内容
        return
    }
    var (
        err = r.GetError()
        res = r.GetHandlerResponse()
    )
    if err != nil {
        code := gerror.Code(err) // 业务码在错误链上则原样透出
        g.Log().Errorf(r.Context(), "handler error: %+v", err)
        r.Response.WriteJson(Response{Code: code.Code(), Message: err.Error()})
        return
    }
    r.Response.WriteJson(Response{Code: 0, Message: "OK", Data: res})
}

mains.Use(middleware.HandlerResponse) 后,所有规范路由的返回都被包装,出错路径统一兜底,不再出现裸堆栈或空响应。

错误码常量:gcode 与 gerror

GoFrame 的错误码模型是 gcode.Code 接口,gerror 提供带错误码的错误创建与包装:

package code

import "github.com/gogf/gf/v2/errors/gcode"

// 官方约定:<1000 为框架预留,业务错误码请使用 >1000
var (
    UserNotExist    = gcode.New(1001, "用户不存在", nil)
    UserPasswordErr = gcode.New(1002, "用户名或密码错误", nil)
    ArticleNotFound = gcode.New(2001, "文章不存在", nil)
)
package service

import (
    "github.com/gogf/gf/v2/errors/gerror"
    "project/internal/code"
)

func Login(ctx context.Context, name, pass string) error {
    user := GetUserByName(ctx, name)
    if user == nil {
        return gerror.NewCode(code.UserNotExist) // 业务层只抛业务码
    }
    return nil
}

注意点

  • 统一中间件模式下,handler 只要 return res, nilreturn nil, err
  • HTTP 状态码与业务码解耦:业务失败常返回 200 + 非零 code;需要 401/404 语义时在中间件按错误码映射状态码;流式响应/已写缓冲的请求不要重复包装。

小结

统一响应 = 一个全局后置中间件 + {code,message,data};错误码 = gcode 常量 + gerror 抛出。二者配合后业务层只关心“抛什么业务码”,传输层永远输出稳定结构。默认结构细节以官方文档 goframe.org 为准。

笔记加载中…