Skip to content

成套工具箱 kit

TIP

  1. 服务端没有 common / utils 目录,这是 Go 社区共识,因为它容易成为全局依赖洼地,极易诱发循环依赖,或者变成代码垃圾抽屉;

  2. 我们转而使用 internal/kit(成套工具)、internal/infra(基础设施),还有外层不依赖任何基础设施的 pkgpkg/util 等粒度更细、更明确的包名代替。

kit 区别于 pkg,它可以随便依赖基础设施(如数据库、配置),同时着重 成套 概念,表示里边的东西并不散乱;目前 kit 里边只有三样,但都很常用。

HTTP 统一响应

响应函数作用
httpx.Fail向响应体写入统一失败响应数据
httpx.Success向响应体写入统一成功响应数据

两个函数可接受相同的 函数式选项;两者主要区别是:失败数据的 code=1,成功数据的 code=0

go
// {code: 0, time: 1788262624}
httpx.Success(c)

// {code: 10001, time: 1788262624}
httpx.Success(c, httpx.WithCode(10001))

// {code: 0, time: 1788262624, message: "当前页面配置项更新成功"}
httpx.Success(c, httpx.WithMessage("当前页面配置项更新成功"))

// {code: 0, time: 1788262624, data: { list: [], total: 2 }}
httpx.Success(c, httpx.WithData(gin.H{"list": list, "total": total}))

// Fail 默认 code: 1
httpx.Fail(c, httpx.WithMessage("参数错误: " + err.Error()))

// Fail 可以接受和 Success 相同的函数式选项
httpx.Fail(c, httpx.WithCode(10001), httpx.WithMessage("记录已存在"), httpx.WithData(gin.H{"name": name}))
选项函数一览
函数说明
WithCode(code int)自定义业务码
WithMessage(msg string)自定义消息
WithData(data any)自定义附带数据
链式用法

还支持以链式调用的方法向响应体写入数据,一般只用于复杂拼装场景:

go
httpx.New(c).Code(0).Message("ok").Data(x).Send()

数据绑定扩展

三绑定 bindx.ShouldBindTri

用于将单份原始请求体同时绑定至多个对象,自动完成数据验证、XSS 代码清洗。

go
var tri bindx.Tri[model.Admin]
if err := bindx.ShouldBindTri(body, &tri); err != nil {
    httpx.Fail(c, httpx.WithMessage("参数错误: "+err.Error()))
    return
}
  1. 自动完成 数据验证,用法和 Ginc.ShouldBindJSON 一致,可参考:Gin模型绑定与验证文档 | 所有可用的验证Tag | go-playground/validator
  2. 自动按结构体字段的 xss tag 清洗 XSS 代码,可参考:反 XSS
  3. 可将单份请求数据,同时绑定到 DTO、Model、Map,然后通过 tri.Modeltri.Map 访问。

自定义 DTO

一般不需要自定义 DTO,直接使用数据模型承担 DTO 的职责,即直接在数据模型上定义验证的 tag、反 XSS 的 tag 等。

除非请求对象确实和数据模型差异太多,那么可以如下自定义 DTO:

go
var tri bindx.Tri[model.Admin]
tri.DTO = &dto.AdminUpdateRequest{}
if err := bindx.ShouldBindTri(body, &tri); err != nil {
    httpx.Fail(c, httpx.WithMessage("参数错误: "+err.Error()))
    return
}

是的,一行;在 internal/dto 定义你的 DTO 之后,加如上一行代码,三绑定就会以 DTO 作为绑定与校验目标

为什么需要三绑定

  1. 需要 DTO 的场景,一般需要先绑定到 DTO 再转为模型,三绑可以省略此步骤。
  2. 直接备好 map,以配合仓储层实现所见即所得的数据更新(能区分前端传递 null(清空)未传(不更新)、能直接更新值为零值的字段)。
  3. 统一清理 XSS 代码。
  4. 统一数据绑定与验证。

三绑定的代价

三绑定实现经过仔细打磨,代价很小:

  1. map 初始化只解析原始请求体中的 key,不解析值(值从 DTO模型 复制,值已类型化(如 jsonb*datatypes.JSON)。
  2. 结构体标签解析带全局缓存机制。
  3. 只需接受一次原始请求体,供所有操作消费。
  4. 若已自定义 DTO,模型的值直接从 DTO 拷贝而不是重复解析(未定义 DTO 则数据直接绑定到模型,拷贝过程也不需要)。

一般在更新、创建场景使用三绑定。

URL扩展

目前主要提供了 FullURL 函数,它用于获取静态资源的完整 URL,示例如下:

go
// http://localhost:8080/static/images/avatar.png
urlx.FullURL(c, "/static/images/avatar.png")

规则:

  1. 入参为空 → 返回空串;
  2. 已是完整 URL → 原样返回(前缀 http://https://data:);
  3. 前缀优先取配置 cdn.url;未配置时回退到当前站点的 httpx.BaseURL(c)
  4. 使用 CDN 且配置了 cdn.url_params 时自动追加参数。

TIP

前端也有相同作用的 fullURL 公共函数:获取静态资源的完整 URL