模板定制化

概述

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

模板指令可参考 goctl template

示例

场景

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

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

① 实际响应数据

模板定制化 - 图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 := {{.LogicName}}.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. 不支持变量修改

模板变量

goctl api -o 代码生成模板

模板默认目录 ~/.goctl/${goctl-version}/newapi

api.tpl

  1. syntax = "v1"
  2. info (
  3. title: // TODO: add title
  4. desc: // TODO: add description
  5. author: "{{.gitUser}}"
  6. email: "{{.gitEmail}}"
  7. )
  8. type request {
  9. // TODO: add members here and delete this comment
  10. }
  11. type response {
  12. // TODO: add members here and delete this comment
  13. }
  14. service {{.serviceName}} {
  15. @handler GetUser // TODO: set handler name and delete this comment
  16. get /users/id/:userId(request) returns(response)
  17. @handler CreateUser // TODO: set handler name and delete this comment
  18. post /users/create(request)
  19. }

对应指令 goctl api -o

模板注入对象为 map[string]string

  1. map[string]string{
  2. "gitUser": getGitName(),
  3. "gitEmail": getGitEmail(),
  4. "serviceName": baseName + "-api",
  5. }
pipeline变量类型说明
.gitUserstringGit用户名
.gitEmailstringGit邮箱
.serviceNamestring服务名称

goctl api go 代码生成模板

对应指令 goctl api go ...

模板默认目录 ~/.goctl/${goctl-version}/api

config.tpl

  1. package config
  2. import {{.authImport}}
  3. type Config struct {
  4. rest.RestConf
  5. {{.auth}}
  6. {{.jwtTrans}}
  7. }

模板注入对象为 map[string]string

  1. map[string]string{
  2. "authImport": authImportStr,
  3. "auth": strings.Join(auths, "\n"),
  4. "jwtTrans": strings.Join(jwtTransList, "\n"),
  5. }
pipeline变量类型说明
.authImportstring认证导入
.authstring认证配置
.jwtTransstringJWT配置

etc.tpl

  1. Name: {{.serviceName}}
  2. Host: {{.host}}
  3. Port: {{.port}}

模板注入对象为 map[string]string

  1. map[string]string{
  2. "serviceName": service.Name,
  3. "host": host,
  4. "port": port,
  5. }
pipeline变量类型说明
.serviceNamestring服务名称
.hoststring主机地址
.portstring端口号

handler.tpl

  1. package {{.PkgName}}
  2. import (
  3. "net/http"
  4. "github.com/zeromicro/go-zero/rest/httpx"
  5. {{.ImportPackages}}
  6. )
  7. {{if .HasDoc}}{{.Doc}}{{end}}
  8. func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
  9. return func(w http.ResponseWriter, r *http.Request) {
  10. {{if .HasRequest}}var req types.{{.RequestType}}
  11. if err := httpx.Parse(r, &req); err != nil {
  12. httpx.ErrorCtx(r.Context(), w, err)
  13. return
  14. }
  15. {{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
  16. {{if .HasResp}}resp, {{end}}err := l.{{.Call}}({{if .HasRequest}}&req{{end}})
  17. if err != nil {
  18. httpx.ErrorCtx(r.Context(), w, err)
  19. } else {
  20. {{if .HasResp}}httpx.OkJsonCtx(r.Context(), w, resp){{else}}httpx.Ok(w){{end}}
  21. }
  22. }
  23. }

模板注入对象为 map[string]any

  1. map[string]any{
  2. "PkgName": pkgName,
  3. "ImportPackages": genHandlerImports(group, route, rootPkg),
  4. "HandlerName": handler,
  5. "RequestType": util.Title(route.RequestTypeName()),
  6. "LogicName": logicName,
  7. "LogicType": strings.Title(getLogicName(route)),
  8. "Call": strings.Title(strings.TrimSuffix(handler, "Handler")),
  9. "HasResp": len(route.ResponseTypeName()) > 0,
  10. "HasRequest": len(route.RequestTypeName()) > 0,
  11. "HasDoc": len(route.JoinedDoc()) > 0,
  12. "Doc": getDoc(route.JoinedDoc()),
  13. }
pipeline变量类型说明
.PkgNamestring包名
.ImportPackagesstring导入包
.HasDocbool是否有文档注释
.Docstring文档注释
.HandlerNamestringhandler 名称
.HasRequestbool是否有请求体
.RequestTypestring请求类型
.LogicNamestring逻辑包名称,默认为logic,如果有分组时为具体的group名称
.LogicTypestring逻辑对象type名称
.Callstringlogic 对象调用方法名称
.HasRespbool是否有响应体

logic.tpl

  1. package {{.pkgName}}
  2. import (
  3. {{.imports}}
  4. )
  5. type {{.logic}} struct {
  6. logx.Logger
  7. ctx context.Context
  8. svcCtx *svc.ServiceContext
  9. }
  10. {{if .hasDoc}}{{.doc}}{{end}}
  11. func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} {
  12. return &{{.logic}}{
  13. Logger: logx.WithContext(ctx),
  14. ctx: ctx,
  15. svcCtx: svcCtx,
  16. }
  17. }
  18. func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} {
  19. // todo: add your logic here and delete this line
  20. {{.returnString}}
  21. }

模板注入对象为 map[string]any

  1. map[string]any{
  2. "pkgName": subDir[strings.LastIndex(subDir, "/")+1:],
  3. "imports": imports,
  4. "logic": strings.Title(logic),
  5. "function": strings.Title(strings.TrimSuffix(logic, "Logic")),
  6. "responseType": responseString,
  7. "returnString": returnString,
  8. "request": requestString,
  9. "hasDoc": len(route.JoinedDoc()) > 0,
  10. "doc": getDoc(route.JoinedDoc()),
  11. }
pipeline变量类型说明
.pkgNamestring包名
.importsstring导入包
.logicstring逻辑结构体名称
.hasDocbool是否有文档注释
.docstring文档注释
.functionstringlogic 函数名称
.requeststring请求体表达式,包含参数名称,参数类型
.responseTypestring响应类型体表达式,包含参数名称,参数类型
.returnStringstring返回语句,返回的结构体

main.tpl

  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. {{.importPackages}}
  6. )
  7. var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
  8. func main() {
  9. flag.Parse()
  10. var c config.Config
  11. conf.MustLoad(*configFile, &c)
  12. server := rest.MustNewServer(c.RestConf)
  13. defer server.Stop()
  14. ctx := svc.NewServiceContext(c)
  15. handler.RegisterHandlers(server, ctx)
  16. fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
  17. server.Start()
  18. }

模板注入对象为 map[string]string

  1. map[string]string{
  2. "importPackages": genMainImports(rootPkg),
  3. "serviceName": configName,
  4. }
pipeline变量类型说明
.importPackagesstring导入包
.serviceNamestring服务名称

middleware.tpl

  1. package middleware
  2. import "net/http"
  3. type {{.name}} struct {
  4. }
  5. func New{{.name}}() *{{.name}} {
  6. return &{{.name}}{}
  7. }
  8. func (m *{{.name}})Handle(next http.HandlerFunc) http.HandlerFunc {
  9. return func(w http.ResponseWriter, r *http.Request) {
  10. // TODO generate middleware implement function, delete after code implementation
  11. // Passthrough to next handler if need
  12. next(w, r)
  13. }
  14. }

