Kaynağa Gözat

remove duplicated code in goctl (#369)

Kevin Wan 4 yıl önce
ebeveyn
işleme
8774d72ddb

+ 8 - 2
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. 微信公众号
 

+ 12 - 30
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
 }

+ 13 - 30
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
 }

+ 10 - 26
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 {

+ 16 - 34
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 {

+ 12 - 30
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 {

+ 11 - 24
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
 }

+ 12 - 22
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 {

+ 16 - 33
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
 }

+ 12 - 24
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) {

+ 46 - 0
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 {