Appearance
成套工具箱 kit
TIP
服务端没有
common / utils目录,这是 Go 社区共识,因为它容易成为全局依赖洼地,极易诱发循环依赖,或者变成代码垃圾抽屉;我们转而使用
internal/kit(成套工具)、internal/infra(基础设施),还有外层不依赖任何基础设施的pkg和pkg/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
}- 自动完成
数据验证,用法和Gin的c.ShouldBindJSON一致,可参考:Gin模型绑定与验证文档 | 所有可用的验证Tag | go-playground/validator - 自动按结构体字段的
xss tag清洗XSS代码,可参考:反 XSS - 可将单份请求数据,同时绑定到
DTO、Model、Map,然后通过tri.Model和tri.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 作为绑定与校验目标。
为什么需要三绑定
- 需要
DTO的场景,一般需要先绑定到DTO再转为模型,三绑可以省略此步骤。 - 直接备好
map,以配合仓储层实现所见即所得的数据更新(能区分前端传递null(清空)和未传(不更新)、能直接更新值为零值的字段)。 - 统一清理
XSS代码。 - 统一数据绑定与验证。
三绑定的代价
三绑定实现经过仔细打磨,代价很小:
map初始化只解析原始请求体中的key,不解析值(值从DTO或模型复制,值已类型化(如jsonb的*datatypes.JSON)。- 结构体标签解析带全局缓存机制。
- 只需接受一次原始请求体,供所有操作消费。
- 若已自定义
DTO,模型的值直接从DTO拷贝而不是重复解析(未定义DTO则数据直接绑定到模型,拷贝过程也不需要)。
一般在更新、创建场景使用三绑定。
URL扩展
目前主要提供了 FullURL 函数,它用于获取静态资源的完整 URL,示例如下:
go
// http://localhost:8080/static/images/avatar.png
urlx.FullURL(c, "/static/images/avatar.png")规则:
- 入参为空 → 返回空串;
- 已是完整 URL → 原样返回(前缀
http://、https://、data:); - 前缀优先取配置
cdn.url;未配置时回退到当前站点的httpx.BaseURL(c); - 使用
CDN且配置了cdn.url_params时自动追加参数。
TIP
前端也有相同作用的 fullURL 公共函数:获取静态资源的完整 URL