模板注入对象为 map[string]string

  1. map[string]string{
  2. "name": strings.Title(name),
  3. }
pipeline变量类型说明
.namestring中间件名称

svc.tpl

  1. package svc
  2. import (
  3. {{.configImport}}
  4. )
  5. type ServiceContext struct {
  6. Config {{.config}}
  7. {{.middleware}}
  8. }
  9. func NewServiceContext(c {{.config}}) *ServiceContext {
  10. return &ServiceContext{
  11. Config: c,
  12. {{.middlewareAssignment}}
  13. }
  14. }

模板注入对象为 map[string]string

  1. map[string]string{
  2. "configImport": configImport,
  3. "config": "config.Config",
  4. "middleware": middlewareStr,
  5. "middlewareAssignment": middlewareAssignment,
  6. }
pipeline变量类型说明
.configImportstringpkg 导入
.configstring配置结构体名称
.middlewarestring中间件字段
.middlewareAssignmentstring中间件赋值语句

type.tpl

  1. // Code generated by goctl. DO NOT EDIT.
  2. package types{{if .containsTime}}
  3. import (
  4. "time"
  5. ){{end}}
  6. {{.types}}

模板注入对象为 map[string]any

  1. map[string]any{
  2. "types": val,
  3. "containsTime": false,
  4. }
pipeline变量类型说明
.containsTimebool是否包含时间
.typesstring类型

goctl api new 代码生成模板

对应指令为 goctl api new ...

模板默认目录 ~/.goctl/${goctl-version}/newapi

api.tpl

  1. syntax = "v1"
  2. type Request {
  3. Name string `path:"name,options=you|me"`
  4. }
  5. type Response {
  6. Message string `json:"message"`
  7. }
  8. service {{.name}}-api {
  9. @handler {{.handler}}Handler
  10. get /from/:name(Request) returns (Response)
  11. }

模板注入对象 map[string]string

  1. map[string]string{
  2. "name": dirName,
  3. "handler": strings.Title(dirName),
  4. }
pipeline变量类型说明
.namestring服务名称
.handlerstring处理器名称

mongo 代码生成模板

模板默认目录 ~/.goctl/${goctl-version}/mongo

error.tpl

  1. package model
  2. import (
  3. "errors"
  4. "github.com/zeromicro/go-zero/core/stores/mon"
  5. )
  6. var (
  7. ErrNotFound = mon.ErrNotFound
  8. ErrInvalidObjectId = errors.New("invalid objectId")
  9. )

model.tpl

  1. // Code generated by goctl. DO NOT EDIT.
  2. package model
  3. import (
  4. "context"
  5. "time"
  6. {{if .Cache}}"github.com/zeromicro/go-zero/core/stores/monc"{{else}}"github.com/zeromicro/go-zero/core/stores/mon"{{end}}
  7. "go.mongodb.org/mongo-driver/bson"
  8. "go.mongodb.org/mongo-driver/bson/primitive"
  9. "go.mongodb.org/mongo-driver/mongo"
  10. )
  11. {{if .Cache}}var prefix{{.Type}}CacheKey = "cache:{{.lowerType}}:"{{end}}
  12. type {{.lowerType}}Model interface{
  13. Insert(ctx context.Context,data *{{.Type}}) error
  14. FindOne(ctx context.Context,id string) (*{{.Type}}, error)
  15. Update(ctx context.Context,data *{{.Type}}) (*mongo.UpdateResult, error)
  16. Delete(ctx context.Context,id string) (int64, error)
  17. }
  18. type default{{.Type}}Model struct {
  19. conn {{if .Cache}}*monc.Model{{else}}*mon.Model{{end}}
  20. }
  21. func newDefault{{.Type}}Model(conn {{if .Cache}}*monc.Model{{else}}*mon.Model{{end}}) *default{{.Type}}Model {
  22. return &default{{.Type}}Model{conn: conn}
  23. }
  24. func (m *default{{.Type}}Model) Insert(ctx context.Context, data *{{.Type}}) error {
  25. if data.ID.IsZero() {
  26. data.ID = primitive.NewObjectID()
  27. data.CreateAt = time.Now()
  28. data.UpdateAt = time.Now()
  29. }
  30. {{if .Cache}}key := prefix{{.Type}}CacheKey + data.ID.Hex(){{end}}
  31. _, err := m.conn.InsertOne(ctx, {{if .Cache}}key, {{end}} data)
  32. return err
  33. }
  34. func (m *default{{.Type}}Model) FindOne(ctx context.Context, id string) (*{{.Type}}, error) {
  35. oid, err := primitive.ObjectIDFromHex(id)
  36. if err != nil {
  37. return nil, ErrInvalidObjectId
  38. }
  39. var data {{.Type}}
  40. {{if .Cache}}key := prefix{{.Type}}CacheKey + id{{end}}
  41. err = m.conn.FindOne(ctx, {{if .Cache}}key, {{end}}&data, bson.M{"_id": oid})
  42. switch err {
  43. case nil:
  44. return &data, nil
  45. case {{if .Cache}}monc{{else}}mon{{end}}.ErrNotFound:
  46. return nil, ErrNotFound
  47. default:
  48. return nil, err
  49. }
  50. }
  51. func (m *default{{.Type}}Model) Update(ctx context.Context, data *{{.Type}}) (*mongo.UpdateResult, error) {
  52. data.UpdateAt = time.Now()
  53. {{if .Cache}}key := prefix{{.Type}}CacheKey + data.ID.Hex(){{end}}
  54. res, err := m.conn.UpdateOne(ctx, {{if .Cache}}key, {{end}}bson.M{"_id": data.ID}, bson.M{"$set": data})
  55. return res, err
  56. }
  57. func (m *default{{.Type}}Model) Delete(ctx context.Context, id string) (int64, error) {
  58. oid, err := primitive.ObjectIDFromHex(id)
  59. if err != nil {
  60. return 0, ErrInvalidObjectId
  61. }
  62. {{if .Cache}}key := prefix{{.Type}}CacheKey +id{{end}}
  63. res, err := m.conn.DeleteOne(ctx, {{if .Cache}}key, {{end}}bson.M{"_id": oid})
  64. return res, err
  65. }

模板注入对象为 map[string]any

  1. map[string]any{
  2. "Type": stringx.From(t).Title(),
  3. "lowerType": stringx.From(t).Untitle(),
  4. "Cache": ctx.Cache,
  5. }
pipeline变量类型说明
.Cachebool是否启用缓存
.Typestring模型类型名称
.lowerTypestring小写模型类型名称

