From 8774d72ddb8c4f39c6f010c597cfb77e714f2c20 Mon Sep 17 00:00:00 2001 From: Kevin Wan Date: Sat, 9 Jan 2021 00:17:23 +0800 Subject: [PATCH] remove duplicated code in goctl (#369) --- readme.md | 10 ++++-- tools/goctl/api/gogen/genconfig.go | 42 +++++++--------------- tools/goctl/api/gogen/genetc.go | 43 +++++++--------------- tools/goctl/api/gogen/genhandlers.go | 36 ++++++------------- tools/goctl/api/gogen/genlogic.go | 50 +++++++++----------------- tools/goctl/api/gogen/genmain.go | 42 +++++++--------------- tools/goctl/api/gogen/genmiddleware.go | 35 ++++++------------ tools/goctl/api/gogen/genroutes.go | 34 +++++++----------- tools/goctl/api/gogen/gensvc.go | 49 +++++++++---------------- tools/goctl/api/gogen/gentypes.go | 36 +++++++------------ tools/goctl/api/gogen/util.go | 46 ++++++++++++++++++++++++ 11 files changed, 168 insertions(+), 255 deletions(-) diff --git a/readme.md b/readme.md index 469bbe4d..ab8bc3cd 100644 --- a/readme.md +++ b/readme.md @@ -157,11 +157,11 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/ ## 7. 文档 -* API 文档 (逐步完善中) +* API 文档 [https://www.yuque.com/tal-tech/go-zero](https://www.yuque.com/tal-tech/go-zero) -* awesome 系列 +* awesome 系列(全部收录于『微服务实践』公众号) * [快速构建高并发微服务](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl.md) * [快速构建高并发微服务 - 多 RPC 版](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore.md) * [goctl 使用帮助](https://github.com/tal-tech/zero-doc/blob/main/doc/goctl.md) @@ -172,6 +172,12 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/ * [基于 prometheus 的微服务指标监控](https://github.com/tal-tech/zero-doc/blob/main/doc/metric.md) * [文本序列化和反序列化](https://github.com/tal-tech/zero-doc/blob/main/doc/mapping.md) * [快速构建 jwt 鉴权认证](https://github.com/tal-tech/zero-doc/blob/main/doc/jwt.md) + +* 精选 `goctl` 插件 + + * [goctl-swagger](https://github.com/zeromicro/goctl-swagger) 一键生成 `api` 的 `swagger` 文档 + * [goctl-android](https://github.com/zeromicro/goctl-android) 生成 `java (android)` 端 `http client` 请求代码 + * [goctl-go-compact](https://github.com/zeromicro/goctl-go-compact) 合并 `api` 里同一个 `group` 里的 `handler` 到一个 `go` 文件 ## 8. 微信公众号 diff --git a/tools/goctl/api/gogen/genconfig.go b/tools/goctl/api/gogen/genconfig.go index 24258cb5..16c38366 100644 --- a/tools/goctl/api/gogen/genconfig.go +++ b/tools/goctl/api/gogen/genconfig.go @@ -1,15 +1,11 @@ package gogen import ( - "bytes" "fmt" "strings" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" - "github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/tal-tech/go-zero/tools/goctl/config" - ctlutil "github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/tal-tech/go-zero/tools/goctl/vars" ) @@ -39,38 +35,24 @@ func genConfig(dir string, cfg *config.Config, api *spec.ApiSpec) error { return err } - fp, created, err := util.MaybeCreateFile(dir, configDir, filename+".go") - if err != nil { - return err - } - if !created { - return nil - } - defer fp.Close() - var authNames = getAuths(api) var auths []string for _, item := range authNames { auths = append(auths, fmt.Sprintf("%s %s", item, jwtTemplate)) } - var authImportStr = fmt.Sprintf("\"%s/rest\"", vars.ProjectOpenSourceUrl) - text, err := ctlutil.LoadTemplate(category, configTemplateFile, configTemplate) - if err != nil { - return err - } - t := template.Must(template.New("configTemplate").Parse(text)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]string{ - "authImport": authImportStr, - "auth": strings.Join(auths, "\n"), + return genFile(fileGenConfig{ + dir: dir, + subdir: configDir, + filename: filename + ".go", + templateName: "configTemplate", + category: category, + templateFile: configTemplateFile, + builtinTemplate: configTemplate, + data: map[string]string{ + "authImport": authImportStr, + "auth": strings.Join(auths, "\n"), + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } diff --git a/tools/goctl/api/gogen/genetc.go b/tools/goctl/api/gogen/genetc.go index ea1cce79..5f72a139 100644 --- a/tools/goctl/api/gogen/genetc.go +++ b/tools/goctl/api/gogen/genetc.go @@ -1,15 +1,12 @@ package gogen import ( - "bytes" "fmt" "strconv" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/tal-tech/go-zero/tools/goctl/config" - ctlutil "github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util/format" ) @@ -28,15 +25,6 @@ func genEtc(dir string, cfg *config.Config, api *spec.ApiSpec) error { return err } - fp, created, err := util.MaybeCreateFile(dir, etcDir, fmt.Sprintf("%s.yaml", filename)) - if err != nil { - return err - } - if !created { - return nil - } - defer fp.Close() - service := api.Service host, ok := util.GetAnnotationValue(service.Groups[0].Annotations, "server", "host") if !ok { @@ -47,23 +35,18 @@ func genEtc(dir string, cfg *config.Config, api *spec.ApiSpec) error { port = strconv.Itoa(defaultPort) } - text, err := ctlutil.LoadTemplate(category, etcTemplateFile, etcTemplate) - if err != nil { - return err - } - - t := template.Must(template.New("etcTemplate").Parse(text)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]string{ - "serviceName": service.Name, - "host": host, - "port": port, + return genFile(fileGenConfig{ + dir: dir, + subdir: etcDir, + filename: fmt.Sprintf("%s.yaml", filename), + templateName: "etcTemplate", + category: category, + templateFile: etcTemplateFile, + builtinTemplate: etcTemplate, + data: map[string]string{ + "serviceName": service.Name, + "host": host, + "port": port, + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } diff --git a/tools/goctl/api/gogen/genhandlers.go b/tools/goctl/api/gogen/genhandlers.go index cdddefbe..f6cd2f5e 100644 --- a/tools/goctl/api/gogen/genhandlers.go +++ b/tools/goctl/api/gogen/genhandlers.go @@ -1,12 +1,10 @@ package gogen import ( - "bytes" "errors" "fmt" "path" "strings" - "text/template" "unicode" "github.com/tal-tech/go-zero/tools/goctl/api/spec" @@ -82,30 +80,16 @@ func doGenToFile(dir, handler string, cfg *config.Config, group spec.Group, return err } - filename = filename + ".go" - fp, created, err := apiutil.MaybeCreateFile(dir, getHandlerFolderPath(group, route), filename) - if err != nil { - return err - } - if !created { - return nil - } - defer fp.Close() - - text, err := util.LoadTemplate(category, handlerTemplateFile, handlerTemplate) - if err != nil { - return err - } - - buffer := new(bytes.Buffer) - err = template.Must(template.New("handlerTemplate").Parse(text)).Execute(buffer, handleObj) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err + return genFile(fileGenConfig{ + dir: dir, + subdir: getHandlerFolderPath(group, route), + filename: filename + ".go", + templateName: "handlerTemplate", + category: category, + templateFile: handlerTemplateFile, + builtinTemplate: handlerTemplate, + data: handleObj, + }) } func genHandlers(dir string, cfg *config.Config, api *spec.ApiSpec) error { diff --git a/tools/goctl/api/gogen/genlogic.go b/tools/goctl/api/gogen/genlogic.go index 59d2ec47..9efb9cd7 100644 --- a/tools/goctl/api/gogen/genlogic.go +++ b/tools/goctl/api/gogen/genlogic.go @@ -1,11 +1,9 @@ package gogen import ( - "bytes" "fmt" "path" "strings" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/tal-tech/go-zero/tools/goctl/api/util" @@ -61,17 +59,6 @@ func genLogicByRoute(dir string, cfg *config.Config, group spec.Group, route spe return err } - goFile = goFile + ".go" - fp, created, err := util.MaybeCreateFile(dir, getLogicFolderPath(group, route), goFile) - if err != nil { - return err - } - - if !created { - return nil - } - defer fp.Close() - parentPkg, err := getParentPackage(dir) if err != nil { return err @@ -93,28 +80,23 @@ func genLogicByRoute(dir string, cfg *config.Config, group spec.Group, route spe requestString = "req " + "types." + strings.Title(route.RequestType.Name) } - text, err := ctlutil.LoadTemplate(category, logicTemplateFile, logicTemplate) - if err != nil { - return err - } - - t := template.Must(template.New("logicTemplate").Parse(text)) - buffer := new(bytes.Buffer) - err = t.Execute(fp, map[string]string{ - "imports": imports, - "logic": strings.Title(logic), - "function": strings.Title(strings.TrimSuffix(logic, "Logic")), - "responseType": responseString, - "returnString": returnString, - "request": requestString, + return genFile(fileGenConfig{ + dir: dir, + subdir: getLogicFolderPath(group, route), + filename: goFile + ".go", + templateName: "logicTemplate", + category: category, + templateFile: logicTemplateFile, + builtinTemplate: logicTemplate, + data: map[string]string{ + "imports": imports, + "logic": strings.Title(logic), + "function": strings.Title(strings.TrimSuffix(logic, "Logic")), + "responseType": responseString, + "returnString": returnString, + "request": requestString, + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } func getLogicFolderPath(group spec.Group, route spec.Route) string { diff --git a/tools/goctl/api/gogen/genmain.go b/tools/goctl/api/gogen/genmain.go index 9cd6b34c..96ca06d8 100644 --- a/tools/goctl/api/gogen/genmain.go +++ b/tools/goctl/api/gogen/genmain.go @@ -1,13 +1,10 @@ package gogen import ( - "bytes" "fmt" "strings" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" - "github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/tal-tech/go-zero/tools/goctl/config" ctlutil "github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util/format" @@ -52,39 +49,24 @@ func genMain(dir string, cfg *config.Config, api *spec.ApiSpec) error { return err } - goFile := filename + ".go" - fp, created, err := util.MaybeCreateFile(dir, "", goFile) - if err != nil { - return err - } - if !created { - return nil - } - defer fp.Close() - parentPkg, err := getParentPackage(dir) if err != nil { return err } - text, err := ctlutil.LoadTemplate(category, mainTemplateFile, mainTemplate) - if err != nil { - return err - } - - t := template.Must(template.New("mainTemplate").Parse(text)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]string{ - "importPackages": genMainImports(parentPkg), - "serviceName": api.Service.Name, + return genFile(fileGenConfig{ + dir: dir, + subdir: "", + filename: filename + ".go", + templateName: "mainTemplate", + category: category, + templateFile: mainTemplateFile, + builtinTemplate: mainTemplate, + data: map[string]string{ + "importPackages": genMainImports(parentPkg), + "serviceName": api.Service.Name, + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } func genMainImports(parentPkg string) string { diff --git a/tools/goctl/api/gogen/genmiddleware.go b/tools/goctl/api/gogen/genmiddleware.go index d4847d62..727673b6 100644 --- a/tools/goctl/api/gogen/genmiddleware.go +++ b/tools/goctl/api/gogen/genmiddleware.go @@ -1,12 +1,9 @@ package gogen import ( - "bytes" "strings" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" - "github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/tal-tech/go-zero/tools/goctl/config" "github.com/tal-tech/go-zero/tools/goctl/util/format" ) @@ -37,36 +34,26 @@ func genMiddleware(dir string, cfg *config.Config, api *spec.ApiSpec) error { var middlewares = getMiddleware(api) for _, item := range middlewares { middlewareFilename := strings.TrimSuffix(strings.ToLower(item), "middleware") + "_middleware" - formatName, err := format.FileNamingFormat(cfg.NamingFormat, middlewareFilename) + filename, err := format.FileNamingFormat(cfg.NamingFormat, middlewareFilename) if err != nil { return err } - filename := formatName + ".go" - fp, created, err := util.MaybeCreateFile(dir, middlewareDir, filename) - if err != nil { - return err - } - if !created { - continue - } - defer fp.Close() - name := strings.TrimSuffix(item, "Middleware") + "Middleware" - t := template.Must(template.New("contextTemplate").Parse(middlewareImplementCode)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]string{ - "name": strings.Title(name), + err = genFile(fileGenConfig{ + dir: dir, + subdir: middlewareDir, + filename: filename + ".go", + templateName: "contextTemplate", + builtinTemplate: middlewareImplementCode, + data: map[string]string{ + "name": strings.Title(name), + }, }) if err != nil { return err } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - if err != nil { - return err - } } + return nil } diff --git a/tools/goctl/api/gogen/genroutes.go b/tools/goctl/api/gogen/genroutes.go index 39ee87d7..65aa27e4 100644 --- a/tools/goctl/api/gogen/genroutes.go +++ b/tools/goctl/api/gogen/genroutes.go @@ -1,7 +1,6 @@ package gogen import ( - "bytes" "fmt" "os" "path" @@ -132,28 +131,19 @@ func genRoutes(dir string, cfg *config.Config, api *spec.ApiSpec) error { filename := path.Join(dir, handlerDir, routeFilename) os.Remove(filename) - fp, created, err := apiutil.MaybeCreateFile(dir, handlerDir, routeFilename) - if err != nil { - return err - } - if !created { - return nil - } - defer fp.Close() - - t := template.Must(template.New("routesTemplate").Parse(routesTemplate)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]string{ - "importPackages": genRouteImports(parentPkg, api), - "routesAdditions": strings.TrimSpace(builder.String()), + return genFile(fileGenConfig{ + dir: dir, + subdir: handlerDir, + filename: routeFilename, + templateName: "routesTemplate", + category: "", + templateFile: "", + builtinTemplate: routesTemplate, + data: map[string]string{ + "importPackages": genRouteImports(parentPkg, api), + "routesAdditions": strings.TrimSpace(builder.String()), + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } func genRouteImports(parentPkg string, api *spec.ApiSpec) string { diff --git a/tools/goctl/api/gogen/gensvc.go b/tools/goctl/api/gogen/gensvc.go index d8ace68b..e4adab37 100644 --- a/tools/goctl/api/gogen/gensvc.go +++ b/tools/goctl/api/gogen/gensvc.go @@ -1,13 +1,10 @@ package gogen import ( - "bytes" "fmt" "strings" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" - "github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/tal-tech/go-zero/tools/goctl/config" ctlutil "github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util/format" @@ -33,7 +30,6 @@ func NewServiceContext(c {{.config}}) *ServiceContext { {{.middlewareAssignment}} } } - ` ) @@ -43,15 +39,6 @@ func genServiceContext(dir string, cfg *config.Config, api *spec.ApiSpec) error return err } - fp, created, err := util.MaybeCreateFile(dir, contextDir, filename+".go") - if err != nil { - return err - } - if !created { - return nil - } - defer fp.Close() - var authNames = getAuths(api) var auths []string for _, item := range authNames { @@ -63,11 +50,6 @@ func genServiceContext(dir string, cfg *config.Config, api *spec.ApiSpec) error return err } - text, err := ctlutil.LoadTemplate(category, contextTemplateFile, contextTemplate) - if err != nil { - return err - } - var middlewareStr string var middlewareAssignment string var middlewares = getMiddleware(api) @@ -75,7 +57,8 @@ func genServiceContext(dir string, cfg *config.Config, api *spec.ApiSpec) error for _, item := range middlewares { middlewareStr += fmt.Sprintf("%s rest.Middleware\n", item) name := strings.TrimSuffix(item, "Middleware") + "Middleware" - middlewareAssignment += fmt.Sprintf("%s: %s,\n", item, fmt.Sprintf("middleware.New%s().%s", strings.Title(name), "Handle")) + middlewareAssignment += fmt.Sprintf("%s: %s,\n", item, + fmt.Sprintf("middleware.New%s().%s", strings.Title(name), "Handle")) } var configImport = "\"" + ctlutil.JoinPackages(parentPkg, configDir) + "\"" @@ -84,19 +67,19 @@ func genServiceContext(dir string, cfg *config.Config, api *spec.ApiSpec) error configImport += fmt.Sprintf("\n\t\"%s/rest\"", vars.ProjectOpenSourceUrl) } - t := template.Must(template.New("contextTemplate").Parse(text)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]string{ - "configImport": configImport, - "config": "config.Config", - "middleware": middlewareStr, - "middlewareAssignment": middlewareAssignment, + return genFile(fileGenConfig{ + dir: dir, + subdir: contextDir, + filename: filename + ".go", + templateName: "contextTemplate", + category: category, + templateFile: contextTemplateFile, + builtinTemplate: contextTemplate, + data: map[string]string{ + "configImport": configImport, + "config": "config.Config", + "middleware": middlewareStr, + "middlewareAssignment": middlewareAssignment, + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } diff --git a/tools/goctl/api/gogen/gentypes.go b/tools/goctl/api/gogen/gentypes.go index 3e466575..4dbd98f3 100644 --- a/tools/goctl/api/gogen/gentypes.go +++ b/tools/goctl/api/gogen/gentypes.go @@ -1,14 +1,12 @@ package gogen import ( - "bytes" "errors" "fmt" "io" "os" "path" "strings" - "text/template" "github.com/tal-tech/go-zero/tools/goctl/api/spec" apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" @@ -59,29 +57,19 @@ func genTypes(dir string, cfg *config.Config, api *spec.ApiSpec) error { filename := path.Join(dir, typesDir, typeFilename) os.Remove(filename) - fp, created, err := apiutil.MaybeCreateFile(dir, typesDir, typeFilename) - if err != nil { - return err - } - - if !created { - return nil - } - defer fp.Close() - - t := template.Must(template.New("typesTemplate").Parse(typesTemplate)) - buffer := new(bytes.Buffer) - err = t.Execute(buffer, map[string]interface{}{ - "types": val, - "containsTime": api.ContainsTime(), + return genFile(fileGenConfig{ + dir: dir, + subdir: typesDir, + filename: typeFilename, + templateName: "typesTemplate", + category: "", + templateFile: "", + builtinTemplate: typesTemplate, + data: map[string]interface{}{ + "types": val, + "containsTime": api.ContainsTime(), + }, }) - if err != nil { - return err - } - - formatCode := formatCode(buffer.String()) - _, err = fp.WriteString(formatCode) - return err } func convertTypeCase(types []spec.Type, t string) (string, error) { diff --git a/tools/goctl/api/gogen/util.go b/tools/goctl/api/gogen/util.go index 0e42e986..cf554980 100644 --- a/tools/goctl/api/gogen/util.go +++ b/tools/goctl/api/gogen/util.go @@ -1,18 +1,64 @@ package gogen import ( + "bytes" "fmt" goformat "go/format" "io" "path/filepath" "strings" + "text/template" "github.com/tal-tech/go-zero/core/collection" "github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/tal-tech/go-zero/tools/goctl/api/util" + ctlutil "github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util/ctx" ) +type fileGenConfig struct { + dir string + subdir string + filename string + templateName string + category string + templateFile string + builtinTemplate string + data interface{} +} + +func genFile(c fileGenConfig) error { + fp, created, err := util.MaybeCreateFile(c.dir, c.subdir, c.filename) + if err != nil { + return err + } + if !created { + return nil + } + defer fp.Close() + + var text string + if len(c.category) == 0 || len(c.templateFile) == 0 { + text = c.builtinTemplate + } else { + text, err = ctlutil.LoadTemplate(c.category, c.templateFile, c.builtinTemplate) + if err != nil { + return err + } + } + + t := template.Must(template.New(c.templateName).Parse(text)) + buffer := new(bytes.Buffer) + err = t.Execute(buffer, c.data) + if err != nil { + return err + } + + code := formatCode(buffer.String()) + _, err = fp.WriteString(code) + return err +} + func getParentPackage(dir string) (string, error) { abs, err := filepath.Abs(dir) if err != nil {