模板定制化

概述

goctl 代码生成是基于 go 的模板去实现数据驱动的,虽然目前 goctl 的代码生成可以满足一部分代码生成功能,但是模板的自定义可以更加丰富代码生成。

模板指令可参考 goctl template

示例

场景

实现统一格式的 body 响应,格式如下:

  1. {
  2. "code": 0,
  3. "msg": "OK",
  4. "data": {} // ①
  5. }

① 实际响应数据

模板定制化 - 图1tip

go-zero生成的代码没有对其进行处理

准备工作

我们提前在 modulegreet 的工程下的 response 包中写一个 Response 方法,目录树类似如下:

  1. greet
  2. ├── response
  3. └── response.go
  4. └── xxx...

代码如下

  1. package response
  2. import (
  3. "net/http"
  4. "github.com/zeromicro/go-zero/rest/httpx"
  5. )
  6. type Body struct {
  7. Code int `json:"code"`
  8. Msg string `json:"msg"`
  9. Data interface{} `json:"data,omitempty"`
  10. }
  11. func Response(w http.ResponseWriter, resp interface{}, err error) {
  12. var body Body
  13. if err != nil {
  14. body.Code = -1
  15. body.Msg = err.Error()
  16. } else {
  17. body.Msg = "OK"
  18. body.Data = resp
  19. }
  20. httpx.OkJson(w, body)
  21. }

修改 handler 模板

  1. $ vim ~/.goctl/${goctl版本号}/api/handler.tpl

将模板替换为以下内容

  1. package handler
  2. import (
  3. "net/http"
  4. "greet/response"// ①
  5. {{.ImportPackages}}
  6. )
  7. func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
  8. return func(w http.ResponseWriter, r *http.Request) {
  9. {{if .HasRequest}}var req types.{{.RequestType}}
  10. if err := httpx.Parse(r, &req); err != nil {
  11. httpx.Error(w, err)
  12. return
  13. }{{end}}
  14. l := logic.New{{.LogicType}}(r.Context(), svcCtx)
  15. {{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
  16. {{if .HasResp}}response.Response(w, resp, err){{else}}response.Response(w, nil, err){{end}}//②
  17. }
  18. }

① 替换为你真实的response包名,仅供参考

② 自定义模板内容

模板定制化 - 图21.如果本地没有~/.goctl/${goctl版本号}/api/handler.tpl文件,可以通过模板初始化命令goctl template init进行初始化

修改模板前后对比

  • 修改前
  1. func GreetHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  2. return func(w http.ResponseWriter, r *http.Request) {
  3. var req types.Request
  4. if err := httpx.Parse(r, &req); err != nil {
  5. httpx.Error(w, err)
  6. return
  7. }
  8. l := logic.NewGreetLogic(r.Context(), svcCtx)
  9. resp, err := l.Greet(&req)
  10. // 以下内容将被自定义模板替换
  11. if err != nil {
  12. httpx.Error(w, err)
  13. } else {
  14. httpx.OkJson(w, resp)
  15. }
  16. }
  17. }
  • 修改后
  1. func GreetHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  2. return func(w http.ResponseWriter, r *http.Request) {
  3. var req types.Request
  4. if err := httpx.Parse(r, &req); err != nil {
  5. httpx.Error(w, err)
  6. return
  7. }
  8. l := logic.NewGreetLogic(r.Context(), svcCtx)
  9. resp, err := l.Greet(&req)
  10. response.Response(w, resp, err)
  11. }
  12. }

修改模板前后响应体对比

  • 修改前
  1. {
  2. "message": "Hello go-zero!"
  3. }
  • 修改后
  1. {
  2. "code": 0,
  3. "msg": "OK",
  4. "data": {
  5. "message": "Hello go-zero!"
  6. }
  7. }

模板自定义规则

  1. 在 goctl 提供的有效数据范围内修改,即不支持外部变量
  2. 不支持新增模板文件
  3. 不支持变量修改

参考文献