model_custom.tpl

  1. package model
  2. {{if .Cache}}import (
  3. "github.com/zeromicro/go-zero/core/stores/cache"
  4. "github.com/zeromicro/go-zero/core/stores/monc"
  5. ){{else}}import "github.com/zeromicro/go-zero/core/stores/mon"{{end}}
  6. {{if .Easy}}
  7. const {{.Type}}CollectionName = "{{.snakeType}}"
  8. {{end}}
  9. var _ {{.Type}}Model = (*custom{{.Type}}Model)(nil)
  10. type (
  11. // {{.Type}}Model is an interface to be customized, add more methods here,
  12. // and implement the added methods in custom{{.Type}}Model.
  13. {{.Type}}Model interface {
  14. {{.lowerType}}Model
  15. }
  16. custom{{.Type}}Model struct {
  17. *default{{.Type}}Model
  18. }
  19. )
  20. // New{{.Type}}Model returns a model for the mongo.
  21. {{if .Easy}}func New{{.Type}}Model(url, db string{{if .Cache}}, c cache.CacheConf{{end}}) {{.Type}}Model {
  22. conn := {{if .Cache}}monc{{else}}mon{{end}}.MustNewModel(url, db, {{.Type}}CollectionName{{if .Cache}}, c{{end}})
  23. return &custom{{.Type}}Model{
  24. default{{.Type}}Model: newDefault{{.Type}}Model(conn),
  25. }
  26. }{{else}}func New{{.Type}}Model(url, db, collection string{{if .Cache}}, c cache.CacheConf{{end}}) {{.Type}}Model {
  27. conn := {{if .Cache}}monc{{else}}mon{{end}}.MustNewModel(url, db, collection{{if .Cache}}, c{{end}})
  28. return &custom{{.Type}}Model{
  29. default{{.Type}}Model: newDefault{{.Type}}Model(conn),
  30. }
  31. }{{end}}

模板注入对象为 map[string]any

  1. map[string]any{
  2. "Type": stringx.From(t).Title(),
  3. "lowerType": stringx.From(t).Untitle(),
  4. "snakeType": stringx.From(t).ToSnake(),
  5. "Cache": ctx.Cache,
  6. "Easy": ctx.Easy,
  7. }
pipeline变量类型说明
.Cachebool是否启用缓存
.Easybool是否简易模式
.Typestring模型类型名称
.snakeTypestring蛇形模型类型名称
.lowerTypestring小写模型类型名称

types.tpl

  1. package model
  2. import (
  3. "time"
  4. "go.mongodb.org/mongo-driver/bson/primitive"
  5. )
  6. type {{.Type}} struct {
  7. ID primitive.ObjectID `bson:"_id,omitempty" json:"id,omitempty"`
  8. // TODO: Fill your own fields
  9. UpdateAt time.Time `bson:"updateAt,omitempty" json:"updateAt,omitempty"`
  10. CreateAt time.Time `bson:"createAt,omitempty" json:"createAt,omitempty"`
  11. }

模板注入对象为 map[string]any

  1. map[string]any{
  2. "Type": stringx.From(t).Title(),
  3. }
pipeline变量类型说明
.Typestring模型类型名称

mysql 代码生成模板

模板默认目录 ~/.goctl/${goctl-version}/model

customized.tpl

空模板,方便自定义

模板注入对象 map[string]any

  1. mmap[string]any{
  2. "withCache": withCache,
  3. "containsIndexCache": table.ContainsUniqueCacheKey,
  4. "upperStartCamelObject": camel,
  5. "lowerStartCamelObject": stringx.From(camel).Untitle(),
  6. "lowerStartCamelPrimaryKey": util.EscapeGolangKeyword(stringx.From(table.PrimaryKey.Name.ToCamel()).Untitle()),
  7. "upperStartCamelPrimaryKey": table.PrimaryKey.Name.ToCamel(),
  8. "primaryKeyDataType": table.PrimaryKey.DataType,
  9. "originalPrimaryKey": wrapWithRawString(table.PrimaryKey.Name.Source(), postgreSql),
  10. "primaryCacheKey": table.PrimaryCacheKey.DataKeyExpression,
  11. "primaryKeyVariable": table.PrimaryCacheKey.KeyLeft,
  12. "keys": strings.Join(keys, "\n"),
  13. "keyValues": strings.Join(keyVars, ", "),
  14. "expression": strings.Join(expressions, ", "),
  15. "expressionValues": strings.Join(expressionValues, ", "),
  16. "postgreSql": postgreSql,
  17. "fields": fields,
  18. "data": table,
  19. }

delete.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
  2. {{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, {{.lowerStartCamelPrimaryKey}})
  3. if err!=nil{
  4. return err
  5. }
  6. {{end}} {{.keys}}
  7. _, err {{if .containsIndexCache}}={{else}}:={{end}} m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
  8. query := fmt.Sprintf("delete from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table)
  9. return conn.ExecCtx(ctx, query, {{.lowerStartCamelPrimaryKey}})
  10. }, {{.keyValues}}){{else}}query := fmt.Sprintf("delete from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table)
  11. _,err:=m.conn.ExecCtx(ctx, query, {{.lowerStartCamelPrimaryKey}}){{end}}
  12. return err
  13. }

模板注入对象为 map[string]any

  1. map[string]any{
  2. "upperStartCamelObject": camel,
  3. "withCache": withCache,
  4. "containsIndexCache": table.ContainsUniqueCacheKey,
  5. "lowerStartCamelPrimaryKey": util.EscapeGolangKeyword(stringx.From(table.PrimaryKey.Name.ToCamel()).Untitle()),
  6. "dataType": table.PrimaryKey.DataType,
  7. "keys": strings.Join(keys, "\n"),
  8. "originalPrimaryKey": wrapWithRawString(table.PrimaryKey.Name.Source(), postgreSql),
  9. "keyValues": strings.Join(keyVars, ", "),
  10. "postgreSql": postgreSql,
  11. "data": table,
  12. }
pipeline变量类型说明
.upperStartCamelObjectstring对象名称的首字母大写形式
.lowerStartCamelPrimaryKeystring主键变量名的首字母小写形式
.dataTypestring主键数据类型
.withCachebool是否启用缓存
.containsIndexCachebool是否包含索引缓存逻辑
.keysstring在包含索引缓存时,用于查找数据的逻辑
.keyValuesstring在缓存中找到的键值对
.postgreSqlbool是否使用 PostgreSQL
.originalPrimaryKeystring原始主键名称

err.tpl

  1. package {{.pkg}}
  2. import "github.com/zeromicro/go-zero/core/stores/sqlx"
  3. var ErrNotFound = sqlx.ErrNotFound

模板注入对象为 map[string]any

  1. map[string]any{
  2. "pkg": g.pkg,
  3. }
pipeline变量类型说明
.pkgstring包名

field.tpl

  1. {{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}

模板注入对象为 map[string]any

  1. map[string]any{
  2. "name": util.SafeString(field.Name.ToCamel()),
  3. "type": field.DataType,
  4. "tag": tag,
  5. "hasComment": field.Comment != "",
  6. "comment": field.Comment,
  7. "data": table,
  8. }
pipeline变量类型说明
.namestring名称
.typestring类型
.tagstring标签
.hasCommentbool是否有注释
.commentstring注释内容 (可选)

find-one.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) {
  2. {{if .withCache}}{{.cacheKey}}
  3. var resp {{.upperStartCamelObject}}
  4. err := m.QueryRowCtx(ctx, &resp, {{.cacheKeyVariable}}, func(ctx context.Context, conn sqlx.SqlConn, v any) error {
  5. query := fmt.Sprintf("select %s from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}} limit 1", {{.lowerStartCamelObject}}Rows, m.table)
  6. return conn.QueryRowCtx(ctx, v, query, {{.lowerStartCamelPrimaryKey}})
  7. })
  8. switch err {
  9. case nil:
  10. return &resp, nil
  11. case sqlc.ErrNotFound:
  12. return nil, ErrNotFound
  13. default:
  14. return nil, err
  15. }{{else}}query := fmt.Sprintf("select %s from %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}} limit 1", {{.lowerStartCamelObject}}Rows, m.table)
  16. var resp {{.upperStartCamelObject}}
  17. err := m.conn.QueryRowCtx(ctx, &resp, query, {{.lowerStartCamelPrimaryKey}})
  18. switch err {
  19. case nil:
  20. return &resp, nil
  21. case sqlx.ErrNotFound:
  22. return nil, ErrNotFound
  23. default:
  24. return nil, err
  25. }{{end}}
  26. }

