yun 8f50c2ce9b 适配 errorx v1.2:错误值不持有 ctx,改用 errors.As + GetCode/Msg(ctx)
- response.go: errorx.As/val.Code() 换成 errors.As(errorx.ErrorInterface) 取
  GetCode(),文案改用 Msg(ctx) 按请求语言渲染(errorx v1.2 起错误值只保存语言,
  渲染时再传 ctx)。
- FormatMessage: langx v0.1 起未知 key 的默认码从 200 变成 -1,命中默认码时
  回落到 SetDefaultSuccessCode,保持升级前 code:200 的行为。
- go.mod: github.com/yuninks/errorx v1.2.0 / github.com/yuninks/langx v0.1.0。
2026-10-02 22:53:10 +08:00
2026-09-19 21:41:50 +08:00
2026-09-19 01:31:34 +08:00
2026-09-19 01:31:34 +08:00
2026-09-19 01:31:34 +08:00
2026-09-19 01:31:34 +08:00
2026-09-19 01:31:34 +08:00
2026-09-19 01:31:34 +08:00
2026-09-19 01:31:34 +08:00

responsex

API 响应封装组件,按需加载:核心包不依赖任何 Web/ORM/追踪框架, 用到哪个框架才 import 哪个适配包。

功能

  1. API 统一响应封装(code / message / data / pagination / trace_id)
  2. 支持多语言的错误码与错误提示(基于 langx)
  3. gin 响应体验优化(responsex/gin)
  4. go-zero trace_id 接入(responsex/gozerotrace,可选)
  5. GORM 分页辅助(responsex/gormx,可选)

模块与按需加载

本仓库是多模块结构,每个模块独立 go.mod,依赖互不牵扯:

模块 import 路径 依赖 适用场景
核心 code.yun.ink/pkg/responsex langx、errorx 任意 HTTP 框架
gin 适配 code.yun.ink/pkg/responsex/gin gin、核心 gin 项目
go-zero trace code.yun.ink/pkg/responsex/gozerotrace go-zero、核心 需要 go-zero trace_id
GORM 分页 code.yun.ink/pkg/responsex/gormx gorm 需要分页偏移

实测依赖隔离效果(go list -deps,外部包数 / 是否引入 go-zero):

消费场景 模块图 外部包 go-zero gin gorm
只用核心包 4 4 ✗ ✗ ✗
核心 + gin 69 57 ✗ ✓ ✗
核心 + gin + gorm 82 69 ✗ ✓ ✓
核心 + gin + gozerotrace 174 210 ✓ ✓ ✗

关键点:不 import gozerotrace 就不会下载、不会链接 go-zero (含 OpenTelemetry / gRPC / zipkin / jaeger 等一整棵依赖树)。

快速开始

纯 gin(推荐)

import (
	"code.yun.ink/pkg/responsex"
	ginx "code.yun.ink/pkg/responsex/gin"
	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.New()
	r.Use(ginx.Middleware()) // 桥接 trace_id 与 Accept-Language

	r.GET("/ping", func(c *gin.Context) {
		c.Set("trace_id", "xxx")      // 有就自动出现在响应里
		ginx.Success(c, gin.H{"pong": true})
	})

	r.GET("/fail", func(c *gin.Context) {
		ginx.ErrorStr(c, "参数异常,请检查参数")
	})

	r.Run()
}

ginx.Middleware() 做了两件事:

  1. 把 gin 的 c.Set("trace_id", ...)(或 X-Request-Id 请求头)桥接到标准 context; 没有它,trace_id 不会出现在响应里(gin 的 c.Value() 读不到 c.Set() 的值)。
  2. 把 Accept-Language 写入语言 context,核心包据此翻译文案。

接入 go-zero 的 trace_id

import _ "code.yun.ink/pkg/responsex/gozerotrace" // 只需这一行

导入后 go-zero 的 OpenTelemetry trace_id 会被自动读取,业务代码无需改动。 (纯 gin 项目如果自己用 c.Set("trace_id", ...) 注入,可以不要这个包。)

GORM 分页

import "code.yun.ink/pkg/responsex/gormx"

var list []User
gormx.GetDbOffset(db, page, size).Find(&list)

respgin.SuccessWithPage(c, list, responsex.GetPage(page, size, total))

不使用 gin 的其它框架

核心包只依赖标准库的 context 与 http.ResponseWriter:

responsex.Success(r.Context(), w, data)
responsex.Error(r.Context(), w, err)

多语言

  1. 错误码/文案注册(langx / errorx):
var ErrParamsInvalid = errorx.NewCode("params_invalid", 40001, "参数异常")

// 或按文件注册:code.json 为 map[string]int,其它 json 文件名为语言名
langx.RegisterDir("./langs")
  1. 输出:
responsex.Error(ctx, w, ErrParamsInvalid.New(ctx)) // 自动带业务码与译文
responsex.FormatMessage(ctx, w, "welcome", map[string]string{"name": "Yun"}, data)
ginx.MsgKV(c, "welcome", "name", "Yun")
  1. 成功文案:默认 请求成功,可用两种方式覆盖:
// 方式一:全局/单次指定
responsex.InitOptions(responsex.SetDefaultSuccessMessage("操作成功"))

// 方式二:注册专用 key "responsex_success",按请求语言输出
langx.AppendTrans("zh", map[string]string{"responsex_success": "请求成功"})
langx.AppendTrans("en", map[string]string{"responsex_success": "success"})

注意:responsex_success 是专用 key。不要用 success,该 key 已被 errorx 预注册。

trace_id 解析顺序

  1. 已注册的驱动(如 go-zero 适配包);
  2. 标准 ctx key responsex.CtxTraceIDKey(值为 "trace_id");
  3. 取不到则响应中不出现 trace_id 字段。

框架适配包通过 responsex.RegisterTraceDriver 注册,业务代码一般无需调用。 需要自定义来源时:

responsex.RegisterTraceDriver(func(ctx context.Context) string {
	return myTracer.IDFrom(ctx)
})

主要 API

核心(responsex):

  • 响应:Success、SuccessWithPage、Error、ErrorWithData、ErrorStr、FormatMessage、ResponseCtx
  • 选项:SetCode、SetMessage、SetData、SetPage、SetHttpStatusCode、SetHeader(s)、SetIgnoreLog、SetLogger、SetIgnoreTrace、SetDefaultSuccessCode、SetDefaultErrorCode、SetDefaultSuccessMessage
  • 分页:GetOffset、GetPage、Pagination
  • trace:SetTraceID、TraceID、RegisterTraceDriver、CtxTraceIDKey、SuccessMessageCtx

gin(ginx):Middleware、Success、SuccessWithPage、Error、ErrorWithData、ErrorStr、Custom、MsgMapData、MsgKV

gormx:GetDbOffset gozerotrace:空导入即注册

开发

本仓库是多模块,本地开发建议在根目录建 go.work(已 gitignore,勿提交):

go 1.22.4

use (
	.
	./gin
	./gormx
	./gozerotrace
)

运行测试:

go test ./...              # 需要 go.work;否则分别进入各模块执行
cd gin && go test ./...
cd gormx && go test ./...
cd gozerotrace && go test ./...

校验依赖隔离(在核心模块根目录执行,应无任何框架包):

go list -deps code.yun.ink/pkg/responsex | grep -E 'gin-gonic|gorm.io|zeromicro|opentelemetry'

发布(tag 规则)

子模块必须带目录前缀的 tag,否则 proxy 不认:

模块 tag 说明
核心 v1.0.2 根目录
gin gin/v1.0.2 子模块
gormx gormx/v1.0.2 子模块
gozerotrace gozerotrace/v1.0.2 子模块

发布顺序(重要):Go 无法 require 本地未发布的模块,所以必须 先推子模块 tag,最后再改根 go.mod 并发布根版本。

v0.0.4 → v1.x 迁移

gin 适配层从根包移到了子模块,并改名为 ginx:

旧(v0.0.4,根包) 新(v1.x)
responsex.GinError ginx.Error
responsex.GinErrorData ginx.ErrorWithData
responsex.GinErrorStr ginx.ErrorStr
responsex.GinSuccess ginx.Success
responsex.GinSuccessWithPage ginx.SuccessWithPage
responsex.GinOptions ginx.Custom
responsex.GinMsgMapData ginx.MsgMapData
responsex.GinMsgKV ginx.MsgKV

新增的 ops ...Option 是变参,旧调用点语义不变;只需把 import 与函数名改掉, 并在路由上挂一次 ginx.Middleware()。

S
Description
No description provided
Readme
72 KiB
Languages
Go 100%