go zero 模板定制
go-zero 提供的 goctl 工具能够根据 API 定义自动生成服务框架代码,但在实际项目中,我们往往需要根据团队规范和业务逻辑定制生成的代码。
例如,我们刚刚的使用错误管理,我们需要在handler中返回的错误信息。
一、 go-zero 模板介绍
1.1 模板原理
goctl 的代码生成是基于 Go 标准库的 text/template 实现的,它通过对模板文件中的占位符进行替换,生成最终的代码文件。模板系统使用了以下几个核心概念:
- 变量:通过
{{.VariableName}}语法在模板中使用 - 条件语句:如
{{if .Condition}}...{{else}}...{{end}} - 循环:如
{{range .Items}}...{{end}} - 函数:如
{{.FunctionName}}
1.2 模板文件组织
goctl 的模板文件按照不同的服务类型进行组织,主要包括:
``` ├─api # API 服务相关模板 ├─docker # Docker 相关配置模板 ├─gateway # 网关服务模板 ├─kube # Kubernetes 配置模板 ├─model # 数据模型相关模板 ├─mongo # MongoDB 相关模板 ├─newapi # 新版 API 服务模板 └─rpc # RPC 服务相关模板 ```
每种服务类型的模板又包含多个子模板,以 API 服务为例:
``` api/ ├─handler.tpl # 处理 HTTP 请求的 handler ├─logic.tpl # 业务逻辑处理 ├─etc.tpl # 配置文件 ├─main.tpl # 主入口文件 └─... # 其他模板 ```
二、初始化模板文件
首先,我们需要初始化模板文件。通过运行goctl template init 命令,可以将模板文件下载到本地。
sql2pb>goctl template init -home ./
- home 是存储模板的路径
执行命令后,指定目录中会生成以下文件和文件夹结构:
├─api
├─docker
├─gateway
├─kube
├─model
├─mongo
├─newapi
└─rpc
这些目录对应了go zero中不同模块的模板,提供了服务生成的基本结构。
2.2 模板变量说明
在修改模板前,我们需要了解模板中可以使用的变量。以 handler.tpl 为例,常用的变量包括:
| 变量名 | 说明 |
|---|---|
.PkgName | 包名 |
.ImportPackages | 需要导入的包 |
.HandlerName | 处理函数名称 |
.LogicName | 逻辑层包名 |
.LogicType | 逻辑结构体名称 |
.RequestType | 请求结构体类型 |
.HasRequest | 是否有请求参数 |
.HasResp | 是否有响应结构体 |
.Call | 调用逻辑层的方法名 |
.HasDoc | 是否有文档注释 |
.Doc | 文档注释内容 |
三、修改模板
3.1 错误处理定制示例
这里我们演示如何修改handler.tpl模板,以便在处理请求时返回更合适的错误信息。
打开handler.tpl文件,可以看到生成的代码框架。我们将在处理请求时引入新的错误处理逻辑,使其更符合业务需求。以下是修改后的模板代码:
package {{.PkgName}}
import (
"net/http"
xhttp "github.com/zeromicro/x/http" //导入zeromicro库
"github.com/zeromicro/go zero/rest/httpx"
{{.ImportPackages}}
)
{{if .HasDoc}}{{.Doc}}{{end}}
func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
{{if .HasRequest}}var req types.{{.RequestType}}
if err := httpx.Parse(r, &req); err != nil {
//httpx.ErrorCtx(r.Context(), w, err)
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
return
}
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
{{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
if err != nil {
//httpx.ErrorCtx(r.Context(), w, err)
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
} else {
{{if .HasResp}}xhttp.JsonBaseResponseCtx(r.Context(), w, resp){{else}}httpx.Ok(w){{end}}
}
}
}
修改说明
- 我们使用了 xhttp.JsonBaseResponseCtx 方法来返回错误信息,这样可以确保客户端得到统一风格的错误响应。
- 处理请求的逻辑保留了原有结构,但在错误处理的方式上作了调整,以更好地符合业务需求。
自定义规则:
- 在 goctl 提供的有效数据范围内修改,即不支持外部变量
- 不支持新增模板文件
- 不支持变量修改
3.2 根据模板生成代码
完成模板的修改后,可以使用 goctl命令来生成新代码。以下是命令示例:
goctl api go --api user.api --dir ./ --home ../sql2pb
--home 指定我们刚刚下载的模板路径, 默认值为 ${HOME}/.goctl
在代码生成完成后,我们可以查看生成的 handler 文件,以确认我们的修改是否成功。新的 handler 文件应当能够根据我们自定义的模板返回整洁的错误响应。

四、高级模板定制技巧
4.1 条件模板生成
我们可以根据 API 定义中的特定注解或标签,动态调整生成的代码:
{{if .HasAuth}}
// 添加认证中间件
server.Use(middleware.Auth())
{{end}}
4.2 自定义函数
goctl 允许在模板中使用自定义函数,例如:
{{$tableName := .Table | snakeCase}} // 转换为蛇形命名
要实现这一点,需要在 goctl 命令中注册自定义函数。
4.3 多环境模板
为不同的环境(如开发、测试、生产)准备不同的模板,可以通过修改 goctl 命令的参数来实现:
goctl api go --api user.api --dir ./ --home ../templates/dev # 开发环境模板
goctl api go --api user.api --dir ./ --home ../templates/prod # 生产环境模板

761

被折叠的 条评论
为什么被折叠?