模板注入对象为 map[string]any

  1. map[string]any{
  2. "withCache": withCache,
  3. "upperStartCamelObject": camel,
  4. "lowerStartCamelObject": stringx.From(camel).Untitle(),
  5. "originalPrimaryKey": wrapWithRawString(table.PrimaryKey.Name.Source(), postgreSql),
  6. "lowerStartCamelPrimaryKey": util.EscapeGolangKeyword(stringx.From(table.PrimaryKey.Name.ToCamel()).Untitle()),
  7. "dataType": table.PrimaryKey.DataType,
  8. "cacheKey": table.PrimaryCacheKey.KeyExpression,
  9. "cacheKeyVariable": table.PrimaryCacheKey.KeyLeft,
  10. "postgreSql": postgreSql,
  11. "data": table,
  12. }
pipeline变量类型说明
.upperStartCamelObjectstring对象名称的首字母大写形式
.lowerStartCamelPrimaryKeystring主键变量名的首字母小写形式
.dataTypestring主键数据类型
.withCachebool是否启用缓存
.cacheKeystring缓存键
.cacheKeyVariablestring缓存键变量
.postgreSqlbool是否使用 PostgreSQL
.originalPrimaryKeystring原始主键名称
.lowerStartCamelObjectstring对象名称的首字母小写形式

find-one-by-field.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error) {
  2. {{if .withCache}}{{.cacheKey}}
  3. var resp {{.upperStartCamelObject}}
  4. err := m.QueryRowIndexCtx(ctx, &resp, {{.cacheKeyVariable}}, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) {
  5. query := fmt.Sprintf("select %s from %s where {{.originalField}} limit 1", {{.lowerStartCamelObject}}Rows, m.table)
  6. if err := conn.QueryRowCtx(ctx, &resp, query, {{.lowerStartCamelField}}); err != nil {
  7. return nil, err
  8. }
  9. return resp.{{.upperStartCamelPrimaryKey}}, nil
  10. }, m.queryPrimary)
  11. switch err {
  12. case nil:
  13. return &resp, nil
  14. case sqlc.ErrNotFound:
  15. return nil, ErrNotFound
  16. default:
  17. return nil, err
  18. }
  19. }{{else}}var resp {{.upperStartCamelObject}}
  20. query := fmt.Sprintf("select %s from %s where {{.originalField}} limit 1", {{.lowerStartCamelObject}}Rows, m.table )
  21. err := m.conn.QueryRowCtx(ctx, &resp, query, {{.lowerStartCamelField}})
  22. switch err {
  23. case nil:
  24. return &resp, nil
  25. case sqlx.ErrNotFound:
  26. return nil, ErrNotFound
  27. default:
  28. return nil, err
  29. }
  30. }{{end}}

模板注入对象为 map[string]any

  1. map[string]any{
  2. "upperStartCamelObject": camelTableName,
  3. "upperField": key.FieldNameJoin.Camel().With("").Source(),
  4. "in": in,
  5. "withCache": withCache,
  6. "cacheKey": key.KeyExpression,
  7. "cacheKeyVariable": key.KeyLeft,
  8. "lowerStartCamelObject": stringx.From(camelTableName).Untitle(),
  9. "lowerStartCamelField": paramJoinString,
  10. "upperStartCamelPrimaryKey": table.PrimaryKey.Name.ToCamel(),
  11. "originalField": originalFieldString,
  12. "postgreSql": postgreSql,
  13. "data": table,
  14. }
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式
.upperFieldstring字段名称的首字母大写形式
.instring输入参数变量名
.withCachebool是否启用缓存
.cacheKeystring缓存键
.cacheKeyVariablestring缓存键变量名
.formatPrimarystring主键格式化字符串
.lowerStartCamelObjectstring对象名称的首字母小写形式
.originalFieldstring原始字段名
.lowerStartCamelObjectRowsstring对象行数的首字母小写形式
.tablestring表名
.queryPrimarystring主要查询

find-one-by-field-extra-method.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary any) string {
  2. return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary)
  3. }
  4. func (m *default{{.upperStartCamelObject}}Model) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error {
  5. query := fmt.Sprintf("select %s from %s where {{.originalPrimaryField}} = {{if .postgreSql}}$1{{else}}?{{end}} limit 1", {{.lowerStartCamelObject}}Rows, m.table )
  6. return conn.QueryRowCtx(ctx, v, query, primary)
  7. }

模板注入对象为

  1. map[string]any{
  2. "upperStartCamelObject": camelTableName,
  3. "primaryKeyLeft": table.PrimaryCacheKey.VarLeft,
  4. "lowerStartCamelObject": stringx.From(camelTableName).Untitle(),
  5. "originalPrimaryField": wrapWithRawString(table.PrimaryKey.Name.Source(), postgreSql),
  6. "postgreSql": postgreSql,
  7. "data": table,
  8. }
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式
.primaryKeyLeftstring主键左部分字符串
.lowerStartCamelObjectstring对象名称的首字母小写形式
.originalPrimaryFieldstring原始主键字段名
.postgreSqlbool是否使用 PostgreSQL
.lowerStartCamelObjectRowsstring对象行数的首字母小写形式

import.tpl

  1. import (
  2. "context"
  3. "database/sql"
  4. "fmt"
  5. "strings"
  6. {{if .time}}"time"{{end}}
  7. {{if .containsPQ}}"github.com/lib/pq"{{end}}
  8. "github.com/zeromicro/go-zero/core/stores/builder"
  9. "github.com/zeromicro/go-zero/core/stores/cache"
  10. "github.com/zeromicro/go-zero/core/stores/sqlc"
  11. "github.com/zeromicro/go-zero/core/stores/sqlx"
  12. "github.com/zeromicro/go-zero/core/stringx"
  13. {{.third}}
  14. )

模板注入对象为

  1. map[string]any{
  2. "time": timeImport,
  3. "containsPQ": table.ContainsPQ,
  4. "data": table,
  5. "third": strings.Join(thirdImports, "\n"),
  6. }
模板变量类型描述
.timebool是否导入时间包 (time)
.containsPQbool是否包含 PostgreSQL 的依赖 (github.com/lib/pq)
.thirdstring其他第三方包的导入路径

import.no-cache.tpl

  1. import (
  2. "context"
  3. "database/sql"
  4. "fmt"
  5. "strings"
  6. {{if .time}}"time"{{end}}
  7. {{if .containsPQ}}"github.com/lib/pq"{{end}}
  8. "github.com/zeromicro/go-zero/core/stores/builder"
  9. "github.com/zeromicro/go-zero/core/stores/sqlx"
  10. "github.com/zeromicro/go-zero/core/stringx"
  11. {{.third}}
  12. )

模板注入对象为:

  1. map[string]any{
  2. "time": timeImport,
  3. "containsPQ": table.ContainsPQ,
  4. "data": table,
  5. "third": strings.Join(thirdImports, "\n"),
  6. }
模板变量类型描述
.timebool是否导入时间包 (time)
.containsPQbool是否包含 PostgreSQL 的依赖 (github.com/lib/pq)
.thirdstring其他第三方包的导入路径

insert.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error) {
  2. {{if .withCache}}{{.keys}}
  3. ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
  4. query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
  5. return conn.ExecCtx(ctx, query, {{.expressionValues}})
  6. }, {{.keyValues}}){{else}}query := fmt.Sprintf("insert into %s (%s) values ({{.expression}})", m.table, {{.lowerStartCamelObject}}RowsExpectAutoSet)
  7. ret,err:=m.conn.ExecCtx(ctx, query, {{.expressionValues}}){{end}}
  8. return ret,err
  9. }

模板注入对象为

  1. map[string]any{
  2. "withCache": withCache,
  3. "upperStartCamelObject": camel,
  4. "lowerStartCamelObject": stringx.From(camel).Untitle(),
  5. "expression": strings.Join(expressions, ", "),
  6. "expressionValues": strings.Join(expressionValues, ", "),
  7. "keys": strings.Join(keys, "\n"),
  8. "keyValues": strings.Join(keyVars, ", "),
  9. "data": table,
  10. })
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式
.withCachebool是否启用缓存
.keysstring在启用缓存时,用于键的生成逻辑
.lowerStartCamelObjectstring对象名称的首字母小写形式
.expressionstring表达式
.expressionValuesstring表达式值

interface-delete.tpl

  1. Delete(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error

模板注入对象为

  1. map[string]any{
  2. "lowerStartCamelPrimaryKey": util.EscapeGolangKeyword(stringx.From(table.PrimaryKey.Name.ToCamel()).Untitle()),
  3. "dataType": table.PrimaryKey.DataType,
  4. "data": table,
  5. }
模板变量类型描述
.lowerStartCamelPrimaryKeystring主键变量名的首字母小写形式
.dataTypestring主键数据类型

interface-find-one.tpl

  1. FindOne(ctx context.Context, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error)

模板注入对象为:

  1. map[string]any{
  2. "upperStartCamelObject": camel,
  3. "lowerStartCamelPrimaryKey": util.EscapeGolangKeyword(stringx.From(table.PrimaryKey.Name.ToCamel()).Untitle()),
  4. "dataType": table.PrimaryKey.DataType,
  5. "data": table,
  6. }
模板变量类型描述
.lowerStartCamelPrimaryKeystring主键变量名的首字母小写形式
.dataTypestring主键数据类型
.upperStartCamelObjectstring对象名称的首字母大写形式

interface-find-one-by-field.tpl

  1. FindOneBy{{.upperField}}(ctx context.Context, {{.in}}) (*{{.upperStartCamelObject}}, error)

模板注入对象为:

  1. string]any{
  2. "upperStartCamelObject": camelTableName,
  3. "upperField": key.FieldNameJoin.Camel().With("").Source(),
  4. "in": in,
  5. "data": table,
  6. }
模板变量类型描述
.upperFieldstring字段名称的首字母大写形式
.instring输入参数变量名
.upperStartCamelObjectstring对象名称的首字母大写形式

interface-insert.tpl

  1. Insert(ctx context.Context, data *{{.upperStartCamelObject}}) (sql.Result,error)

注入对象为

  1. string]any{
  2. "upperStartCamelObject": camel,
  3. "data": table,
  4. }
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式

interface-update.tpl

  1. Update(ctx context.Context, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error

模板注入对象为:

  1. map[string]any{
  2. "upperStartCamelObject": camelTableName,
  3. "data": table,
  4. }
模板变量类型描述
.containsIndexCachebool是否包含索引缓存
.upperStartCamelObjectstring对象名称的首字母大写形式

model.tpl

  1. package {{.pkg}}
  2. {{if .withCache}}
  3. import (
  4. "github.com/zeromicro/go-zero/core/stores/cache"
  5. "github.com/zeromicro/go-zero/core/stores/sqlx"
  6. )
  7. {{else}}
  8. import "github.com/zeromicro/go-zero/core/stores/sqlx"
  9. {{end}}
  10. var _ {{.upperStartCamelObject}}Model = (*custom{{.upperStartCamelObject}}Model)(nil)
  11. type (
  12. // {{.upperStartCamelObject}}Model is an interface to be customized, add more methods here,
  13. // and implement the added methods in custom{{.upperStartCamelObject}}Model.
  14. {{.upperStartCamelObject}}Model interface {
  15. {{.lowerStartCamelObject}}Model
  16. {{if not .withCache}}withSession(session sqlx.Session) {{.upperStartCamelObject}}Model{{end}}
  17. }
  18. custom{{.upperStartCamelObject}}Model struct {
  19. *default{{.upperStartCamelObject}}Model
  20. }
  21. )
  22. // New{{.upperStartCamelObject}}Model returns a model for the database table.
  23. func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf, opts ...cache.Option{{end}}) {{.upperStartCamelObject}}Model {
  24. return &custom{{.upperStartCamelObject}}Model{
  25. default{{.upperStartCamelObject}}Model: new{{.upperStartCamelObject}}Model(conn{{if .withCache}}, c, opts...{{end}}),
  26. }
  27. }
  28. {{if not .withCache}}
  29. func (m *custom{{.upperStartCamelObject}}Model) withSession(session sqlx.Session) {{.upperStartCamelObject}}Model {
  30. return New{{.upperStartCamelObject}}Model(sqlx.NewSqlConnFromSession(session))
  31. }
  32. {{end}}

模板注入对象为:

  1. map[string]any{
  2. "pkg": g.pkg,
  3. "withCache": withCache,
  4. "upperStartCamelObject": in.Name.ToCamel(),
  5. "lowerStartCamelObject": stringx.From(in.Name.ToCamel()).Untitle(),
  6. }
模板变量类型描述
.pkgstring包名
.withCachebool是否启用缓存
.upperStartCamelObjectstring对象名称的首字母大写形式
.lowerStartCamelObjectstring对象名称的首字母小写形式

model-new.tpl

  1. func new{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf, opts ...cache.Option{{end}}) *default{{.upperStartCamelObject}}Model {
  2. return &default{{.upperStartCamelObject}}Model{
  3. {{if .withCache}}CachedConn: sqlc.NewConn(conn, c, opts...){{else}}conn:conn{{end}},
  4. table: {{.table}},
  5. }
  6. }

模板注入对象为:

  1. map[string]any{
  2. "table": t,
  3. "withCache": withCache,
  4. "upperStartCamelObject": table.Name.ToCamel(),
  5. "data": table,
  6. }
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式
.withCachebool是否启用缓存
.tablestring数据库表名

table-name.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) tableName() string {
  2. return m.table
  3. }

模板注入对象为:

  1. map[string]any{
  2. "tableName": table.Name.Source(),
  3. "upperStartCamelObject": table.Name.ToCamel(),
  4. }
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式

tag.tpl

  1. `db:"{{.field}}"`

模板注入对象为:

  1. map[string]any{
  2. "field": in,
  3. "data": table,
  4. }
模板变量类型描述
.fieldstringdb tag 名称

types.tpl

  1. type (
  2. {{.lowerStartCamelObject}}Model interface{
  3. {{.method}}
  4. }
  5. default{{.upperStartCamelObject}}Model struct {
  6. {{if .withCache}}sqlc.CachedConn{{else}}conn sqlx.SqlConn{{end}}
  7. table string
  8. }
  9. {{.upperStartCamelObject}} struct {
  10. {{.fields}}
  11. }
  12. )

模板注入对象为:

  1. map[string]any{
  2. "withCache": withCache,
  3. "method": methods,
  4. "upperStartCamelObject": table.Name.ToCamel(),
  5. "lowerStartCamelObject": stringx.From(table.Name.ToCamel()).Untitle(),
  6. "fields": fieldsString,
  7. "data": table,
  8. }
模板变量类型描述
.lowerStartCamelObjectstring对象名称的首字母小写形式
.methodstring接口方法定义
.upperStartCamelObjectstring对象名称的首字母大写形式
.withCachebool是否启用缓存
.fieldsstring结构体字段定义

update.tpl

  1. func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error {
  2. {{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne(ctx, newData.{{.upperStartCamelPrimaryKey}})
  3. if err!=nil{
  4. return err
  5. }
  6. {{end}} {{.keys}}
  7. _, {{if .containsIndexCache}}err{{else}}err:{{end}}= m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
  8. query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
  9. return conn.ExecCtx(ctx, query, {{.expressionValues}})
  10. }, {{.keyValues}}){{else}}query := fmt.Sprintf("update %s set %s where {{.originalPrimaryKey}} = {{if .postgreSql}}$1{{else}}?{{end}}", m.table, {{.lowerStartCamelObject}}RowsWithPlaceHolder)
  11. _,err:=m.conn.ExecCtx(ctx, query, {{.expressionValues}}){{end}}
  12. return err
  13. }

模板注入对象为:

  1. map[string]any{
  2. "withCache": withCache,
  3. "containsIndexCache": table.ContainsUniqueCacheKey,
  4. "upperStartCamelObject": camelTableName,
  5. "keys": strings.Join(keys, "\n"),
  6. "keyValues": strings.Join(keyVars, ", "),
  7. "primaryCacheKey": table.PrimaryCacheKey.DataKeyExpression,
  8. "primaryKeyVariable": table.PrimaryCacheKey.KeyLeft,
  9. "lowerStartCamelObject": stringx.From(camelTableName).Untitle(),
  10. "upperStartCamelPrimaryKey": util.EscapeGolangKeyword(
  11. stringx.From(table.PrimaryKey.Name.ToCamel()).Title(),
  12. ),
  13. "originalPrimaryKey": wrapWithRawString(
  14. table.PrimaryKey.Name.Source(), postgreSql,
  15. ),
  16. "expressionValues": strings.Join(
  17. expressionValues, ", ",
  18. ),
  19. "postgreSql": postgreSql,
  20. "data": table,
  21. }
模板变量类型描述
.upperStartCamelObjectstring对象名称的首字母大写形式
.containsIndexCachebool是否包含索引缓存
.withCachebool是否启用缓存
.upperStartCamelPrimaryKeystring主键字段名称的首字母大写形式
.lowerStartCamelObjectstring对象名称的首字母小写形式
.lowerStartCamelPrimaryKeystring主键字段名称的首字母小写形式
.postgreSqlbool是否为 PostgreSQL 数据库
.keysstring键值
.expressionValuesstring表达值

var.tpl

  1. var (
  2. {{.lowerStartCamelObject}}FieldNames = builder.RawFieldNames(&{{.upperStartCamelObject}}{}{{if .postgreSql}}, true{{end}})
  3. {{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",")
  4. {{.lowerStartCamelObject}}RowsExpectAutoSet = {{if .postgreSql}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}", {{end}} {{.ignoreColumns}}), ","){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}", {{end}} {{.ignoreColumns}}), ","){{end}}
  5. {{.lowerStartCamelObject}}RowsWithPlaceHolder = {{if .postgreSql}}builder.PostgreSqlJoin(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", {{.ignoreColumns}})){{else}}strings.Join(stringx.Remove({{.lowerStartCamelObject}}FieldNames, "{{.originalPrimaryKey}}", {{.ignoreColumns}}), "=?,") + "=?"{{end}}
  6. {{if .withCache}}{{.cacheKeys}}{{end}}
  7. )

模板注入对象为:

  1. map[string]any{
  2. "lowerStartCamelObject": stringx.From(camel).Untitle(),
  3. "upperStartCamelObject": camel,
  4. "cacheKeys": strings.Join(keys, "\n"),
  5. "autoIncrement": table.PrimaryKey.AutoIncrement,
  6. "originalPrimaryKey": wrapWithRawString(table.PrimaryKey.Name.Source(), postgreSql),
  7. "withCache": withCache,
  8. "postgreSql": postgreSql,
  9. "data": table,
  10. "ignoreColumns": func() string {
  11. var set = collection.NewSet()
  12. for _, c := range table.ignoreColumns {
  13. if postgreSql {
  14. set.AddStr(fmt.Sprintf(`"%s"`, c))
  15. } else {
  16. set.AddStr(fmt.Sprintf("\"`%s`\"", c))
  17. }
  18. }
  19. list := set.KeysStr()
  20. sort.Strings(list)
  21. return strings.Join(list, ", ")
  22. }(),
  23. }
模板变量类型描述
.lowerStartCamelObjectstring对象名称的首字母小写形式
.upperStartCamelObjectstring对象名称的首字母大写形式
.postgreSqlbool是否为 PostgreSQL 数据库
.autoIncrementstring自动增量标识符
.originalPrimaryKeystring原始主键字段名
.ignoreColumnsstring忽略的列名列表
.withCachebool是否启用缓存
.cacheKeysstring缓存键列表

goctl kube 代码生成模板

模板默认目录 ~/.goctl/${goctl-version}/kube

deployment.tpl

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: {{.Name}}
  5. namespace: {{.Namespace}}
  6. labels:
  7. app: {{.Name}}
  8. spec:
  9. replicas: {{.Replicas}}
  10. revisionHistoryLimit: {{.Revisions}}
  11. selector:
  12. matchLabels:
  13. app: {{.Name}}
  14. template:
  15. metadata:
  16. labels:
  17. app: {{.Name}}
  18. spec:{{if .ServiceAccount}}
  19. serviceAccountName: {{.ServiceAccount}}{{end}}
  20. containers:
  21. - name: {{.Name}}
  22. image: {{.Image}}
  23. {{if .ImagePullPolicy}}imagePullPolicy: {{.ImagePullPolicy}}
  24. {{end}}ports:
  25. - containerPort: {{.Port}}
  26. readinessProbe:
  27. tcpSocket:
  28. port: {{.Port}}
  29. initialDelaySeconds: 5
  30. periodSeconds: 10
  31. livenessProbe:
  32. tcpSocket:
  33. port: {{.Port}}
  34. initialDelaySeconds: 15
  35. periodSeconds: 20
  36. resources:
  37. requests:
  38. cpu: {{.RequestCpu}}m
  39. memory: {{.RequestMem}}Mi
  40. limits:
  41. cpu: {{.LimitCpu}}m
  42. memory: {{.LimitMem}}Mi
  43. volumeMounts:
  44. - name: timezone
  45. mountPath: /etc/localtime
  46. {{if .Secret}}imagePullSecrets:
  47. - name: {{.Secret}}
  48. {{end}}volumes:
  49. - name: timezone
  50. hostPath:
  51. path: /usr/share/zoneinfo/Asia/Shanghai
  52. ---
  53. apiVersion: v1
  54. kind: Service
  55. metadata:
  56. name: {{.Name}}-svc
  57. namespace: {{.Namespace}}
  58. spec:
  59. ports:
  60. {{if .UseNodePort}}- nodePort: {{.NodePort}}
  61. port: {{.Port}}
  62. protocol: TCP
  63. targetPort: {{.TargetPort}}
  64. type:
  65. NodePort{{else}}- port: {{.Port}}
  66. targetPort: {{.TargetPort}}{{end}}
  67. selector:
  68. app: {{.Name}}
  69. ---
  70. apiVersion: autoscaling/v2beta2
  71. kind: HorizontalPodAutoscaler
  72. metadata:
  73. name: {{.Name}}-hpa-c
  74. namespace: {{.Namespace}}
  75. labels:
  76. app: {{.Name}}-hpa-c
  77. spec:
  78. scaleTargetRef:
  79. apiVersion: apps/v1
  80. kind: Deployment
  81. name: {{.Name}}
  82. minReplicas: {{.MinReplicas}}
  83. maxReplicas: {{.MaxReplicas}}
  84. metrics:
  85. - type: Resource
  86. resource:
  87. name: cpu
  88. target:
  89. type: Utilization
  90. averageUtilization: 80
  91. ---
  92. apiVersion: autoscaling/v2beta2
  93. kind: HorizontalPodAutoscaler
  94. metadata:
  95. name: {{.Name}}-hpa-m
  96. namespace: {{.Namespace}}
  97. labels:
  98. app: {{.Name}}-hpa-m
  99. spec:
  100. scaleTargetRef:
  101. apiVersion: apps/v1
  102. kind: Deployment
  103. name: {{.Name}}
  104. minReplicas: {{.MinReplicas}}
  105. maxReplicas: {{.MaxReplicas}}
  106. metrics:
  107. - type: Resource
  108. resource:
  109. name: memory
  110. target:
  111. type: Utilization
  112. averageUtilization: 80

模板注入对象为 Deployment

  1. Deployment{
  2. Name: varStringName,
  3. Namespace: varStringNamespace,
  4. Image: varStringImage,
  5. Secret: varStringSecret,
  6. Replicas: varIntReplicas,
  7. Revisions: varIntRevisions,
  8. Port: varIntPort,
  9. TargetPort: varIntTargetPort,
  10. NodePort: nodePort,
  11. UseNodePort: nodePort > 0,
  12. RequestCpu: varIntRequestCpu,
  13. RequestMem: varIntRequestMem,
  14. LimitCpu: varIntLimitCpu,
  15. LimitMem: varIntLimitMem,
  16. MinReplicas: varIntMinReplicas,
  17. MaxReplicas: varIntMaxReplicas,
  18. ServiceAccount: varStringServiceAccount,
  19. ImagePullPolicy: varStringImagePullPolicy,
  20. }
pipeline变量类型说明
.Namestring名称
.Namespacestring命名空间
.Replicasint副本数量
.Revisionsint修订历史限制
.ServiceAccountstring服务账户名称 (可选)
.Imagestring容器镜像
.ImagePullPolicystring镜像拉取策略 (可选)
.Portint容器端口
.RequestCpuintCPU 请求 (单位: millicores)
.RequestMemint内存请求 (单位: MiB)
.LimitCpuintCPU 限制 (单位: millicores)
.LimitMemint内存限制 (单位: MiB)
.Secretstring镜像拉取密钥 (可选)
.UseNodePortbool使用 NodePort (布尔值)
.NodePortintNodePort 端口 (当 UseNodePort 为 true 时)
.TargetPortint目标端口
.MinReplicasint最小副本数
.MaxReplicasint最大副本数

goctl docker 生成模板

模板默认目录 ~/.goctl/${goctl-version}/docker

docker.tpl

  1. FROM golang:{{.Version}}alpine AS builder
  2. LABEL stage=gobuilder
  3. ENV CGO_ENABLED 0
  4. {{if .Chinese}}ENV GOPROXY https://goproxy.cn,direct
  5. RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
  6. {{end}}{{if .HasTimezone}}
  7. RUN apk update --no-cache && apk add --no-cache tzdata
  8. {{end}}
  9. WORKDIR /build
  10. ADD go.mod .
  11. ADD go.sum .
  12. RUN go mod download
  13. COPY . .
  14. {{if .Argument}}COPY {{.GoRelPath}}/etc /app/etc
  15. {{end}}RUN go build -ldflags="-s -w" -o /app/{{.ExeFile}} {{.GoMainFrom}}
  16. FROM {{.BaseImage}}
  17. COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
  18. {{if .HasTimezone}}COPY --from=builder /usr/share/zoneinfo/{{.Timezone}} /usr/share/zoneinfo/{{.Timezone}}
  19. ENV TZ {{.Timezone}}
  20. {{end}}
  21. WORKDIR /app
  22. COPY --from=builder /app/{{.ExeFile}} /app/{{.ExeFile}}{{if .Argument}}
  23. COPY --from=builder /app/etc /app/etc{{end}}
  24. {{if .HasPort}}
  25. EXPOSE {{.Port}}
  26. {{end}}
  27. CMD ["./{{.ExeFile}}"{{.Argument}}]

模板注入对象为 Docker

  1. Docker{
  2. Chinese: env.InChina(),
  3. GoMainFrom: path.Join(projPath, goFile),
  4. GoRelPath: projPath,
  5. GoFile: goFile,
  6. ExeFile: exeName,
  7. BaseImage: base,
  8. HasPort: port > 0,
  9. Port: port,
  10. Argument: builder.String(),
  11. Version: version,
  12. HasTimezone: len(timezone) > 0,
  13. Timezone: timezone,
  14. }
pipeline变量类型说明
.VersionstringGolang 版本
.Chinesebool是否使用中国时区
.HasTimezonebool是否需要时区设置
.Argumentstring命令行参数 (可选)
.GoRelPathstringGo 项目相对路径
.ExeFilestring可执行文件名称
.GoMainFromstringGo 主程序源文件路径
.BaseImagestring基础镜像
.Timezonestring时区
.HasPortbool是否需要暴露端口

rpc 代码生成模板

模板默认目录 ~/.goctl/${goctl-version}/rpc

call.tpl

  1. {{.head}}
  2. package {{.filePackage}}
  3. import (
  4. "context"
  5. {{.pbPackage}}
  6. {{if ne .pbPackage .protoGoPackage}}{{.protoGoPackage}}{{end}}
  7. "github.com/zeromicro/go-zero/zrpc"
  8. "google.golang.org/grpc"
  9. )
  10. type (
  11. {{.alias}}
  12. {{.serviceName}} interface {
  13. {{.interface}}
  14. }
  15. default{{.serviceName}} struct {
  16. cli zrpc.Client
  17. }
  18. )
  19. func New{{.serviceName}}(cli zrpc.Client) {{.serviceName}} {
  20. return &default{{.serviceName}}{
  21. cli: cli,
  22. }
  23. }
  24. {{.functions}}

模板注入对象 map[string]any

  1. map[string]any{
  2. "name": callFilename,
  3. "alias": strings.Join(aliasKeys, pathx.NL),
  4. "head": head,
  5. "filePackage": childDir,
  6. "pbPackage": pbPackage,
  7. "protoGoPackage": protoGoPackage,
  8. "serviceName": serviceName,
  9. "functions": strings.Join(functions, pathx.NL),
  10. "interface": strings.Join(iFunctions, pathx.NL),
  11. }
pipeline变量类型说明
.headstring头部信息
.filePackagestring文件包名
.pbPackagestringProtocol Buffers 包导入路径
.protoGoPackagestringProtocol Buffers Go 包导入路径 (可选)
.aliasstring类型别名声明
.serviceNamestring服务名称
.interfacestring接口定义
.functionsstring函数实现

config.tpl

  1. package config
  2. import "github.com/zeromicro/go-zero/zrpc"
  3. type Config struct {
  4. zrpc.RpcServerConf
  5. }

无变量注入

etc.tpl

  1. Name: {{.serviceName}}.rpc
  2. ListenOn: 0.0.0.0:8080
  3. Etcd:
  4. Hosts:
  5. - 127.0.0.1:2379
  6. Key: {{.serviceName}}.rpc

模板注入对象为:

  1. map[string]any{
  2. "serviceName": strings.ToLower(stringx.From(ctx.GetServiceName().Source()).ToCamel()),
  3. }
pipeline变量类型描述
.serviceNamestring服务名称的变量

logic.tpl

  1. package {{.packageName}}
  2. import (
  3. "context"
  4. {{.imports}}
  5. "github.com/zeromicro/go-zero/core/logx"
  6. )
  7. type {{.logicName}} struct {
  8. ctx context.Context
  9. svcCtx *svc.ServiceContext
  10. logx.Logger
  11. }
  12. func New{{.logicName}}(ctx context.Context,svcCtx *svc.ServiceContext) *{{.logicName}} {
  13. return &{{.logicName}}{
  14. ctx: ctx,
  15. svcCtx: svcCtx,
  16. Logger: logx.WithContext(ctx),
  17. }
  18. }
  19. {{.functions}}

模板注入对象为:

  • 不支持分组情况下
  1. map[string]any{
  2. "logicName": fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel()),
  3. "functions": functions,
  4. "packageName": "logic",
  5. "imports": strings.Join(imports.KeysStr(), pathx.NL),
  6. }
  • 支持分组情况下
  1. map[string]any{
  2. "logicName": logicName,
  3. "functions": functions,
  4. "packageName": packageName,
  5. "imports": strings.Join(imports.KeysStr(), pathx.NL),
  6. }
pipeline变量类型描述
.packageNamestring包名
.importsstring导入的包列表
.logicNamestring逻辑结构体名称
.functionsstring函数定义部分

main.tpl

  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. {{.imports}}
  6. "github.com/zeromicro/go-zero/core/conf"
  7. "github.com/zeromicro/go-zero/core/service"
  8. "github.com/zeromicro/go-zero/zrpc"
  9. "google.golang.org/grpc"
  10. "google.golang.org/grpc/reflection"
  11. )
  12. var configFile = flag.String("f", "etc/{{.serviceName}}.yaml", "the config file")
  13. func main() {
  14. flag.Parse()
  15. var c config.Config
  16. conf.MustLoad(*configFile, &c)
  17. ctx := svc.NewServiceContext(c)
  18. s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
  19. {{range .serviceNames}} {{.Pkg}}.Register{{.GRPCService}}Server(grpcServer, {{.ServerPkg}}.New{{.Service}}Server(ctx))
  20. {{end}}
  21. if c.Mode == service.DevMode || c.Mode == service.TestMode {
  22. reflection.Register(grpcServer)
  23. }
  24. })
  25. defer s.Stop()
  26. fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
  27. s.Start()
  28. }

模板注入对象为:

  1. map[string]any{
  2. "serviceName": etcFileName,
  3. "imports": strings.Join(imports, pathx.NL),
  4. "pkg": proto.PbPackage,
  5. "serviceNames": serviceNames,
  6. }
pipeline变量类型描述
.importsstring导入的包列表
.serviceNamestring服务名称
.serviceNames列表包含以下子变量的列表
.serviceNames.Pkgstring服务包名
.serviceNames.GRPCServicestringgRPC 服务名称
.serviceNames.ServerPkgstringgRPC 服务包名
.serviceNames.Servicestring服务名称

rpc.tpl

  1. {{.head}}
  2. package server
  3. import (
  4. {{if .notStream}}"context"{{end}}
  5. {{.imports}}
  6. )
  7. type {{.server}}Server struct {
  8. svcCtx *svc.ServiceContext
  9. {{.unimplementedServer}}
  10. }
  11. func New{{.server}}Server(svcCtx *svc.ServiceContext) *{{.server}}Server {
  12. return &{{.server}}Server{
  13. svcCtx: svcCtx,
  14. }
  15. }
  16. {{.funcs}}

模板注入对象为:

  • 不支持分组情况
  1. map[string]any{
  2. "head": head,
  3. "unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage,
  4. parser.CamelCase(service.Name)),
  5. "server": stringx.From(service.Name).ToCamel(),
  6. "imports": strings.Join(imports.KeysStr(), pathx.NL),
  7. "funcs": strings.Join(funcList, pathx.NL),
  8. "notStream": notStream,
  9. }
  • 支持分组情况
  1. map[string]any{
  2. "head": head,
  3. "unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage,
  4. parser.CamelCase(service.Name)),
  5. "server": stringx.From(service.Name).ToCamel(),
  6. "imports": strings.Join(imports.KeysStr(), pathx.NL),
  7. "funcs": strings.Join(funcList, pathx.NL),
  8. "notStream": notStream,
  9. }
pipeline变量类型描述
.head文本包级别注释或其他代码
.notStream布尔根据条件是否引入 context
.imports文本其他导入语句
.server文本定义服务名称的占位符
.unimplementedServer文本定义未实现服务器的占位符
.funcs文本生成特定于服务器类型的其他函数/方法的占位符

svc.tpl

  1. package svc
  2. import {{.imports}}
  3. type ServiceContext struct {
  4. Config config.Config
  5. }
  6. func NewServiceContext(c config.Config) *ServiceContext {
  7. return &ServiceContext{
  8. Config:c,
  9. }
  10. }

模板注入对象为:

  1. map[string]any{
  2. "imports": fmt.Sprintf(`"%v"`, ctx.GetConfig().Package),
  3. }
pipeline变量类型描述
.imports文本其他导入语句

参考文献