Jelajahi Sumber

Code optimized (#523)

* optimized markdown generator

* optimized markdown generator

* optimized markdown generator

* add more comment

* add comment

* add comment

* add comments for rpc tool

* add comments for model tool

* add comments for model tool

* add comments for model tool

* add comments for config tool

* add comments for config tool

* add comments

* add comments

* add comments

* add comments

* add comment

* remove rpc main head info

* add comment

* optimized

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
kingxt 3 tahun lalu
induk
melakukan
e6ef1fca12
100 mengubah file dengan 639 tambahan dan 280 penghapusan
  1. 1 1
      tools/goctl/api/docgen/gen.go
  2. 7 5
      tools/goctl/api/format/format.go
  3. 2 0
      tools/goctl/api/gogen/gen.go
  4. 3 3
      tools/goctl/api/gogen/genhandlers.go
  5. 1 0
      tools/goctl/api/gogen/gentypes.go
  6. 1 0
      tools/goctl/api/javagen/gen.go
  7. 1 0
      tools/goctl/api/ktgen/cmd.go
  8. 2 1
      tools/goctl/api/new/newservice.go
  9. 5 0
      tools/goctl/api/parser/g4/ast/api.go
  10. 6 0
      tools/goctl/api/parser/g4/ast/apiparser.go
  11. 12 0
      tools/goctl/api/parser/g4/ast/ast.go
  12. 10 0
      tools/goctl/api/parser/g4/ast/import.go
  13. 4 0
      tools/goctl/api/parser/g4/ast/info.go
  14. 6 0
      tools/goctl/api/parser/g4/ast/kv.go
  15. 2 0
      tools/goctl/api/parser/g4/ast/placeholder.go
  16. 41 1
      tools/goctl/api/parser/g4/ast/service.go
  17. 6 0
      tools/goctl/api/parser/g4/ast/syntax.go
  18. 66 2
      tools/goctl/api/parser/g4/ast/type.go
  19. 1 1
      tools/goctl/api/parser/g4/gen/api/apiparser_parser.go
  20. 4 1
      tools/goctl/api/parser/g4/gen/api/baseparser.go
  21. 13 13
      tools/goctl/api/parser/g4/test/apiparser_test.go
  22. 2 0
      tools/goctl/api/parser/parser.go
  23. 16 16
      tools/goctl/api/spec/fn.go
  24. 6 0
      tools/goctl/api/spec/name.go
  25. 18 1
      tools/goctl/api/spec/spec.go
  26. 6 0
      tools/goctl/api/spec/tags.go
  27. 4 3
      tools/goctl/api/tsgen/gen.go
  28. 7 7
      tools/goctl/api/tsgen/genpacket.go
  29. 1 1
      tools/goctl/api/tsgen/util.go
  30. 11 7
      tools/goctl/api/util/case.go
  31. 6 0
      tools/goctl/api/util/util.go
  32. 1 0
      tools/goctl/api/validate/validate.go
  33. 3 84
      tools/goctl/config/config.go
  34. 1 0
      tools/goctl/configgen/genconfig.go
  35. 2 0
      tools/goctl/docker/docker.go
  36. 5 0
      tools/goctl/docker/template.go
  37. 4 4
      tools/goctl/goctl.go
  38. 1 0
      tools/goctl/kube/kube.go
  39. 4 0
      tools/goctl/model/sql/builderx/builder.go
  40. 14 14
      tools/goctl/model/sql/builderx/builder_test.go
  41. 4 2
      tools/goctl/model/sql/command/command.go
  42. 1 0
      tools/goctl/model/sql/converter/types.go
  43. 0 5
      tools/goctl/model/sql/gen/error.go
  44. 4 0
      tools/goctl/model/sql/gen/gen.go
  45. 1 1
      tools/goctl/model/sql/gen/gen_test.go
  46. 15 10
      tools/goctl/model/sql/gen/keys.go
  47. 5 0
      tools/goctl/model/sql/gen/template.go
  48. 7 2
      tools/goctl/model/sql/model/informationschemamodel.go
  49. 7 0
      tools/goctl/model/sql/parser/parser.go
  50. 2 0
      tools/goctl/model/sql/template/delete.go
  51. 1 0
      tools/goctl/model/sql/template/errors.go
  52. 1 0
      tools/goctl/model/sql/template/field.go
  53. 2 0
      tools/goctl/model/sql/template/import.go
  54. 2 0
      tools/goctl/model/sql/template/insert.go
  55. 1 0
      tools/goctl/model/sql/template/model.go
  56. 1 0
      tools/goctl/model/sql/template/new.go
  57. 1 0
      tools/goctl/model/sql/template/tag.go
  58. 1 0
      tools/goctl/model/sql/template/types.go
  59. 2 0
      tools/goctl/model/sql/template/update.go
  60. 1 0
      tools/goctl/model/sql/template/vars.go
  61. 28 28
      tools/goctl/model/sql/test/model/model_test.go
  62. 13 10
      tools/goctl/model/sql/test/model/studentmodel.go
  63. 5 2
      tools/goctl/model/sql/test/model/usermodel.go
  64. 1 0
      tools/goctl/model/sql/test/model/vars.go
  65. 7 3
      tools/goctl/model/sql/test/orm.go
  66. 9 0
      tools/goctl/model/sql/test/sqlconn.go
  67. 0 5
      tools/goctl/model/sql/test/utils.go
  68. 1 1
      tools/goctl/model/sql/util/matcher.go
  69. 1 0
      tools/goctl/model/sql/util/slice.go
  70. 3 0
      tools/goctl/plugin/plugin.go
  71. 8 7
      tools/goctl/rpc/cli/cli.go
  72. 3 0
      tools/goctl/rpc/execx/execx.go
  73. 8 4
      tools/goctl/rpc/generator/defaultgenerator.go
  74. 12 6
      tools/goctl/rpc/generator/gen.go
  75. 1 1
      tools/goctl/rpc/generator/gen_test.go
  76. 5 3
      tools/goctl/rpc/generator/gencall.go
  77. 5 1
      tools/goctl/rpc/generator/genconfig.go
  78. 1 0
      tools/goctl/rpc/generator/generator.go
  79. 3 1
      tools/goctl/rpc/generator/genetc.go
  80. 3 2
      tools/goctl/rpc/generator/genlogic.go
  81. 3 6
      tools/goctl/rpc/generator/genmain.go
  82. 3 1
      tools/goctl/rpc/generator/genpb.go
  83. 3 2
      tools/goctl/rpc/generator/genserver.go
  84. 3 1
      tools/goctl/rpc/generator/gensvc.go
  85. 4 0
      tools/goctl/rpc/generator/mkdir.go
  86. 1 0
      tools/goctl/rpc/generator/prototmpl.go
  87. 7 0
      tools/goctl/rpc/generator/template.go
  88. 1 0
      tools/goctl/rpc/parser/comment.go
  89. 1 0
      tools/goctl/rpc/parser/import.go
  90. 3 2
      tools/goctl/rpc/parser/message.go
  91. 1 0
      tools/goctl/rpc/parser/option.go
  92. 10 6
      tools/goctl/rpc/parser/parser.go
  93. 1 0
      tools/goctl/rpc/parser/proto.go
  94. 1 0
      tools/goctl/rpc/parser/rpc.go
  95. 2 0
      tools/goctl/rpc/parser/service.go
  96. 5 0
      tools/goctl/tpl/templates.go
  97. 1 0
      tools/goctl/update/config/config.go
  98. 2 0
      tools/goctl/upgrade/upgrade.go
  99. 2 2
      tools/goctl/util/console/console.go
  100. 103 1
      tools/goctl/util/file.go

+ 1 - 1
tools/goctl/api/docgen/gen.go

@@ -29,7 +29,7 @@ func DocCommand(c *cli.Context) error {
 	}
 
 	if !util.FileExists(dir) {
-		return errors.New(fmt.Sprintf("dir %s not exsit", dir))
+		return fmt.Errorf("dir %s not exsit", dir)
 	}
 
 	dir, err := filepath.Abs(dir)

+ 7 - 5
tools/goctl/api/format/format.go

@@ -25,12 +25,13 @@ const (
 	rightBrace       = "}"
 )
 
+// GoFormatApi format api file
 func GoFormatApi(c *cli.Context) error {
 	useStdin := c.Bool("stdin")
 
 	var be errorx.BatchError
 	if useStdin {
-		if err := ApiFormatByStdin(); err != nil {
+		if err := apiFormatByStdin(); err != nil {
 			be.Add(err)
 		}
 	} else {
@@ -63,7 +64,7 @@ func GoFormatApi(c *cli.Context) error {
 	return be.Err()
 }
 
-func ApiFormatByStdin() error {
+func apiFormatByStdin() error {
 	data, err := ioutil.ReadAll(os.Stdin)
 	if err != nil {
 		return err
@@ -78,6 +79,7 @@ func ApiFormatByStdin() error {
 	return err
 }
 
+// ApiFormatByPath format api from file path
 func ApiFormatByPath(apiFilePath string) error {
 	data, err := ioutil.ReadFile(apiFilePath)
 	if err != nil {
@@ -135,19 +137,19 @@ func apiFormat(data string) (string, error) {
 
 		noCommentLine := util.RemoveComment(line)
 		if noCommentLine == rightParenthesis || noCommentLine == rightBrace {
-			tapCount -= 1
+			tapCount--
 		}
 		if tapCount < 0 {
 			line := strings.TrimSuffix(noCommentLine, rightBrace)
 			line = strings.TrimSpace(line)
 			if strings.HasSuffix(line, leftBrace) {
-				tapCount += 1
+				tapCount++
 			}
 		}
 		util.WriteIndent(&builder, tapCount)
 		builder.WriteString(line + ctlutil.NL)
 		if strings.HasSuffix(noCommentLine, leftParenthesis) || strings.HasSuffix(noCommentLine, leftBrace) {
-			tapCount += 1
+			tapCount++
 		}
 		preLine = line
 	}

+ 2 - 0
tools/goctl/api/gogen/gen.go

@@ -25,6 +25,7 @@ const tmpFile = "%s-%d"
 
 var tmpDir = path.Join(os.TempDir(), "goctl")
 
+// GoCommand gen go project files from command line
 func GoCommand(c *cli.Context) error {
 	apiFile := c.String("api")
 	dir := c.String("dir")
@@ -40,6 +41,7 @@ func GoCommand(c *cli.Context) error {
 	return DoGenProject(apiFile, dir, namingStyle)
 }
 
+// DoGenProject gen go project files with api file
 func DoGenProject(apiFile, dir, style string) error {
 	api, err := parser.Parse(apiFile)
 	if err != nil {

+ 3 - 3
tools/goctl/api/gogen/genhandlers.go

@@ -39,7 +39,7 @@ func {{.HandlerName}}(ctx *svc.ServiceContext) http.HandlerFunc {
 }
 `
 
-type Handler struct {
+type handlerInfo struct {
 	ImportPackages string
 	HandlerName    string
 	RequestType    string
@@ -59,7 +59,7 @@ func genHandler(dir string, cfg *config.Config, group spec.Group, route spec.Rou
 		return err
 	}
 
-	return doGenToFile(dir, handler, cfg, group, route, Handler{
+	return doGenToFile(dir, handler, cfg, group, route, handlerInfo{
 		ImportPackages: genHandlerImports(group, route, parentPkg),
 		HandlerName:    handler,
 		RequestType:    util.Title(route.RequestTypeName()),
@@ -71,7 +71,7 @@ func genHandler(dir string, cfg *config.Config, group spec.Group, route spec.Rou
 }
 
 func doGenToFile(dir, handler string, cfg *config.Config, group spec.Group,
-	route spec.Route, handleObj Handler) error {
+	route spec.Route, handleObj handlerInfo) error {
 	filename, err := format.FileNamingFormat(cfg.NamingFormat, handler)
 	if err != nil {
 		return err

+ 1 - 0
tools/goctl/api/gogen/gentypes.go

@@ -25,6 +25,7 @@ import (
 `
 )
 
+// BuildTypes gen types to string
 func BuildTypes(types []spec.Type) (string, error) {
 	var builder strings.Builder
 	first := true

+ 1 - 0
tools/goctl/api/javagen/gen.go

@@ -12,6 +12,7 @@ import (
 	"github.com/urfave/cli"
 )
 
+// JavaCommand the generate java code command entrance
 func JavaCommand(c *cli.Context) error {
 	apiFile := c.String("api")
 	dir := c.String("dir")

+ 1 - 0
tools/goctl/api/ktgen/cmd.go

@@ -7,6 +7,7 @@ import (
 	"github.com/urfave/cli"
 )
 
+// KtCommand the generate kotlin code command entrance
 func KtCommand(c *cli.Context) error {
 	apiFile := c.String("api")
 	if apiFile == "" {

+ 2 - 1
tools/goctl/api/new/newservice.go

@@ -27,7 +27,8 @@ service {{.name}}-api {
 }
 `
 
-func NewService(c *cli.Context) error {
+// CreateServiceCommand fast create service
+func CreateServiceCommand(c *cli.Context) error {
 	args := c.Args()
 	dirName := args.First()
 	if len(dirName) == 0 {

+ 5 - 0
tools/goctl/api/parser/g4/ast/api.go

@@ -7,6 +7,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
 )
 
+// Api describes syntax for api
 type Api struct {
 	LinePrefix string
 	Syntax     *SyntaxExpr
@@ -21,6 +22,7 @@ type Api struct {
 	routeM     map[string]PlaceHolder
 }
 
+// VisitApi implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitApi(ctx *api.ApiContext) interface{} {
 	var final Api
 	final.importM = map[string]PlaceHolder{}
@@ -152,6 +154,7 @@ func (v *ApiVisitor) acceptSyntax(root *Api, final *Api) {
 	}
 }
 
+// VisitSpec implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitSpec(ctx *api.SpecContext) interface{} {
 	var root Api
 	if ctx.SyntaxLit() != nil {
@@ -178,11 +181,13 @@ func (v *ApiVisitor) VisitSpec(ctx *api.SpecContext) interface{} {
 	return &root
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *Api) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Api are equal
 func (a *Api) Equal(v interface{}) bool {
 	if v == nil {
 		return false

+ 6 - 0
tools/goctl/api/parser/g4/ast/apiparser.go

@@ -12,6 +12,7 @@ import (
 )
 
 type (
+	// Parser provides api parsing capabilities
 	Parser struct {
 		linePrefix string
 		debug      bool
@@ -19,9 +20,11 @@ type (
 		antlr.DefaultErrorListener
 	}
 
+	// ParserOption defines an function with argument Parser
 	ParserOption func(p *Parser)
 )
 
+// NewParser creates an instance for Parser
 func NewParser(options ...ParserOption) *Parser {
 	p := &Parser{
 		log: console.NewColorConsole(),
@@ -425,6 +428,7 @@ func (p *Parser) readContent(filename string) (string, error) {
 	return string(data), nil
 }
 
+// SyntaxError accepts errors and panic it
 func (p *Parser) SyntaxError(_ antlr.Recognizer, _ interface{}, line, column int, msg string, _ antlr.RecognitionException) {
 	str := fmt.Sprintf(`%s line %d:%d  %s`, p.linePrefix, line, column, msg)
 	if p.debug {
@@ -433,12 +437,14 @@ func (p *Parser) SyntaxError(_ antlr.Recognizer, _ interface{}, line, column int
 	panic(str)
 }
 
+// WithParserDebug returns a debug ParserOption
 func WithParserDebug() ParserOption {
 	return func(p *Parser) {
 		p.debug = true
 	}
 }
 
+// WithParserPrefix returns a prefix ParserOption
 func WithParserPrefix(prefix string) ParserOption {
 	return func(p *Parser) {
 		p.linePrefix = prefix

+ 12 - 0
tools/goctl/api/parser/g4/ast/ast.go

@@ -12,11 +12,15 @@ import (
 )
 
 type (
+	// TokenStream defines a token
 	TokenStream interface {
 		GetStart() antlr.Token
 		GetStop() antlr.Token
 		GetParser() antlr.Parser
 	}
+
+	// ApiVisitor wraps api.BaseApiParserVisitor to call methods which has prefix Visit to
+	// visit node from the api syntax
 	ApiVisitor struct {
 		api.BaseApiParserVisitor
 		debug    bool
@@ -25,8 +29,10 @@ type (
 		infoFlag bool
 	}
 
+	// VisitorOption defines a function with argument ApiVisitor
 	VisitorOption func(v *ApiVisitor)
 
+	// Spec describes api spec
 	Spec interface {
 		Doc() []Expr
 		Comment() Expr
@@ -34,6 +40,7 @@ type (
 		Equal(v interface{}) bool
 	}
 
+	// Expr describes ast expression
 	Expr interface {
 		Prefix() string
 		Line() int
@@ -47,6 +54,7 @@ type (
 	}
 )
 
+// NewApiVisitor creates an instance for ApiVisitor
 func NewApiVisitor(options ...VisitorOption) *ApiVisitor {
 	v := &ApiVisitor{
 		log: console.NewColorConsole(),
@@ -66,12 +74,14 @@ func (v *ApiVisitor) panic(expr Expr, msg string) {
 	panic(errString)
 }
 
+// WithVisitorPrefix returns a VisitorOption wrap with specified prefix
 func WithVisitorPrefix(prefix string) VisitorOption {
 	return func(v *ApiVisitor) {
 		v.prefix = prefix
 	}
 }
 
+// WithVisitorDebug returns a debug VisitorOption
 func WithVisitorDebug() VisitorOption {
 	return func(v *ApiVisitor) {
 		v.debug = true
@@ -84,6 +94,7 @@ type defaultExpr struct {
 	start, stop  int
 }
 
+// NewTextExpr creates a default instance for Expr
 func NewTextExpr(v string) *defaultExpr {
 	return &defaultExpr{
 		v: v,
@@ -201,6 +212,7 @@ func (e *defaultExpr) IsNotNil() bool {
 	return e != nil
 }
 
+// EqualDoc compares whether the element literals in two Spec are equal
 func EqualDoc(spec1, spec2 Spec) bool {
 	if spec1 == nil {
 		return spec2 == nil

+ 10 - 0
tools/goctl/api/parser/g4/ast/import.go

@@ -4,6 +4,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
 )
 
+// ImportExpr defines import syntax for api
 type ImportExpr struct {
 	Import      Expr
 	Value       Expr
@@ -11,6 +12,7 @@ type ImportExpr struct {
 	CommentExpr Expr
 }
 
+// VisitImportSpec implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitImportSpec(ctx *api.ImportSpecContext) interface{} {
 	var list []*ImportExpr
 	if ctx.ImportLit() != nil {
@@ -25,6 +27,7 @@ func (v *ApiVisitor) VisitImportSpec(ctx *api.ImportSpecContext) interface{} {
 	return list
 }
 
+// VisitImportLit implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitImportLit(ctx *api.ImportLitContext) interface{} {
 	importToken := v.newExprWithToken(ctx.GetImportToken())
 	valueExpr := ctx.ImportValue().Accept(v).(Expr)
@@ -38,6 +41,7 @@ func (v *ApiVisitor) VisitImportLit(ctx *api.ImportLitContext) interface{} {
 	}
 }
 
+// VisitImportBlock implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitImportBlock(ctx *api.ImportBlockContext) interface{} {
 	importToken := v.newExprWithToken(ctx.GetImportToken())
 	values := ctx.AllImportBlockValue()
@@ -52,6 +56,7 @@ func (v *ApiVisitor) VisitImportBlock(ctx *api.ImportBlockContext) interface{} {
 	return list
 }
 
+// VisitImportBlockValue implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitImportBlockValue(ctx *api.ImportBlockValueContext) interface{} {
 	value := ctx.ImportValue().Accept(v).(Expr)
 	return &ImportExpr{
@@ -61,15 +66,18 @@ func (v *ApiVisitor) VisitImportBlockValue(ctx *api.ImportBlockValueContext) int
 	}
 }
 
+// VisitImportValue implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitImportValue(ctx *api.ImportValueContext) interface{} {
 	return v.newExprWithTerminalNode(ctx.STRING())
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (i *ImportExpr) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two ImportExpr are equal
 func (i *ImportExpr) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -87,10 +95,12 @@ func (i *ImportExpr) Equal(v interface{}) bool {
 	return i.Import.Equal(imp.Import) && i.Value.Equal(imp.Value)
 }
 
+// Doc returns the document of ImportExpr, like // some text
 func (i *ImportExpr) Doc() []Expr {
 	return i.DocExpr
 }
 
+// Comment returns the comment of ImportExpr, like // some text
 func (i *ImportExpr) Comment() Expr {
 	return i.CommentExpr
 }

+ 4 - 0
tools/goctl/api/parser/g4/ast/info.go

@@ -4,6 +4,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
 )
 
+// InfoExpr defines info syntax for api
 type InfoExpr struct {
 	Info Expr
 	Lp   Expr
@@ -11,6 +12,7 @@ type InfoExpr struct {
 	Kvs  []*KvExpr
 }
 
+// VisitInfoSpec implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitInfoSpec(ctx *api.InfoSpecContext) interface{} {
 	var expr InfoExpr
 	expr.Info = v.newExprWithToken(ctx.GetInfoToken())
@@ -29,11 +31,13 @@ func (v *ApiVisitor) VisitInfoSpec(ctx *api.InfoSpecContext) interface{} {
 	return &expr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (i *InfoExpr) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two InfoExpr are equal
 func (i *InfoExpr) Equal(v interface{}) bool {
 	if v == nil {
 		return false

+ 6 - 0
tools/goctl/api/parser/g4/ast/kv.go

@@ -6,6 +6,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
 )
 
+// KvExpr describes key-value for api
 type KvExpr struct {
 	Key         Expr
 	Value       Expr
@@ -13,6 +14,7 @@ type KvExpr struct {
 	CommentExpr Expr
 }
 
+// VisitKvLit implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitKvLit(ctx *api.KvLitContext) interface{} {
 	var kvExpr KvExpr
 	kvExpr.Key = v.newExprWithToken(ctx.GetKey())
@@ -48,11 +50,13 @@ func (v *ApiVisitor) VisitKvLit(ctx *api.KvLitContext) interface{} {
 	return &kvExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (k *KvExpr) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two KvExpr are equal
 func (k *KvExpr) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -70,10 +74,12 @@ func (k *KvExpr) Equal(v interface{}) bool {
 	return k.Key.Equal(kv.Key) && k.Value.Equal(kv.Value)
 }
 
+// Doc returns the document of KvExpr, like // some text
 func (k *KvExpr) Doc() []Expr {
 	return k.DocExpr
 }
 
+// Comment returns the comment of KvExpr, like // some text
 func (k *KvExpr) Comment() Expr {
 	return k.CommentExpr
 }

+ 2 - 0
tools/goctl/api/parser/g4/ast/placeholder.go

@@ -1,5 +1,7 @@
 package ast
 
+// Holder defines a default instance for PlaceHolder
 var Holder PlaceHolder
 
+// PlaceHolder defines an empty struct
 type PlaceHolder struct{}

+ 41 - 1
tools/goctl/api/parser/g4/ast/service.go

@@ -7,13 +7,16 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
 )
 
+// Service describes service for api syntax
 type Service struct {
 	AtServer   *AtServer
 	ServiceApi *ServiceApi
 }
 
+// KV defines a slice for KvExpr
 type KV []*KvExpr
 
+// AtServer describes server metadata for api syntax
 type AtServer struct {
 	AtServerToken Expr
 	Lp            Expr
@@ -21,6 +24,7 @@ type AtServer struct {
 	Kv            KV
 }
 
+// ServiceApi describes service ast for api syntax
 type ServiceApi struct {
 	ServiceToken Expr
 	Name         Expr
@@ -29,6 +33,7 @@ type ServiceApi struct {
 	ServiceRoute []*ServiceRoute
 }
 
+// ServiceRoute describes service route ast for api syntax
 type ServiceRoute struct {
 	AtDoc     *AtDoc
 	AtServer  *AtServer
@@ -36,6 +41,7 @@ type ServiceRoute struct {
 	Route     *Route
 }
 
+// AtDoc describes service comments ast for api syntax
 type AtDoc struct {
 	AtDocToken Expr
 	Lp         Expr
@@ -44,6 +50,7 @@ type AtDoc struct {
 	Kv         []*KvExpr
 }
 
+// AtHandler describes service hander ast for api syntax
 type AtHandler struct {
 	AtHandlerToken Expr
 	Name           Expr
@@ -51,6 +58,7 @@ type AtHandler struct {
 	CommentExpr    Expr
 }
 
+// Route describes route ast for api syntax
 type Route struct {
 	Method      Expr
 	Path        Expr
@@ -61,12 +69,14 @@ type Route struct {
 	CommentExpr Expr
 }
 
+// Body describes request,response body ast for api syntax
 type Body struct {
 	Lp   Expr
 	Rp   Expr
 	Name DataType
 }
 
+// VisitServiceSpec implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitServiceSpec(ctx *api.ServiceSpecContext) interface{} {
 	var serviceSpec Service
 	if ctx.AtServer() != nil {
@@ -77,6 +87,7 @@ func (v *ApiVisitor) VisitServiceSpec(ctx *api.ServiceSpecContext) interface{} {
 	return &serviceSpec
 }
 
+// VisitAtServer implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitAtServer(ctx *api.AtServerContext) interface{} {
 	var atServer AtServer
 	atServer.AtServerToken = v.newExprWithTerminalNode(ctx.ATSERVER())
@@ -90,6 +101,7 @@ func (v *ApiVisitor) VisitAtServer(ctx *api.AtServerContext) interface{} {
 	return &atServer
 }
 
+// VisitServiceApi implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitServiceApi(ctx *api.ServiceApiContext) interface{} {
 	var serviceApi ServiceApi
 	serviceApi.ServiceToken = v.newExprWithToken(ctx.GetServiceToken())
@@ -105,6 +117,7 @@ func (v *ApiVisitor) VisitServiceApi(ctx *api.ServiceApiContext) interface{} {
 	return &serviceApi
 }
 
+// VisitServiceRoute implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitServiceRoute(ctx *api.ServiceRouteContext) interface{} {
 	var serviceRoute ServiceRoute
 	if ctx.AtDoc() != nil {
@@ -121,6 +134,7 @@ func (v *ApiVisitor) VisitServiceRoute(ctx *api.ServiceRouteContext) interface{}
 	return &serviceRoute
 }
 
+// VisitAtDoc implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitAtDoc(ctx *api.AtDocContext) interface{} {
 	var atDoc AtDoc
 	atDoc.AtDocToken = v.newExprWithTerminalNode(ctx.ATDOC())
@@ -150,6 +164,7 @@ func (v *ApiVisitor) VisitAtDoc(ctx *api.AtDocContext) interface{} {
 	return &atDoc
 }
 
+// VisitAtHandler implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitAtHandler(ctx *api.AtHandlerContext) interface{} {
 	var atHandler AtHandler
 	astHandlerExpr := v.newExprWithTerminalNode(ctx.ATHANDLER())
@@ -160,6 +175,7 @@ func (v *ApiVisitor) VisitAtHandler(ctx *api.AtHandlerContext) interface{} {
 	return &atHandler
 }
 
+// VisitRoute implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitRoute(ctx *api.RouteContext) interface{} {
 	var route Route
 	path := ctx.Path()
@@ -193,6 +209,7 @@ func (v *ApiVisitor) VisitRoute(ctx *api.RouteContext) interface{} {
 	return &route
 }
 
+// VisitBody implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitBody(ctx *api.BodyContext) interface{} {
 	if ctx.ID() == nil {
 		return nil
@@ -211,7 +228,7 @@ func (v *ApiVisitor) VisitBody(ctx *api.BodyContext) interface{} {
 	}
 }
 
-// note: forward compatible
+// VisitReplybody implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitReplybody(ctx *api.ReplybodyContext) interface{} {
 	if ctx.DataType() == nil {
 		return nil
@@ -253,10 +270,13 @@ func (v *ApiVisitor) VisitReplybody(ctx *api.ReplybodyContext) interface{} {
 	}
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (b *Body) Format() error {
 	// todo
 	return nil
 }
+
+// Equal compares whether the element literals in two Body are equal
 func (b *Body) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -278,19 +298,23 @@ func (b *Body) Equal(v interface{}) bool {
 	return b.Name.Equal(body.Name)
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (r *Route) Format() error {
 	// todo
 	return nil
 }
 
+// Doc returns the document of Route, like // some text
 func (r *Route) Doc() []Expr {
 	return r.DocExpr
 }
 
+// Comment returns the comment of Route, like // some text
 func (r *Route) Comment() Expr {
 	return r.CommentExpr
 }
 
+// Equal compares whether the element literals in two Route are equal
 func (r *Route) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -330,19 +354,23 @@ func (r *Route) Equal(v interface{}) bool {
 	return EqualDoc(r, route)
 }
 
+// Doc returns the document of AtHandler, like // some text
 func (a *AtHandler) Doc() []Expr {
 	return a.DocExpr
 }
 
+// Comment returns the comment of AtHandler, like // some text
 func (a *AtHandler) Comment() Expr {
 	return a.CommentExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *AtHandler) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two AtHandler are equal
 func (a *AtHandler) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -364,11 +392,13 @@ func (a *AtHandler) Equal(v interface{}) bool {
 	return EqualDoc(a, atHandler)
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *AtDoc) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two AtDoc are equal
 func (a *AtDoc) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -419,11 +449,13 @@ func (a *AtDoc) Equal(v interface{}) bool {
 	return true
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *AtServer) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two AtServer are equal
 func (a *AtServer) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -471,6 +503,7 @@ func (a *AtServer) Equal(v interface{}) bool {
 	return true
 }
 
+// Equal compares whether the element literals in two ServiceRoute are equal
 func (s *ServiceRoute) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -500,11 +533,13 @@ func (s *ServiceRoute) Equal(v interface{}) bool {
 	return s.Route.Equal(sr.Route)
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (s *ServiceRoute) Format() error {
 	// todo
 	return nil
 }
 
+// GetHandler returns handler name of api route
 func (s *ServiceRoute) GetHandler() Expr {
 	if s.AtHandler != nil {
 		return s.AtHandler.Name
@@ -513,11 +548,13 @@ func (s *ServiceRoute) GetHandler() Expr {
 	return s.AtServer.Kv.Get("handler")
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *ServiceApi) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two ServiceApi are equal
 func (a *ServiceApi) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -569,11 +606,13 @@ func (a *ServiceApi) Equal(v interface{}) bool {
 	return true
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (s *Service) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Service are equal
 func (s *Service) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -593,6 +632,7 @@ func (s *Service) Equal(v interface{}) bool {
 	return s.ServiceApi.Equal(service.ServiceApi)
 }
 
+// Get returns the tergate KV by specified key
 func (kv KV) Get(key string) Expr {
 	for _, each := range kv {
 		if each.Key.Text() == key {

+ 6 - 0
tools/goctl/api/parser/g4/ast/syntax.go

@@ -4,6 +4,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
 )
 
+// SyntaxExpr describes syntax for api
 type SyntaxExpr struct {
 	Syntax      Expr
 	Assign      Expr
@@ -12,6 +13,7 @@ type SyntaxExpr struct {
 	CommentExpr Expr
 }
 
+// VisitSyntaxLit implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitSyntaxLit(ctx *api.SyntaxLitContext) interface{} {
 	syntax := v.newExprWithToken(ctx.GetSyntaxToken())
 	assign := v.newExprWithToken(ctx.GetAssign())
@@ -25,11 +27,13 @@ func (v *ApiVisitor) VisitSyntaxLit(ctx *api.SyntaxLitContext) interface{} {
 	}
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (s *SyntaxExpr) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two SyntaxExpr are equal
 func (s *SyntaxExpr) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -49,10 +53,12 @@ func (s *SyntaxExpr) Equal(v interface{}) bool {
 		s.Version.Equal(syntax.Version)
 }
 
+// Doc returns the document of SyntaxExpr, like // some text
 func (s *SyntaxExpr) Doc() []Expr {
 	return s.DocExpr
 }
 
+// Comment returns the comment of SyntaxExpr, like // some text
 func (s *SyntaxExpr) Comment() Expr {
 	return s.CommentExpr
 }

+ 66 - 2
tools/goctl/api/parser/g4/ast/type.go

@@ -9,13 +9,15 @@ import (
 )
 
 type (
-	// TypeAlias、 TypeStruct
+	// TypeExpr describes an expression for TypeAlias and TypeStruct
 	TypeExpr interface {
 		Doc() []Expr
 		Format() error
 		Equal(v interface{}) bool
 		NameExpr() Expr
 	}
+
+	// TypeAlias describes alias ast for api syatax
 	TypeAlias struct {
 		Name        Expr
 		Assign      Expr
@@ -24,6 +26,7 @@ type (
 		CommentExpr Expr
 	}
 
+	// TypeStruct describes structure ast for api syatax
 	TypeStruct struct {
 		Name    Expr
 		Struct  Expr
@@ -33,6 +36,7 @@ type (
 		Fields  []*TypeField
 	}
 
+	// TypeField describes field ast for api syntax
 	TypeField struct {
 		IsAnonymous bool
 		// Name is nil if IsAnonymous
@@ -43,6 +47,7 @@ type (
 		CommentExpr Expr
 	}
 
+	// DataType describes datatype for api syntax, the default implementation expressions are
 	// Literal, Interface, Map, Array, Time, Pointer
 	DataType interface {
 		Expr() Expr
@@ -51,15 +56,18 @@ type (
 		IsNotNil() bool
 	}
 
-	// int, bool, Foo,...
+	// Literal describes the basic types of golang, non-reference types,
+	// such as int, bool, Foo,...
 	Literal struct {
 		Literal Expr
 	}
 
+	// Interface describes the interface type of golang,Its fixed value is interface{}
 	Interface struct {
 		Literal Expr
 	}
 
+	// Map describes the map ast for api syntax
 	Map struct {
 		MapExpr Expr
 		Map     Expr
@@ -69,6 +77,7 @@ type (
 		Value   DataType
 	}
 
+	// Array describes the slice ast for api syntax
 	Array struct {
 		ArrayExpr Expr
 		LBrack    Expr
@@ -76,10 +85,12 @@ type (
 		Literal   DataType
 	}
 
+	// Time describes the time ast for api syntax
 	Time struct {
 		Literal Expr
 	}
 
+	// Pointer describes the pointer ast for api syntax
 	Pointer struct {
 		PointerExpr Expr
 		Star        Expr
@@ -87,6 +98,7 @@ type (
 	}
 )
 
+// VisitTypeSpec implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeSpec(ctx *api.TypeSpecContext) interface{} {
 	if ctx.TypeLit() != nil {
 		return []TypeExpr{ctx.TypeLit().Accept(v).(TypeExpr)}
@@ -94,6 +106,7 @@ func (v *ApiVisitor) VisitTypeSpec(ctx *api.TypeSpecContext) interface{} {
 	return ctx.TypeBlock().Accept(v)
 }
 
+// VisitTypeLit implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeLit(ctx *api.TypeLitContext) interface{} {
 	typeLit := ctx.TypeLitBody().Accept(v)
 	alias, ok := typeLit.(*TypeAlias)
@@ -109,6 +122,7 @@ func (v *ApiVisitor) VisitTypeLit(ctx *api.TypeLitContext) interface{} {
 	return typeLit
 }
 
+// VisitTypeBlock implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeBlock(ctx *api.TypeBlockContext) interface{} {
 	list := ctx.AllTypeBlockBody()
 	var types []TypeExpr
@@ -119,6 +133,7 @@ func (v *ApiVisitor) VisitTypeBlock(ctx *api.TypeBlockContext) interface{} {
 	return types
 }
 
+// VisitTypeLitBody implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeLitBody(ctx *api.TypeLitBodyContext) interface{} {
 	if ctx.TypeAlias() != nil {
 		return ctx.TypeAlias().Accept(v)
@@ -126,6 +141,7 @@ func (v *ApiVisitor) VisitTypeLitBody(ctx *api.TypeLitBodyContext) interface{} {
 	return ctx.TypeStruct().Accept(v)
 }
 
+// VisitTypeBlockBody implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeBlockBody(ctx *api.TypeBlockBodyContext) interface{} {
 	if ctx.TypeBlockAlias() != nil {
 		return ctx.TypeBlockAlias().Accept(v).(*TypeAlias)
@@ -133,6 +149,7 @@ func (v *ApiVisitor) VisitTypeBlockBody(ctx *api.TypeBlockBodyContext) interface
 	return ctx.TypeBlockStruct().Accept(v).(*TypeStruct)
 }
 
+// VisitTypeStruct implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeStruct(ctx *api.TypeStructContext) interface{} {
 	var st TypeStruct
 	st.Name = v.newExprWithToken(ctx.GetStructName())
@@ -168,6 +185,7 @@ func (v *ApiVisitor) VisitTypeStruct(ctx *api.TypeStructContext) interface{} {
 	return &st
 }
 
+// VisitTypeBlockStruct implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeBlockStruct(ctx *api.TypeBlockStructContext) interface{} {
 	var st TypeStruct
 	st.Name = v.newExprWithToken(ctx.GetStructName())
@@ -200,6 +218,7 @@ func (v *ApiVisitor) VisitTypeBlockStruct(ctx *api.TypeBlockStructContext) inter
 	return &st
 }
 
+// VisitTypeBlockAlias implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeBlockAlias(ctx *api.TypeBlockAliasContext) interface{} {
 	var alias TypeAlias
 	alias.Name = v.newExprWithToken(ctx.GetAlias())
@@ -212,6 +231,7 @@ func (v *ApiVisitor) VisitTypeBlockAlias(ctx *api.TypeBlockAliasContext) interfa
 	return &alias
 }
 
+// VisitTypeAlias implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitTypeAlias(ctx *api.TypeAliasContext) interface{} {
 	var alias TypeAlias
 	alias.Name = v.newExprWithToken(ctx.GetAlias())
@@ -224,6 +244,7 @@ func (v *ApiVisitor) VisitTypeAlias(ctx *api.TypeAliasContext) interface{} {
 	return &alias
 }
 
+// VisitField implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitField(ctx *api.FieldContext) interface{} {
 	iAnonymousFiled := ctx.AnonymousFiled()
 	iNormalFieldContext := ctx.NormalField()
@@ -236,6 +257,7 @@ func (v *ApiVisitor) VisitField(ctx *api.FieldContext) interface{} {
 	return nil
 }
 
+// VisitNormalField implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitNormalField(ctx *api.NormalFieldContext) interface{} {
 	var field TypeField
 	field.Name = v.newExprWithToken(ctx.GetFieldName())
@@ -259,6 +281,7 @@ func (v *ApiVisitor) VisitNormalField(ctx *api.NormalFieldContext) interface{} {
 	return &field
 }
 
+// VisitAnonymousFiled implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitAnonymousFiled(ctx *api.AnonymousFiledContext) interface{} {
 	start := ctx.GetStart()
 	stop := ctx.GetStop()
@@ -282,6 +305,7 @@ func (v *ApiVisitor) VisitAnonymousFiled(ctx *api.AnonymousFiledContext) interfa
 	return &field
 }
 
+// VisitDataType implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitDataType(ctx *api.DataTypeContext) interface{} {
 	if ctx.ID() != nil {
 		idExpr := v.newExprWithTerminalNode(ctx.ID())
@@ -310,6 +334,7 @@ func (v *ApiVisitor) VisitDataType(ctx *api.DataTypeContext) interface{} {
 	return ctx.TypeStruct().Accept(v)
 }
 
+// VisitPointerType implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitPointerType(ctx *api.PointerTypeContext) interface{} {
 	nameExpr := v.newExprWithTerminalNode(ctx.ID())
 	v.exportCheck(nameExpr)
@@ -320,6 +345,7 @@ func (v *ApiVisitor) VisitPointerType(ctx *api.PointerTypeContext) interface{} {
 	}
 }
 
+// VisitMapType implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitMapType(ctx *api.MapTypeContext) interface{} {
 	return &Map{
 		MapExpr: v.newExprWithText(ctx.GetText(), ctx.GetMapToken().GetLine(), ctx.GetMapToken().GetColumn(),
@@ -332,6 +358,7 @@ func (v *ApiVisitor) VisitMapType(ctx *api.MapTypeContext) interface{} {
 	}
 }
 
+// VisitArrayType implements from api.BaseApiParserVisitor
 func (v *ApiVisitor) VisitArrayType(ctx *api.ArrayTypeContext) interface{} {
 	return &Array{
 		ArrayExpr: v.newExprWithText(ctx.GetText(), ctx.GetLbrack().GetLine(), ctx.GetLbrack().GetColumn(), ctx.GetLbrack().GetStart(), ctx.DataType().GetStop().GetStop()),
@@ -341,22 +368,27 @@ func (v *ApiVisitor) VisitArrayType(ctx *api.ArrayTypeContext) interface{} {
 	}
 }
 
+// NameExpr returns the expression string of TypeAlias
 func (a *TypeAlias) NameExpr() Expr {
 	return a.Name
 }
 
+// Doc returns the document of TypeAlias, like // some text
 func (a *TypeAlias) Doc() []Expr {
 	return a.DocExpr
 }
 
+// Comment returns the comment of TypeAlias, like // some text
 func (a *TypeAlias) Comment() Expr {
 	return a.CommentExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *TypeAlias) Format() error {
 	return nil
 }
 
+// Equal compares whether the element literals in two TypeAlias are equal
 func (a *TypeAlias) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -378,15 +410,18 @@ func (a *TypeAlias) Equal(v interface{}) bool {
 	return EqualDoc(a, alias)
 }
 
+// Expr returns the expression string of Literal
 func (l *Literal) Expr() Expr {
 	return l.Literal
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (l *Literal) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Literal are equal
 func (l *Literal) Equal(dt DataType) bool {
 	if dt == nil {
 		return false
@@ -400,19 +435,23 @@ func (l *Literal) Equal(dt DataType) bool {
 	return l.Literal.Equal(v.Literal)
 }
 
+// IsNotNil returns whether the instance is nil or not
 func (l *Literal) IsNotNil() bool {
 	return l != nil
 }
 
+// Expr returns the expression string of Interface
 func (i *Interface) Expr() Expr {
 	return i.Literal
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (i *Interface) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Interface are equal
 func (i *Interface) Equal(dt DataType) bool {
 	if dt == nil {
 		return false
@@ -426,19 +465,23 @@ func (i *Interface) Equal(dt DataType) bool {
 	return i.Literal.Equal(v.Literal)
 }
 
+// IsNotNil returns whether the instance is nil or not
 func (i *Interface) IsNotNil() bool {
 	return i != nil
 }
 
+// Expr returns the expression string of Map
 func (m *Map) Expr() Expr {
 	return m.MapExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (m *Map) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Map are equal
 func (m *Map) Equal(dt DataType) bool {
 	if dt == nil {
 		return false
@@ -464,19 +507,23 @@ func (m *Map) Equal(dt DataType) bool {
 	return m.Map.Equal(v.Map)
 }
 
+// IsNotNil returns whether the instance is nil or not
 func (m *Map) IsNotNil() bool {
 	return m != nil
 }
 
+// Expr returns the expression string of Array
 func (a *Array) Expr() Expr {
 	return a.ArrayExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (a *Array) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Array are equal
 func (a *Array) Equal(dt DataType) bool {
 	if dt == nil {
 		return false
@@ -494,19 +541,23 @@ func (a *Array) Equal(dt DataType) bool {
 	return a.Literal.Equal(v.Literal)
 }
 
+// IsNotNil returns whether the instance is nil or not
 func (a *Array) IsNotNil() bool {
 	return a != nil
 }
 
+// Expr returns the expression string of Time
 func (t *Time) Expr() Expr {
 	return t.Literal
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (t *Time) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two Time are equal
 func (t *Time) Equal(dt DataType) bool {
 	if dt == nil {
 		return false
@@ -520,18 +571,22 @@ func (t *Time) Equal(dt DataType) bool {
 	return t.Literal.Equal(v.Literal)
 }
 
+// IsNotNil returns whether the instance is nil or not
 func (t *Time) IsNotNil() bool {
 	return t != nil
 }
 
+// Expr returns the expression string of Pointer
 func (p *Pointer) Expr() Expr {
 	return p.PointerExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (p *Pointer) Format() error {
 	return nil
 }
 
+// Equal compares whether the element literals in two Pointer are equal
 func (p *Pointer) Equal(dt DataType) bool {
 	if dt == nil {
 		return false
@@ -553,14 +608,17 @@ func (p *Pointer) Equal(dt DataType) bool {
 	return p.Name.Equal(v.Name)
 }
 
+// IsNotNil returns whether the instance is nil or not
 func (p *Pointer) IsNotNil() bool {
 	return p != nil
 }
 
+// NameExpr returns the expression string of TypeStruct
 func (s *TypeStruct) NameExpr() Expr {
 	return s.Name
 }
 
+// Equal compares whether the element literals in two TypeStruct are equal
 func (s *TypeStruct) Equal(dt interface{}) bool {
 	if dt == nil {
 		return false
@@ -621,15 +679,18 @@ func (s *TypeStruct) Equal(dt interface{}) bool {
 	return true
 }
 
+// Doc returns the document of TypeStruct, like // some text
 func (s *TypeStruct) Doc() []Expr {
 	return s.DocExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (s *TypeStruct) Format() error {
 	// todo
 	return nil
 }
 
+// Equal compares whether the element literals in two TypeField are equal
 func (t *TypeField) Equal(v interface{}) bool {
 	if v == nil {
 		return false
@@ -663,14 +724,17 @@ func (t *TypeField) Equal(v interface{}) bool {
 	return EqualDoc(t, f)
 }
 
+// Doc returns the document of TypeField, like // some text
 func (t *TypeField) Doc() []Expr {
 	return t.DocExpr
 }
 
+// Comment returns the comment of TypeField, like // some text
 func (t *TypeField) Comment() Expr {
 	return t.CommentExpr
 }
 
+// Format provides a formatter for api command, now nothing to do
 func (t *TypeField) Format() error {
 	// todo
 	return nil

+ 1 - 1
tools/goctl/api/parser/g4/gen/api/apiparser_parser.go

@@ -4931,7 +4931,7 @@ func (p *ApiParserParser) Route() (localctx IRouteContext) {
 	}()
 
 	p.EnterOuterAlt(localctx, 1)
-	checkHttpMethod(p)
+	checkHTTPMethod(p)
 	{
 		p.SetState(291)
 

+ 4 - 1
tools/goctl/api/parser/g4/gen/api/baseparser.go

@@ -74,7 +74,7 @@ func checkKeyValue(p *ApiParserParser) {
 	setCurrentTokenText(p, v)
 }
 
-func checkHttpMethod(p *ApiParserParser) {
+func checkHTTPMethod(p *ApiParserParser) {
 	method := getCurrentTokenText(p)
 	uppler := strings.ToUpper(method)
 	switch uppler {
@@ -107,11 +107,13 @@ func checkKey(p *ApiParserParser) {
 	}
 }
 
+// IsBasicType returns true if the input argument is basic golang type
 func IsBasicType(text string) bool {
 	_, ok := kind[text]
 	return ok
 }
 
+// IsGolangKeyWord returns true if input argument is golang keyword, but it will be ignored which in excepts
 func IsGolangKeyWord(text string, excepts ...string) bool {
 	for _, each := range excepts {
 		if text == each {
@@ -171,6 +173,7 @@ func isNormal(p *ApiParserParser) bool {
 	return len(list) > 1
 }
 
+// MatchTag returns a Boolean value, which returns true if it does matched, otherwise returns fase
 func MatchTag(v string) bool {
 	return matchRegex(v, tagRegex)
 }

+ 13 - 13
tools/goctl/api/parser/g4/test/apiparser_test.go

@@ -12,7 +12,7 @@ import (
 )
 
 var (
-	normalApi = `
+	normalAPI = `
 	syntax="v1"
 	
 	info (
@@ -32,7 +32,7 @@ var (
 		post /foo (Foo) returns ([]int)
 	}
 `
-	missDeclarationApi = `
+	missDeclarationAPI = `
 	@server(
 		foo: bar
 	)
@@ -43,7 +43,7 @@ var (
 	}
 	`
 
-	missDeclarationInArrayApi = `
+	missDeclarationInArrayAPI = `
 	@server(
 		foo: bar
 	)
@@ -54,7 +54,7 @@ var (
 	}
 	`
 
-	missDeclarationInArrayApi2 = `
+	missDeclarationInArrayAPI2 = `
 	@server(
 		foo: bar
 	)
@@ -65,7 +65,7 @@ var (
 	}
 	`
 
-	nestedApiImport = `
+	nestedAPIImport = `
 	import "foo.api"
 	`
 
@@ -99,27 +99,27 @@ var (
 )
 
 func TestApiParser(t *testing.T) {
-	t.Run("missDeclarationApi", func(t *testing.T) {
-		_, err := parser.ParseContent(missDeclarationApi)
+	t.Run("missDeclarationAPI", func(t *testing.T) {
+		_, err := parser.ParseContent(missDeclarationAPI)
 		assert.Error(t, err)
 		fmt.Printf("%+v\n", err)
 	})
 
-	t.Run("missDeclarationApi", func(t *testing.T) {
-		_, err := parser.ParseContent(missDeclarationInArrayApi)
+	t.Run("missDeclarationAPI", func(t *testing.T) {
+		_, err := parser.ParseContent(missDeclarationInArrayAPI)
 		assert.Error(t, err)
 		fmt.Printf("%+v\n", err)
 	})
 
-	t.Run("missDeclarationApi", func(t *testing.T) {
-		_, err := parser.ParseContent(missDeclarationInArrayApi2)
+	t.Run("missDeclarationAPI", func(t *testing.T) {
+		_, err := parser.ParseContent(missDeclarationInArrayAPI2)
 		assert.Error(t, err)
 		fmt.Printf("%+v\n", err)
 	})
 
 	t.Run("nestedImport", func(t *testing.T) {
 		file := filepath.Join(t.TempDir(), "foo.api")
-		err := ioutil.WriteFile(file, []byte(nestedApiImport), os.ModePerm)
+		err := ioutil.WriteFile(file, []byte(nestedAPIImport), os.ModePerm)
 		if err != nil {
 			return
 		}
@@ -275,7 +275,7 @@ func TestApiParser(t *testing.T) {
 	})
 
 	t.Run("normal", func(t *testing.T) {
-		v, err := parser.ParseContent(normalApi)
+		v, err := parser.ParseContent(normalAPI)
 		assert.Nil(t, err)
 		body := &ast.Body{
 			Lp:   ast.NewTextExpr("("),

+ 2 - 0
tools/goctl/api/parser/parser.go

@@ -15,6 +15,7 @@ type parser struct {
 	spec *spec.ApiSpec
 }
 
+// Parse parses the api file
 func Parse(filename string) (*spec.ApiSpec, error) {
 	astParser := ast.NewParser(ast.WithParserPrefix(filepath.Base(filename)))
 	ast, err := astParser.Parse(filename)
@@ -32,6 +33,7 @@ func Parse(filename string) (*spec.ApiSpec, error) {
 	return spec, nil
 }
 
+// ParseContent parses the api content
 func ParseContent(content string) (*spec.ApiSpec, error) {
 	astParser := ast.NewParser()
 	ast, err := astParser.ParseContent(content)

+ 16 - 16
tools/goctl/api/spec/fn.go

@@ -16,6 +16,7 @@ const (
 
 var definedKeys = []string{bodyTagKey, formTagKey, "path"}
 
+// Routes returns all routes in api service
 func (s Service) Routes() []Route {
 	var result []Route
 	for _, group := range s.Groups {
@@ -24,6 +25,7 @@ func (s Service) Routes() []Route {
 	return result
 }
 
+// Tags retuens all tags in Member
 func (m Member) Tags() []*Tag {
 	tags, err := Parse(m.Tag)
 	if err != nil {
@@ -33,6 +35,7 @@ func (m Member) Tags() []*Tag {
 	return tags.Tags()
 }
 
+// IsOptional returns true if tag is optional
 func (m Member) IsOptional() bool {
 	if !m.IsBodyMember() {
 		return false
@@ -49,6 +52,7 @@ func (m Member) IsOptional() bool {
 	return false
 }
 
+// IsOmitEmpty returns true if tag contains omitempty
 func (m Member) IsOmitEmpty() bool {
 	if !m.IsBodyMember() {
 		return false
@@ -65,22 +69,7 @@ func (m Member) IsOmitEmpty() bool {
 	return false
 }
 
-func (m Member) IsOmitempty() bool {
-	if !m.IsBodyMember() {
-		return false
-	}
-
-	tag := m.Tags()
-	for _, item := range tag {
-		if item.Key == bodyTagKey {
-			if stringx.Contains(item.Options, "omitempty") {
-				return true
-			}
-		}
-	}
-	return false
-}
-
+// GetPropertyName returns json tag value
 func (m Member) GetPropertyName() (string, error) {
 	tags := m.Tags()
 	for _, tag := range tags {
@@ -95,10 +84,12 @@ func (m Member) GetPropertyName() (string, error) {
 	return "", errors.New("json property name not exist, member: " + m.Name)
 }
 
+// GetComment returns comment value of Member
 func (m Member) GetComment() string {
 	return strings.TrimSpace(m.Comment)
 }
 
+// IsBodyMember returns true if contains json tag
 func (m Member) IsBodyMember() bool {
 	if m.IsInline {
 		return true
@@ -113,6 +104,7 @@ func (m Member) IsBodyMember() bool {
 	return false
 }
 
+// IsFormMember returns true if contains form tag
 func (m Member) IsFormMember() bool {
 	if m.IsInline {
 		return false
@@ -127,6 +119,7 @@ func (m Member) IsFormMember() bool {
 	return false
 }
 
+// GetBodyMembers returns all json fields
 func (t DefineStruct) GetBodyMembers() []Member {
 	var result []Member
 	for _, member := range t.Members {
@@ -137,6 +130,7 @@ func (t DefineStruct) GetBodyMembers() []Member {
 	return result
 }
 
+// GetFormMembers returns all form fields
 func (t DefineStruct) GetFormMembers() []Member {
 	var result []Member
 	for _, member := range t.Members {
@@ -147,6 +141,7 @@ func (t DefineStruct) GetFormMembers() []Member {
 	return result
 }
 
+// GetNonBodyMembers retruns all have no tag fields
 func (t DefineStruct) GetNonBodyMembers() []Member {
 	var result []Member
 	for _, member := range t.Members {
@@ -157,6 +152,7 @@ func (t DefineStruct) GetNonBodyMembers() []Member {
 	return result
 }
 
+// JoinedDoc joins comments and summary value in AtDoc
 func (r Route) JoinedDoc() string {
 	doc := r.AtDoc.Text
 	if r.AtDoc.Properties != nil {
@@ -166,6 +162,7 @@ func (r Route) JoinedDoc() string {
 	return strings.TrimSpace(doc)
 }
 
+// GetAnnotation returns the value by specified key
 func (r Route) GetAnnotation(key string) string {
 	if r.Annotation.Properties == nil {
 		return ""
@@ -174,6 +171,7 @@ func (r Route) GetAnnotation(key string) string {
 	return r.Annotation.Properties[key]
 }
 
+// GetAnnotation returns the value by specified key
 func (g Group) GetAnnotation(key string) string {
 	if g.Annotation.Properties == nil {
 		return ""
@@ -182,6 +180,7 @@ func (g Group) GetAnnotation(key string) string {
 	return g.Annotation.Properties[key]
 }
 
+// ResponseTypeName returns response type name of route
 func (r Route) ResponseTypeName() string {
 	if r.ResponseType == nil {
 		return ""
@@ -190,6 +189,7 @@ func (r Route) ResponseTypeName() string {
 	return r.ResponseType.Name()
 }
 
+// RequestTypeName returns request type name of route
 func (r Route) RequestTypeName() string {
 	if r.RequestType == nil {
 		return ""

+ 6 - 0
tools/goctl/api/spec/name.go

@@ -1,25 +1,31 @@
 package spec
 
+// Name returns a basic string, such as int32,int64
 func (t PrimitiveType) Name() string {
 	return t.RawName
 }
 
+// Name returns a structure string, such as User
 func (t DefineStruct) Name() string {
 	return t.RawName
 }
 
+// Name returns a map string, such as map[string]int
 func (t MapType) Name() string {
 	return t.RawName
 }
 
+// Name returns a slice string, such as []int
 func (t ArrayType) Name() string {
 	return t.RawName
 }
 
+// Name returns a pointer string, such as *User
 func (t PointerType) Name() string {
 	return t.RawName
 }
 
+// Name returns a interface string, Its fixed value is interface{}
 func (t InterfaceType) Name() string {
 	return t.RawName
 }

+ 18 - 1
tools/goctl/api/spec/spec.go

@@ -1,16 +1,20 @@
 package spec
 
 type (
+	// Doc describes document
 	Doc []string
 
+	// Annotation defines key-value
 	Annotation struct {
 		Properties map[string]string
 	}
 
+	// ApiSyntax describes the syntax grammar
 	ApiSyntax struct {
 		Version string
 	}
 
+	// ApiSpec describes a api file
 	ApiSpec struct {
 		Info    Info
 		Syntax  ApiSyntax
@@ -19,15 +23,18 @@ type (
 		Service Service
 	}
 
+	// Import describes api import
 	Import struct {
 		Value string
 	}
 
+	// Group defines a set of routing information
 	Group struct {
 		Annotation Annotation
 		Routes     []Route
 	}
 
+	// Info describes info grammar block
 	Info struct {
 		// Deprecated: use Properties instead
 		Title string
@@ -42,6 +49,7 @@ type (
 		Properties map[string]string
 	}
 
+	// Member describes the field of a structure
 	Member struct {
 		Name string
 		// 数据类型字面值,如:string、map[int]string、[]int64、[]*User
@@ -53,6 +61,7 @@ type (
 		IsInline bool
 	}
 
+	// Route describes api route
 	Route struct {
 		Annotation   Annotation
 		Method       string
@@ -64,26 +73,30 @@ type (
 		AtDoc        AtDoc
 	}
 
+	// Service describes api service
 	Service struct {
 		Name   string
 		Groups []Group
 	}
 
+	// Type defines api type
 	Type interface {
 		Name() string
 	}
 
+	// DefineStruct describes api structure
 	DefineStruct struct {
 		RawName string
 		Members []Member
 		Docs    Doc
 	}
 
-	// 系统预设基本数据类型 bool int32 int64 float32
+	// PrimitiveType describes the basic golang type, such as bool,int32,int64, ...
 	PrimitiveType struct {
 		RawName string
 	}
 
+	// MapType describes a map for api
 	MapType struct {
 		RawName string
 		// only support the PrimitiveType
@@ -97,20 +110,24 @@ type (
 		Value Type
 	}
 
+	// ArrayType describes a slice for api
 	ArrayType struct {
 		RawName string
 		Value   Type
 	}
 
+	// InterfaceType describes a interface for api
 	InterfaceType struct {
 		RawName string
 	}
 
+	// PointerType describes a pointer for api
 	PointerType struct {
 		RawName string
 		Type    Type
 	}
 
+	// AtDoc describes a metadata for api grammar: @doc(...)
 	AtDoc struct {
 		Properties map[string]string
 		Text       string

+ 6 - 0
tools/goctl/api/spec/tags.go

@@ -10,6 +10,7 @@ import (
 var errTagNotExist = errors.New("tag does not exist")
 
 type (
+	// Tag defines a tag for structure filed
 	Tag struct {
 		// Key is the tag key, such as json, xml, etc..
 		// i.e: `json:"foo,omitempty". Here key is: "json"
@@ -24,11 +25,13 @@ type (
 		Options []string
 	}
 
+	// Tags defines a slice for Tag
 	Tags struct {
 		tags []*Tag
 	}
 )
 
+// Parse converts tag string into Tag
 func Parse(tag string) (*Tags, error) {
 	tag = strings.TrimPrefix(tag, "`")
 	tag = strings.TrimSuffix(tag, "`")
@@ -44,6 +47,7 @@ func Parse(tag string) (*Tags, error) {
 	return &result, nil
 }
 
+// Get gets tag value by specified key
 func (t *Tags) Get(key string) (*Tag, error) {
 	for _, tag := range t.tags {
 		if tag.Key == key {
@@ -54,6 +58,7 @@ func (t *Tags) Get(key string) (*Tag, error) {
 	return nil, errTagNotExist
 }
 
+// Keys returns all keys in Tags
 func (t *Tags) Keys() []string {
 	var keys []string
 	for _, tag := range t.tags {
@@ -62,6 +67,7 @@ func (t *Tags) Keys() []string {
 	return keys
 }
 
+// Tags returns all tags in Tags
 func (t *Tags) Tags() []*Tag {
 	return t.tags
 }

+ 4 - 3
tools/goctl/api/tsgen/gen.go

@@ -11,12 +11,13 @@ import (
 	"github.com/urfave/cli"
 )
 
+// TsCommand provides the entry to generting typescript codes
 func TsCommand(c *cli.Context) error {
 	apiFile := c.String("api")
 	dir := c.String("dir")
-	webApi := c.String("webapi")
+	webAPI := c.String("webapi")
 	caller := c.String("caller")
-	unwrapApi := c.Bool("unwrap")
+	unwrapAPI := c.Bool("unwrap")
 	if len(apiFile) == 0 {
 		return errors.New("missing -api")
 	}
@@ -32,7 +33,7 @@ func TsCommand(c *cli.Context) error {
 	}
 
 	logx.Must(util.MkdirIfNotExist(dir))
-	logx.Must(genHandler(dir, webApi, caller, api, unwrapApi))
+	logx.Must(genHandler(dir, webAPI, caller, api, unwrapAPI))
 	logx.Must(genComponents(dir, api))
 
 	fmt.Println(aurora.Green("Done."))

+ 7 - 7
tools/goctl/api/tsgen/genpacket.go

@@ -18,7 +18,7 @@ const (
 `
 )
 
-func genHandler(dir, webApi, caller string, api *spec.ApiSpec, unwrapApi bool) error {
+func genHandler(dir, webAPI, caller string, api *spec.ApiSpec, unwrapAPI bool) error {
 	filename := strings.Replace(api.Service.Name, "-api", "", 1) + ".ts"
 	if err := util.RemoveIfExist(path.Join(dir, filename)); err != nil {
 		return err
@@ -37,11 +37,11 @@ func genHandler(dir, webApi, caller string, api *spec.ApiSpec, unwrapApi bool) e
 		caller = "webapi"
 	}
 	importCaller := caller
-	if unwrapApi {
+	if unwrapAPI {
 		importCaller = "{ " + importCaller + " }"
 	}
-	if len(webApi) > 0 {
-		imports += `import ` + importCaller + ` from ` + "\"" + webApi + "\""
+	if len(webAPI) > 0 {
+		imports += `import ` + importCaller + ` from ` + "\"" + webAPI + "\""
 	}
 
 	if len(api.Types) != 0 {
@@ -53,7 +53,7 @@ func genHandler(dir, webApi, caller string, api *spec.ApiSpec, unwrapApi bool) e
 		imports += fmt.Sprintf(`%sexport * from "%s"`, util.NL, "./"+outputFile)
 	}
 
-	apis, err := genApi(api, caller)
+	apis, err := genAPI(api, caller)
 	if err != nil {
 		return err
 	}
@@ -65,7 +65,7 @@ func genHandler(dir, webApi, caller string, api *spec.ApiSpec, unwrapApi bool) e
 	})
 }
 
-func genApi(api *spec.ApiSpec, caller string) (string, error) {
+func genAPI(api *spec.ApiSpec, caller string) (string, error) {
 	var builder strings.Builder
 	for _, group := range api.Service.Groups {
 		for _, route := range group.Routes {
@@ -157,7 +157,7 @@ func callParamsForRoute(route spec.Route, group spec.Group) string {
 }
 
 func pathForRoute(route spec.Route, group spec.Group) string {
-	prefix := group.GetAnnotation("pathPrefix")
+	prefix := group.GetAnnotation(pathPrefix)
 	if len(prefix) == 0 {
 		return "\"" + route.Path + "\""
 	}

+ 1 - 1
tools/goctl/api/tsgen/util.go

@@ -19,7 +19,7 @@ func writeProperty(writer io.Writer, member spec.Member, indent int) error {
 	}
 
 	optionalTag := ""
-	if member.IsOptional() || member.IsOmitempty() {
+	if member.IsOptional() || member.IsOmitEmpty() {
 		optionalTag = "?"
 	}
 	name, err := member.GetPropertyName()

+ 11 - 7
tools/goctl/api/util/case.go

@@ -5,6 +5,7 @@ import (
 	"unicode"
 )
 
+// IsUpperCase returns true if the rune in A-Z
 func IsUpperCase(r rune) bool {
 	if r >= 'A' && r <= 'Z' {
 		return true
@@ -12,6 +13,7 @@ func IsUpperCase(r rune) bool {
 	return false
 }
 
+// IsLowerCase returns true if the rune in a-z
 func IsLowerCase(r rune) bool {
 	if r >= 'a' && r <= 'z' {
 		return true
@@ -19,6 +21,7 @@ func IsLowerCase(r rune) bool {
 	return false
 }
 
+// ToSnakeCase returns a copy string by converting camel case into snake case
 func ToSnakeCase(s string) string {
 	var out []rune
 	for index, r := range s {
@@ -44,6 +47,7 @@ func ToSnakeCase(s string) string {
 	return string(out)
 }
 
+// ToCamelCase returns a copy string by converting snake case into camel case
 func ToCamelCase(s string) string {
 	s = ToLower(s)
 	out := []rune{}
@@ -66,6 +70,7 @@ func ToCamelCase(s string) string {
 	return string(out)
 }
 
+// ToLowerCase converts rune into lower case
 func ToLowerCase(r rune) rune {
 	dx := 'A' - 'a'
 	if IsUpperCase(r) {
@@ -73,6 +78,8 @@ func ToLowerCase(r rune) rune {
 	}
 	return r
 }
+
+// ToUpperCase converts rune into upper case
 func ToUpperCase(r rune) rune {
 	dx := 'A' - 'a'
 	if IsLowerCase(r) {
@@ -81,6 +88,7 @@ func ToUpperCase(r rune) rune {
 	return r
 }
 
+// ToLower returns a copy string by converting it into lower
 func ToLower(s string) string {
 	var out []rune
 	for _, r := range s {
@@ -89,6 +97,7 @@ func ToLower(s string) string {
 	return string(out)
 }
 
+// ToUpper returns a copy string by converting it into upper
 func ToUpper(s string) string {
 	var out []rune
 	for _, r := range s {
@@ -97,13 +106,7 @@ func ToUpper(s string) string {
 	return string(out)
 }
 
-func LowerFirst(s string) string {
-	if len(s) == 0 {
-		return s
-	}
-	return ToLower(s[:1]) + s[1:]
-}
-
+// UpperFirst converts s[0] into upper case
 func UpperFirst(s string) string {
 	if len(s) == 0 {
 		return s
@@ -111,6 +114,7 @@ func UpperFirst(s string) string {
 	return ToUpper(s[:1]) + s[1:]
 }
 
+// UnExport converts the first letter into lower case
 func UnExport(text string) bool {
 	var flag bool
 	str := strings.Map(func(r rune) rune {

+ 6 - 0
tools/goctl/api/util/util.go

@@ -13,6 +13,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
+// MaybeCreateFile creates file if not exists
 func MaybeCreateFile(dir, subdir, file string) (fp *os.File, created bool, err error) {
 	logx.Must(util.MkdirIfNotExist(path.Join(dir, subdir)))
 	fpath := path.Join(dir, subdir, file)
@@ -26,10 +27,12 @@ func MaybeCreateFile(dir, subdir, file string) (fp *os.File, created bool, err e
 	return
 }
 
+// WrapErr wraps an error with message
 func WrapErr(err error, message string) error {
 	return errors.New(message + ", " + err.Error())
 }
 
+// Copy calls io.Copy if the source file and destination file exists
 func Copy(src, dst string) (int64, error) {
 	sourceFileStat, err := os.Stat(src)
 	if err != nil {
@@ -55,6 +58,7 @@ func Copy(src, dst string) (int64, error) {
 	return nBytes, err
 }
 
+// ComponentName returns component name for typescript
 func ComponentName(api *spec.ApiSpec) string {
 	name := api.Service.Name
 	if strings.HasSuffix(name, "-api") {
@@ -63,12 +67,14 @@ func ComponentName(api *spec.ApiSpec) string {
 	return name + "Components"
 }
 
+// WriteIndent writes tab spaces
 func WriteIndent(writer io.Writer, indent int) {
 	for i := 0; i < indent; i++ {
 		fmt.Fprint(writer, "\t")
 	}
 }
 
+// RemoveComment filters comment content
 func RemoveComment(line string) string {
 	var commentIdx = strings.Index(line, "//")
 	if commentIdx >= 0 {

+ 1 - 0
tools/goctl/api/validate/validate.go

@@ -9,6 +9,7 @@ import (
 	"github.com/urfave/cli"
 )
 
+// GoValidateApi verifies whether the api has a syntax error
 func GoValidateApi(c *cli.Context) error {
 	apiFile := c.String("api")
 

+ 3 - 84
tools/goctl/config/config.go

@@ -2,35 +2,15 @@ package config
 
 import (
 	"errors"
-	"io/ioutil"
-	"os"
-	"path/filepath"
 	"strings"
-
-	"github.com/tal-tech/go-zero/tools/goctl/util"
-	"gopkg.in/yaml.v2"
 )
 
 const (
-	configFile    = "config.yaml"
-	configFolder  = "config"
+	// DefaultFormat defines a default naming style
 	DefaultFormat = "gozero"
 )
 
-const defaultYaml = `# namingFormat is used to define the naming format of the generated file name.
-# just like time formatting, you can specify the formatting style through the
-# two format characters go, and zero. for example: snake format you can
-# define as go_zero, camel case format you can it is defined as goZero,
-# and even split characters can be specified, such as go#zero. in theory,
-# any combination can be used, but the prerequisite must meet the naming conventions
-# of each operating system file name. if you want to independently control the file 
-# naming style of the api, rpc, and model layers, you can set it through apiNamingFormat, 
-# rpcNamingFormat, modelNamingFormat, and independent control is not enabled by default. 
-# for more information, please see #{apiNamingFormat},#{rpcNamingFormat},#{modelNamingFormat}
-# Note: namingFormat is based on snake or camel string
-namingFormat: gozero
-`
-
+// Config defines the file naming style
 type Config struct {
 	// NamingFormat is used to define the naming format of the generated file name.
 	// just like time formatting, you can specify the formatting style through the
@@ -43,6 +23,7 @@ type Config struct {
 	NamingFormat string `yaml:"namingFormat"`
 }
 
+// NewConfig creates an instance for Config
 func NewConfig(format string) (*Config, error) {
 	if len(format) == 0 {
 		format = DefaultFormat
@@ -52,68 +33,6 @@ func NewConfig(format string) (*Config, error) {
 	return cfg, err
 }
 
-func InitOrGetConfig() (*Config, error) {
-	var (
-		defaultConfig Config
-	)
-	err := yaml.Unmarshal([]byte(defaultYaml), &defaultConfig)
-	if err != nil {
-		return nil, err
-	}
-
-	goctlHome, err := util.GetGoctlHome()
-	if err != nil {
-		return nil, err
-	}
-
-	configDir := filepath.Join(goctlHome, configFolder)
-	configFilename := filepath.Join(configDir, configFile)
-	if util.FileExists(configFilename) {
-		data, err := ioutil.ReadFile(configFilename)
-		if err != nil {
-			return nil, err
-		}
-
-		err = yaml.Unmarshal(data, &defaultConfig)
-		if err != nil {
-			return nil, err
-		}
-
-		err = validate(&defaultConfig)
-		if err != nil {
-			return nil, err
-		}
-
-		return &defaultConfig, nil
-	}
-
-	err = util.MkdirIfNotExist(configDir)
-	if err != nil {
-		return nil, err
-	}
-
-	f, err := os.Create(configFilename)
-	if err != nil {
-		return nil, err
-	}
-
-	defer func() {
-		_ = f.Close()
-	}()
-
-	_, err = f.WriteString(defaultYaml)
-	if err != nil {
-		return nil, err
-	}
-
-	err = validate(&defaultConfig)
-	if err != nil {
-		return nil, err
-	}
-
-	return &defaultConfig, nil
-}
-
 func validate(cfg *Config) error {
 	if len(strings.TrimSpace(cfg.NamingFormat)) == 0 {
 		return errors.New("missing namingFormat")

+ 1 - 0
tools/goctl/configgen/genconfig.go

@@ -37,6 +37,7 @@ func main() {
 }
 `
 
+// GenConfigCommand provides the entry of goctl config
 func GenConfigCommand(c *cli.Context) error {
 	path, err := filepath.Abs(c.String("path"))
 	if err != nil {

+ 2 - 0
tools/goctl/docker/docker.go

@@ -22,6 +22,7 @@ const (
 	cstOffset      = 60 * 60 * 8 // 8 hours offset for Chinese Standard Time
 )
 
+// Docker describes a dockerfile
 type Docker struct {
 	Chinese   bool
 	GoRelPath string
@@ -32,6 +33,7 @@ type Docker struct {
 	Argument  string
 }
 
+// DockerCommand provides the entry for goctl docker
 func DockerCommand(c *cli.Context) (err error) {
 	defer func() {
 		if err == nil {

+ 5 - 0
tools/goctl/docker/template.go

@@ -41,22 +41,27 @@ CMD ["./{{.ExeFile}}"{{.Argument}}]
 `
 )
 
+// Clean deletes all templates files
 func Clean() error {
 	return util.Clean(category)
 }
 
+// GenTemplates creates docker template files
 func GenTemplates(_ *cli.Context) error {
 	return initTemplate()
 }
 
+// Category returns the const string of docker category
 func Category() string {
 	return category
 }
 
+// RevertTemplate recovers the deleted template files
 func RevertTemplate(name string) error {
 	return util.CreateTemplate(category, name, dockerTemplate)
 }
 
+// Update deletes and creates new template files
 func Update() error {
 	err := Clean()
 	if err != nil {

+ 4 - 4
tools/goctl/goctl.go

@@ -49,7 +49,7 @@ var (
 				{
 					Name:   "new",
 					Usage:  "fast create api service",
-					Action: new.NewService,
+					Action: new.CreateServiceCommand,
 				},
 				{
 					Name:  "format",
@@ -337,7 +337,7 @@ var (
 							Usage: "whether the command execution environment is from idea plugin. [optional]",
 						},
 					},
-					Action: rpc.RpcNew,
+					Action: rpc.RPCNew,
 				},
 				{
 					Name:  "template",
@@ -348,7 +348,7 @@ var (
 							Usage: "the target path of proto",
 						},
 					},
-					Action: rpc.RpcTemplate,
+					Action: rpc.RPCTemplate,
 				},
 				{
 					Name:  "proto",
@@ -375,7 +375,7 @@ var (
 							Usage: "whether the command execution environment is from idea plugin. [optional]",
 						},
 					},
-					Action: rpc.Rpc,
+					Action: rpc.RPC,
 				},
 			},
 		},

+ 1 - 0
tools/goctl/kube/kube.go

@@ -18,6 +18,7 @@ const (
 	portLimit          = 32767
 )
 
+// Deployment describes the k8s deployment yaml
 type Deployment struct {
 	Name        string
 	Namespace   string

+ 4 - 0
tools/goctl/model/sql/builderx/builder.go

@@ -9,14 +9,17 @@ import (
 
 const dbTag = "db"
 
+// NewEq wraps builder.Eq
 func NewEq(in interface{}) builder.Eq {
 	return builder.Eq(ToMap(in))
 }
 
+// NewGt wraps builder.Gt
 func NewGt(in interface{}) builder.Gt {
 	return builder.Gt(ToMap(in))
 }
 
+// ToMap converts interface into map
 func ToMap(in interface{}) map[string]interface{} {
 	out := make(map[string]interface{})
 	v := reflect.ValueOf(in)
@@ -76,6 +79,7 @@ func FieldNames(in interface{}) []string {
 	return out
 }
 
+// RawFieldNames converts golang struct field into slice string
 func RawFieldNames(in interface{}) []string {
 	out := make([]string, 0)
 	v := reflect.ValueOf(in)

+ 14 - 14
tools/goctl/model/sql/builderx/builder_test.go

@@ -10,12 +10,12 @@ import (
 
 type mockedUser struct {
 	// 自增id
-	Id string `db:"id" json:"id,omitempty"`
+	ID string `db:"id" json:"id,omitempty"`
 	// 姓名
 	UserName string `db:"user_name" json:"userName,omitempty"`
 	// 1男,2女
 	Sex  int    `db:"sex" json:"sex,omitempty"`
-	Uuid string `db:"uuid" uuid:"uuid,omitempty"`
+	UUID string `db:"uuid" uuid:"uuid,omitempty"`
 	Age  int    `db:"age" json:"age"`
 }
 
@@ -42,7 +42,7 @@ func TestFieldNames(t *testing.T) {
 
 func TestNewEq(t *testing.T) {
 	u := &mockedUser{
-		Id:       "123456",
+		ID:       "123456",
 		UserName: "wahaha",
 	}
 	out := NewEq(u)
@@ -54,16 +54,16 @@ func TestNewEq(t *testing.T) {
 // @see https://github.com/go-xorm/builder
 func TestBuilderSql(t *testing.T) {
 	u := &mockedUser{
-		Id: "123123",
+		ID: "123123",
 	}
 	fields := RawFieldNames(u)
 	eq := NewEq(u)
 	sql, args, err := builder.Select(fields...).From("user").Where(eq).ToSQL()
 	fmt.Println(sql, args, err)
 
-	actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE id=?"
+	actualSQL := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE id=?"
 	actualArgs := []interface{}{"123123"}
-	assert.Equal(t, sql, actualSql)
+	assert.Equal(t, sql, actualSQL)
 	assert.Equal(t, args, actualArgs)
 }
 
@@ -76,9 +76,9 @@ func TestBuildSqlDefaultValue(t *testing.T) {
 		sql, args, err := builder.Select(userFieldsWithRawStringQuote...).From("user").Where(eq).ToSQL()
 		fmt.Println(sql, args, err)
 
-		actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE age=? AND user_name=?"
+		actualSQL := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE age=? AND user_name=?"
 		actualArgs := []interface{}{0, ""}
-		assert.Equal(t, sql, actualSql)
+		assert.Equal(t, sql, actualSQL)
 		assert.Equal(t, args, actualArgs)
 	})
 
@@ -86,9 +86,9 @@ func TestBuildSqlDefaultValue(t *testing.T) {
 		sql, args, err := builder.Select(userFieldsWithoutRawStringQuote...).From("user").Where(eq).ToSQL()
 		fmt.Println(sql, args, err)
 
-		actualSql := "SELECT id,user_name,sex,uuid,age FROM user WHERE age=? AND user_name=?"
+		actualSQL := "SELECT id,user_name,sex,uuid,age FROM user WHERE age=? AND user_name=?"
 		actualArgs := []interface{}{0, ""}
-		assert.Equal(t, sql, actualSql)
+		assert.Equal(t, sql, actualSQL)
 		assert.Equal(t, args, actualArgs)
 	})
 }
@@ -102,9 +102,9 @@ func TestBuilderSqlIn(t *testing.T) {
 	sql, args, err := builder.Select(userFieldsWithRawStringQuote...).From("user").Where(in).And(gtU).ToSQL()
 	fmt.Println(sql, args, err)
 
-	actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE id IN (?,?,?) AND age>?"
+	actualSQL := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE id IN (?,?,?) AND age>?"
 	actualArgs := []interface{}{"1", "2", "3", 18}
-	assert.Equal(t, sql, actualSql)
+	assert.Equal(t, sql, actualSQL)
 	assert.Equal(t, args, actualArgs)
 }
 
@@ -113,8 +113,8 @@ func TestBuildSqlLike(t *testing.T) {
 	sql, args, err := builder.Select(userFieldsWithRawStringQuote...).From("user").Where(like).ToSQL()
 	fmt.Println(sql, args, err)
 
-	actualSql := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE name LIKE ?"
+	actualSQL := "SELECT `id`,`user_name`,`sex`,`uuid`,`age` FROM user WHERE name LIKE ?"
 	actualArgs := []interface{}{"%wang%"}
-	assert.Equal(t, sql, actualSql)
+	assert.Equal(t, sql, actualSQL)
 	assert.Equal(t, args, actualArgs)
 }

+ 4 - 2
tools/goctl/model/sql/command/command.go

@@ -22,13 +22,14 @@ const (
 	flagDir   = "dir"
 	flagCache = "cache"
 	flagIdea  = "idea"
-	flagUrl   = "url"
+	flagURL   = "url"
 	flagTable = "table"
 	flagStyle = "style"
 )
 
 var errNotMatched = errors.New("sql not matched")
 
+// MysqlDDL generates model code from ddl
 func MysqlDDL(ctx *cli.Context) error {
 	src := ctx.String(flagSrc)
 	dir := ctx.String(flagDir)
@@ -43,8 +44,9 @@ func MysqlDDL(ctx *cli.Context) error {
 	return fromDDl(src, dir, cfg, cache, idea)
 }
 
+// MyDataSource generates model code from datasource
 func MyDataSource(ctx *cli.Context) error {
-	url := strings.TrimSpace(ctx.String(flagUrl))
+	url := strings.TrimSpace(ctx.String(flagURL))
 	dir := strings.TrimSpace(ctx.String(flagDir))
 	cache := ctx.Bool(flagCache)
 	idea := ctx.Bool(flagIdea)

+ 1 - 0
tools/goctl/model/sql/converter/types.go

@@ -39,6 +39,7 @@ var commonMysqlDataTypeMap = map[string]string{
 	"json":       "string",
 }
 
+// ConvertDataType converts mysql column type into golang type
 func ConvertDataType(dataBaseType string, isDefaultNull bool) (string, error) {
 	tp, ok := commonMysqlDataTypeMap[strings.ToLower(dataBaseType)]
 	if !ok {

+ 0 - 5
tools/goctl/model/sql/gen/error.go

@@ -1,5 +0,0 @@
-package gen
-
-import "errors"
-
-var ErrCircleQuery = errors.New("circle query with other fields")

+ 4 - 0
tools/goctl/model/sql/gen/gen.go

@@ -33,6 +33,7 @@ type (
 		cfg *config.Config
 	}
 
+	// Option defines a function with argument defaultGenerator
 	Option func(generator *defaultGenerator)
 
 	code struct {
@@ -48,6 +49,7 @@ type (
 	}
 )
 
+// NewDefaultGenerator creates an instance for defaultGenerator
 func NewDefaultGenerator(dir string, cfg *config.Config, opt ...Option) (*defaultGenerator, error) {
 	if dir == "" {
 		dir = pwd
@@ -75,6 +77,7 @@ func NewDefaultGenerator(dir string, cfg *config.Config, opt ...Option) (*defaul
 	return generator, nil
 }
 
+// WithConsoleOption creates a console option
 func WithConsoleOption(c console.Console) Option {
 	return func(generator *defaultGenerator) {
 		generator.Console = c
@@ -189,6 +192,7 @@ func (g *defaultGenerator) genFromDDL(source string, withCache bool) (map[string
 	return m, nil
 }
 
+// Table defines mysql table
 type Table struct {
 	parser.Table
 	CacheKey          map[string]Key

+ 1 - 1
tools/goctl/model/sql/gen/gen_test.go

@@ -94,7 +94,7 @@ func TestWrapWithRawString(t *testing.T) {
 
 func TestFields(t *testing.T) {
 	type Student struct {
-		Id         int64           `db:"id"`
+		ID         int64           `db:"id"`
 		Name       string          `db:"name"`
 		Age        sql.NullInt64   `db:"age"`
 		Score      sql.NullFloat64 `db:"score"`

+ 15 - 10
tools/goctl/model/sql/gen/keys.go

@@ -8,17 +8,22 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 
-// tableName:user
-// {{prefix}}=cache
-// key:id
+// Key defines cache key variable for generating code
 type Key struct {
-	VarExpression     string // cacheUserIdPrefix = "cache#User#id#"
-	Left              string // cacheUserIdPrefix
-	Right             string // cache#user#id#
-	Variable          string // userIdKey
-	KeyExpression     string // userIdKey: = fmt.Sprintf("cache#user#id#%v", userId)
-	DataKeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", data.userId)
-	RespKeyExpression string // userIdKey: = fmt.Sprintf("cache#user#id#%v", resp.userId)
+	// VarExpression likes cacheUserIdPrefix = "cache#User#id#"
+	VarExpression string
+	// Left likes cacheUserIdPrefix
+	Left string
+	// Right likes  cache#user#id#
+	Right string
+	// Variable likes userIdKey
+	Variable string
+	// KeyExpression likes userIdKey: = fmt.Sprintf("cache#user#id#%v", userId)
+	KeyExpression string
+	// DataKeyExpression likes userIdKey: = fmt.Sprintf("cache#user#id#%v", data.userId)
+	DataKeyExpression string
+	// RespKeyExpression likes userIdKey: = fmt.Sprintf("cache#user#id#%v", resp.userId)
+	RespKeyExpression string
 }
 
 // key-数据库原始字段名,value-缓存key相关数据

+ 5 - 0
tools/goctl/model/sql/gen/template.go

@@ -54,18 +54,22 @@ var templates = map[string]string{
 	errTemplateFile:                       template.Error,
 }
 
+// Category returns model const value
 func Category() string {
 	return category
 }
 
+// Clean deletes all template files
 func Clean() error {
 	return util.Clean(category)
 }
 
+// GenTemplates creates template files if not exists
 func GenTemplates(_ *cli.Context) error {
 	return util.InitTemplates(category, templates)
 }
 
+// RevertTemplate recovers the delete template files
 func RevertTemplate(name string) error {
 	content, ok := templates[name]
 	if !ok {
@@ -75,6 +79,7 @@ func RevertTemplate(name string) error {
 	return util.CreateTemplate(category, name, content)
 }
 
+// Update provides template clean and init
 func Update() error {
 	err := Clean()
 	if err != nil {

+ 7 - 2
tools/goctl/model/sql/model/informationschemamodel.go

@@ -3,10 +3,12 @@ package model
 import "github.com/tal-tech/go-zero/core/stores/sqlx"
 
 type (
+	// InformationSchemaModel defines information schema model
 	InformationSchemaModel struct {
 		conn sqlx.SqlConn
 	}
 
+	// Column defines column in table
 	Column struct {
 		Name          string      `db:"COLUMN_NAME"`
 		DataType      string      `db:"DATA_TYPE"`
@@ -18,10 +20,12 @@ type (
 	}
 )
 
+// NewInformationSchemaModel creates an instance for InformationSchemaModel
 func NewInformationSchemaModel(conn sqlx.SqlConn) *InformationSchemaModel {
 	return &InformationSchemaModel{conn: conn}
 }
 
+// GetAllTables selects all tables from TABLE_SCHEMA
 func (m *InformationSchemaModel) GetAllTables(database string) ([]string, error) {
 	query := `select TABLE_NAME from TABLES where TABLE_SCHEMA = ?`
 	var tables []string
@@ -33,9 +37,10 @@ func (m *InformationSchemaModel) GetAllTables(database string) ([]string, error)
 	return tables, nil
 }
 
+// FindByTableName finds out the target table by name
 func (m *InformationSchemaModel) FindByTableName(db, table string) ([]*Column, error) {
-	querySql := `select COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,COLUMN_KEY,EXTRA,COLUMN_COMMENT from COLUMNS where TABLE_SCHEMA = ? and TABLE_NAME = ?`
+	querySQL := `select COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE,DATA_TYPE,COLUMN_KEY,EXTRA,COLUMN_COMMENT from COLUMNS where TABLE_SCHEMA = ? and TABLE_NAME = ?`
 	var reply []*Column
-	err := m.conn.QueryRows(&reply, querySql, db, table)
+	err := m.conn.QueryRows(&reply, querySQL, db, table)
 	return reply, err
 }

+ 7 - 0
tools/goctl/model/sql/parser/parser.go

@@ -21,17 +21,20 @@ const (
 const timeImport = "time.Time"
 
 type (
+	// Table describes a mysql table
 	Table struct {
 		Name       stringx.String
 		PrimaryKey Primary
 		Fields     []Field
 	}
 
+	// Primary describes a primary key
 	Primary struct {
 		Field
 		AutoIncrement bool
 	}
 
+	// Field describes a table field
 	Field struct {
 		Name         stringx.String
 		DataBaseType string
@@ -41,9 +44,11 @@ type (
 		Comment      string
 	}
 
+	// KeyType types alias of int
 	KeyType int
 )
 
+// Parse parses ddl into golang structure
 func Parse(ddl string) (*Table, error) {
 	stmt, err := sqlparser.ParseStrictDDL(ddl)
 	if err != nil {
@@ -169,6 +174,7 @@ func getIndexKeyType(indexes []*sqlparser.IndexDefinition) (map[string]KeyType,
 	return keyMap, nil
 }
 
+// ContainsTime determines whether the table field contains time.Time
 func (t *Table) ContainsTime() bool {
 	for _, item := range t.Fields {
 		if item.DataType == timeImport {
@@ -178,6 +184,7 @@ func (t *Table) ContainsTime() bool {
 	return false
 }
 
+// ConvertColumn provides type conversion for mysql clolumn, primary key lookup
 func ConvertColumn(db, table string, in []*model.Column) (*Table, error) {
 	var reply Table
 	reply.Name = stringx.From(table)

+ 2 - 0
tools/goctl/model/sql/template/delete.go

@@ -1,5 +1,6 @@
 package template
 
+// Delete defines a delete template
 var Delete = `
 func (m *default{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error {
 	{{if .withCache}}{{if .containsIndexCache}}data, err:=m.FindOne({{.lowerStartCamelPrimaryKey}})
@@ -17,4 +18,5 @@ func (m *default{{.upperStartCamelObject}}Model) Delete({{.lowerStartCamelPrimar
 }
 `
 
+// DeleteMethod defines a delete template for interface method
 var DeleteMethod = `Delete({{.lowerStartCamelPrimaryKey}} {{.dataType}}) error`

+ 1 - 0
tools/goctl/model/sql/template/errors.go

@@ -1,5 +1,6 @@
 package template
 
+// Error defines an error template
 var Error = `package {{.pkg}}
 
 import "github.com/tal-tech/go-zero/core/stores/sqlx"

+ 1 - 0
tools/goctl/model/sql/template/field.go

@@ -1,3 +1,4 @@
 package template
 
+// Field defines a filed template for types
 var Field = `{{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}}`

+ 2 - 0
tools/goctl/model/sql/template/import.go

@@ -1,6 +1,7 @@
 package template
 
 var (
+	// Imports defines a import template for model in cache case
 	Imports = `import (
 	"database/sql"
 	"fmt"
@@ -14,6 +15,7 @@ var (
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
 )
 `
+	// ImportsNoCache defines a import template for model in normal case
 	ImportsNoCache = `import (
 	"database/sql"
 	"fmt"

+ 2 - 0
tools/goctl/model/sql/template/insert.go

@@ -1,5 +1,6 @@
 package template
 
+// Insert defines a template for insert code in model
 var Insert = `
 func (m *default{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelObject}}) (sql.Result,error) {
 	{{if .withCache}}{{if .containsIndexCache}}{{.keys}}
@@ -14,4 +15,5 @@ func (m *default{{.upperStartCamelObject}}Model) Insert(data {{.upperStartCamelO
 }
 `
 
+// InsertMethod defines a interface method template for insert code in model
 var InsertMethod = `Insert(data {{.upperStartCamelObject}}) (sql.Result,error)`

+ 1 - 0
tools/goctl/model/sql/template/model.go

@@ -1,5 +1,6 @@
 package template
 
+// Model defines a template for model
 var Model = `package {{.pkg}}
 {{.imports}}
 {{.vars}}

+ 1 - 0
tools/goctl/model/sql/template/new.go

@@ -1,5 +1,6 @@
 package template
 
+// New defines an template for creating model instance
 var New = `
 func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn{{if .withCache}}, c cache.CacheConf{{end}}) {{.upperStartCamelObject}}Model {
 	return &default{{.upperStartCamelObject}}Model{

+ 1 - 0
tools/goctl/model/sql/template/tag.go

@@ -1,3 +1,4 @@
 package template
 
+// Tag defines a tag template text
 var Tag = "`db:\"{{.field}}\"`"

+ 1 - 0
tools/goctl/model/sql/template/types.go

@@ -1,5 +1,6 @@
 package template
 
+// Types defines a template for types in model
 var Types = `
 type (
 	{{.upperStartCamelObject}}Model interface{

+ 2 - 0
tools/goctl/model/sql/template/update.go

@@ -1,5 +1,6 @@
 package template
 
+// Update defines a template for generating update codes
 var Update = `
 func (m *default{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelObject}}) error {
 	{{if .withCache}}{{.primaryCacheKey}}
@@ -12,4 +13,5 @@ func (m *default{{.upperStartCamelObject}}Model) Update(data {{.upperStartCamelO
 }
 `
 
+// UpdateMethod defines an interface method template for generating update codes
 var UpdateMethod = `Update(data {{.upperStartCamelObject}}) error`

+ 1 - 0
tools/goctl/model/sql/template/vars.go

@@ -2,6 +2,7 @@ package template
 
 import "fmt"
 
+// Vars defines a template for var block in model
 var Vars = fmt.Sprintf(`
 var (
 	{{.lowerStartCamelObject}}FieldNames          = builderx.RawFieldNames(&{{.upperStartCamelObject}}{})

+ 28 - 28
tools/goctl/model/sql/test/model/model_test.go

@@ -20,11 +20,11 @@ func TestStudentModel(t *testing.T) {
 		testTable              = "`student`"
 		testUpdateName         = "gozero1"
 		testRowsAffected int64 = 1
-		testInsertId     int64 = 1
+		testInsertID     int64 = 1
 	)
 
 	var data Student
-	data.Id = testInsertId
+	data.ID = testInsertID
 	data.Name = "gozero"
 	data.Age = sql.NullInt64{
 		Int64: 1,
@@ -43,14 +43,14 @@ func TestStudentModel(t *testing.T) {
 	err := mockStudent(func(mock sqlmock.Sqlmock) {
 		mock.ExpectExec(fmt.Sprintf("insert into %s", testTable)).
 			WithArgs(data.Name, data.Age, data.Score).
-			WillReturnResult(sqlmock.NewResult(testInsertId, testRowsAffected))
+			WillReturnResult(sqlmock.NewResult(testInsertID, testRowsAffected))
 	}, func(m StudentModel) {
 		r, err := m.Insert(data)
 		assert.Nil(t, err)
 
-		lastInsertId, err := r.LastInsertId()
+		lastInsertID, err := r.LastInsertId()
 		assert.Nil(t, err)
-		assert.Equal(t, testInsertId, lastInsertId)
+		assert.Equal(t, testInsertID, lastInsertID)
 
 		rowsAffected, err := r.RowsAffected()
 		assert.Nil(t, err)
@@ -60,17 +60,17 @@ func TestStudentModel(t *testing.T) {
 
 	err = mockStudent(func(mock sqlmock.Sqlmock) {
 		mock.ExpectQuery(fmt.Sprintf("select (.+) from %s", testTable)).
-			WithArgs(testInsertId).
-			WillReturnRows(sqlmock.NewRows([]string{"id", "name", "age", "score", "create_time", "update_time"}).AddRow(testInsertId, data.Name, data.Age, data.Score, testTimeValue, testTimeValue))
+			WithArgs(testInsertID).
+			WillReturnRows(sqlmock.NewRows([]string{"id", "name", "age", "score", "create_time", "update_time"}).AddRow(testInsertID, data.Name, data.Age, data.Score, testTimeValue, testTimeValue))
 	}, func(m StudentModel) {
-		result, err := m.FindOne(testInsertId)
+		result, err := m.FindOne(testInsertID)
 		assert.Nil(t, err)
 		assert.Equal(t, *result, data)
 	})
 	assert.Nil(t, err)
 
 	err = mockStudent(func(mock sqlmock.Sqlmock) {
-		mock.ExpectExec(fmt.Sprintf("update %s", testTable)).WithArgs(testUpdateName, data.Age, data.Score, testInsertId).WillReturnResult(sqlmock.NewResult(testInsertId, testRowsAffected))
+		mock.ExpectExec(fmt.Sprintf("update %s", testTable)).WithArgs(testUpdateName, data.Age, data.Score, testInsertID).WillReturnResult(sqlmock.NewResult(testInsertID, testRowsAffected))
 	}, func(m StudentModel) {
 		data.Name = testUpdateName
 		err := m.Update(data)
@@ -80,19 +80,19 @@ func TestStudentModel(t *testing.T) {
 
 	err = mockStudent(func(mock sqlmock.Sqlmock) {
 		mock.ExpectQuery(fmt.Sprintf("select (.+) from %s ", testTable)).
-			WithArgs(testInsertId).
-			WillReturnRows(sqlmock.NewRows([]string{"id", "name", "age", "score", "create_time", "update_time"}).AddRow(testInsertId, data.Name, data.Age, data.Score, testTimeValue, testTimeValue))
+			WithArgs(testInsertID).
+			WillReturnRows(sqlmock.NewRows([]string{"id", "name", "age", "score", "create_time", "update_time"}).AddRow(testInsertID, data.Name, data.Age, data.Score, testTimeValue, testTimeValue))
 	}, func(m StudentModel) {
-		result, err := m.FindOne(testInsertId)
+		result, err := m.FindOne(testInsertID)
 		assert.Nil(t, err)
 		assert.Equal(t, *result, data)
 	})
 	assert.Nil(t, err)
 
 	err = mockStudent(func(mock sqlmock.Sqlmock) {
-		mock.ExpectExec(fmt.Sprintf("delete from %s where `id` = ?", testTable)).WithArgs(testInsertId).WillReturnResult(sqlmock.NewResult(testInsertId, testRowsAffected))
+		mock.ExpectExec(fmt.Sprintf("delete from %s where `id` = ?", testTable)).WithArgs(testInsertID).WillReturnResult(sqlmock.NewResult(testInsertID, testRowsAffected))
 	}, func(m StudentModel) {
-		err := m.Delete(testInsertId)
+		err := m.Delete(testInsertID)
 		assert.Nil(t, err)
 	})
 	assert.Nil(t, err)
@@ -109,11 +109,11 @@ func TestUserModel(t *testing.T) {
 		testGender             = "男"
 		testNickname           = "test_nickname"
 		testRowsAffected int64 = 1
-		testInsertId     int64 = 1
+		testInsertID     int64 = 1
 	)
 
 	var data User
-	data.Id = testInsertId
+	data.ID = testInsertID
 	data.User = testUser
 	data.Name = "gozero"
 	data.Password = testPassword
@@ -126,14 +126,14 @@ func TestUserModel(t *testing.T) {
 	err := mockUser(func(mock sqlmock.Sqlmock) {
 		mock.ExpectExec(fmt.Sprintf("insert into %s", testTable)).
 			WithArgs(data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname).
-			WillReturnResult(sqlmock.NewResult(testInsertId, testRowsAffected))
+			WillReturnResult(sqlmock.NewResult(testInsertID, testRowsAffected))
 	}, func(m UserModel) {
 		r, err := m.Insert(data)
 		assert.Nil(t, err)
 
-		lastInsertId, err := r.LastInsertId()
+		lastInsertID, err := r.LastInsertId()
 		assert.Nil(t, err)
-		assert.Equal(t, testInsertId, lastInsertId)
+		assert.Equal(t, testInsertID, lastInsertID)
 
 		rowsAffected, err := r.RowsAffected()
 		assert.Nil(t, err)
@@ -143,17 +143,17 @@ func TestUserModel(t *testing.T) {
 
 	err = mockUser(func(mock sqlmock.Sqlmock) {
 		mock.ExpectQuery(fmt.Sprintf("select (.+) from %s", testTable)).
-			WithArgs(testInsertId).
-			WillReturnRows(sqlmock.NewRows([]string{"id", "user", "name", "password", "mobile", "gender", "nickname", "create_time", "update_time"}).AddRow(testInsertId, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, testTimeValue, testTimeValue))
+			WithArgs(testInsertID).
+			WillReturnRows(sqlmock.NewRows([]string{"id", "user", "name", "password", "mobile", "gender", "nickname", "create_time", "update_time"}).AddRow(testInsertID, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, testTimeValue, testTimeValue))
 	}, func(m UserModel) {
-		result, err := m.FindOne(testInsertId)
+		result, err := m.FindOne(testInsertID)
 		assert.Nil(t, err)
 		assert.Equal(t, *result, data)
 	})
 	assert.Nil(t, err)
 
 	err = mockUser(func(mock sqlmock.Sqlmock) {
-		mock.ExpectExec(fmt.Sprintf("update %s", testTable)).WithArgs(data.User, testUpdateName, data.Password, data.Mobile, data.Gender, data.Nickname, testInsertId).WillReturnResult(sqlmock.NewResult(testInsertId, testRowsAffected))
+		mock.ExpectExec(fmt.Sprintf("update %s", testTable)).WithArgs(data.User, testUpdateName, data.Password, data.Mobile, data.Gender, data.Nickname, testInsertID).WillReturnResult(sqlmock.NewResult(testInsertID, testRowsAffected))
 	}, func(m UserModel) {
 		data.Name = testUpdateName
 		err := m.Update(data)
@@ -163,19 +163,19 @@ func TestUserModel(t *testing.T) {
 
 	err = mockUser(func(mock sqlmock.Sqlmock) {
 		mock.ExpectQuery(fmt.Sprintf("select (.+) from %s ", testTable)).
-			WithArgs(testInsertId).
-			WillReturnRows(sqlmock.NewRows([]string{"id", "user", "name", "password", "mobile", "gender", "nickname", "create_time", "update_time"}).AddRow(testInsertId, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, testTimeValue, testTimeValue))
+			WithArgs(testInsertID).
+			WillReturnRows(sqlmock.NewRows([]string{"id", "user", "name", "password", "mobile", "gender", "nickname", "create_time", "update_time"}).AddRow(testInsertID, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, testTimeValue, testTimeValue))
 	}, func(m UserModel) {
-		result, err := m.FindOne(testInsertId)
+		result, err := m.FindOne(testInsertID)
 		assert.Nil(t, err)
 		assert.Equal(t, *result, data)
 	})
 	assert.Nil(t, err)
 
 	err = mockUser(func(mock sqlmock.Sqlmock) {
-		mock.ExpectExec(fmt.Sprintf("delete from %s where `id` = ?", testTable)).WithArgs(testInsertId).WillReturnResult(sqlmock.NewResult(testInsertId, testRowsAffected))
+		mock.ExpectExec(fmt.Sprintf("delete from %s where `id` = ?", testTable)).WithArgs(testInsertID).WillReturnResult(sqlmock.NewResult(testInsertID, testRowsAffected))
 	}, func(m UserModel) {
-		err := m.Delete(testInsertId)
+		err := m.Delete(testInsertID)
 		assert.Nil(t, err)
 	})
 	assert.Nil(t, err)

+ 13 - 10
tools/goctl/model/sql/test/model/studentmodel.go

@@ -19,10 +19,11 @@ var (
 	studentRowsExpectAutoSet   = strings.Join(stringx.Remove(studentFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
 	studentRowsWithPlaceHolder = strings.Join(stringx.Remove(studentFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
 
-	cacheStudentIdPrefix = "cache#Student#id#"
+	cacheStudentIDPrefix = "cache#Student#id#"
 )
 
 type (
+	// StudentModel defines a model for Student
 	StudentModel interface {
 		Insert(data Student) (sql.Result, error)
 		FindOne(id int64) (*Student, error)
@@ -35,8 +36,9 @@ type (
 		table string
 	}
 
+	// Student defines an data structure for mysql
 	Student struct {
-		Id         int64           `db:"id"`
+		ID         int64           `db:"id"`
 		Name       string          `db:"name"`
 		Age        sql.NullInt64   `db:"age"`
 		Score      sql.NullFloat64 `db:"score"`
@@ -45,6 +47,7 @@ type (
 	}
 )
 
+// NewStudentModel creates an instance for StudentModel
 func NewStudentModel(conn sqlx.SqlConn, c cache.CacheConf) StudentModel {
 	return &defaultStudentModel{
 		CachedConn: sqlc.NewConn(conn, c),
@@ -60,9 +63,9 @@ func (m *defaultStudentModel) Insert(data Student) (sql.Result, error) {
 }
 
 func (m *defaultStudentModel) FindOne(id int64) (*Student, error) {
-	studentIdKey := fmt.Sprintf("%s%v", cacheStudentIdPrefix, id)
+	studentIDKey := fmt.Sprintf("%s%v", cacheStudentIDPrefix, id)
 	var resp Student
-	err := m.QueryRow(&resp, studentIdKey, func(conn sqlx.SqlConn, v interface{}) error {
+	err := m.QueryRow(&resp, studentIDKey, func(conn sqlx.SqlConn, v interface{}) error {
 		query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", studentRows, m.table)
 		return conn.QueryRow(v, query, id)
 	})
@@ -77,26 +80,26 @@ func (m *defaultStudentModel) FindOne(id int64) (*Student, error) {
 }
 
 func (m *defaultStudentModel) Update(data Student) error {
-	studentIdKey := fmt.Sprintf("%s%v", cacheStudentIdPrefix, data.Id)
+	studentIDKey := fmt.Sprintf("%s%v", cacheStudentIDPrefix, data.ID)
 	_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
 		query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, studentRowsWithPlaceHolder)
-		return conn.Exec(query, data.Name, data.Age, data.Score, data.Id)
-	}, studentIdKey)
+		return conn.Exec(query, data.Name, data.Age, data.Score, data.ID)
+	}, studentIDKey)
 	return err
 }
 
 func (m *defaultStudentModel) Delete(id int64) error {
 
-	studentIdKey := fmt.Sprintf("%s%v", cacheStudentIdPrefix, id)
+	studentIDKey := fmt.Sprintf("%s%v", cacheStudentIDPrefix, id)
 	_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
 		query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
 		return conn.Exec(query, id)
-	}, studentIdKey)
+	}, studentIDKey)
 	return err
 }
 
 func (m *defaultStudentModel) formatPrimary(primary interface{}) string {
-	return fmt.Sprintf("%s%v", cacheStudentIdPrefix, primary)
+	return fmt.Sprintf("%s%v", cacheStudentIDPrefix, primary)
 }
 
 func (m *defaultStudentModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {

+ 5 - 2
tools/goctl/model/sql/test/model/usermodel.go

@@ -20,6 +20,7 @@ var (
 )
 
 type (
+	// UserModel defines a model for user
 	UserModel interface {
 		Insert(data User) (sql.Result, error)
 		FindOne(id int64) (*User, error)
@@ -35,8 +36,9 @@ type (
 		table string
 	}
 
+	// User defines an data structure for mysql
 	User struct {
-		Id         int64     `db:"id"`
+		ID         int64     `db:"id"`
 		User       string    `db:"user"`     // 用户
 		Name       string    `db:"name"`     // 用户名称
 		Password   string    `db:"password"` // 用户密码
@@ -48,6 +50,7 @@ type (
 	}
 )
 
+// NewUserModel creates an instance for UserModel
 func NewUserModel(conn sqlx.SqlConn) UserModel {
 	return &defaultUserModel{
 		conn:  conn,
@@ -119,7 +122,7 @@ func (m *defaultUserModel) FindOneByMobile(mobile string) (*User, error) {
 
 func (m *defaultUserModel) Update(data User) error {
 	query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userRowsWithPlaceHolder)
-	_, err := m.conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
+	_, err := m.conn.Exec(query, data.User, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.ID)
 	return err
 }
 

+ 1 - 0
tools/goctl/model/sql/test/model/vars.go

@@ -2,4 +2,5 @@ package model
 
 import "github.com/tal-tech/go-zero/core/stores/sqlx"
 
+// ErrNotFound types an alias for sqlx.ErrNotFound
 var ErrNotFound = sqlx.ErrNotFound

+ 7 - 3
tools/goctl/model/sql/test/orm.go

@@ -13,9 +13,13 @@ import (
 const tagName = "db"
 
 var (
-	ErrNotMatchDestination  = errors.New("not matching destination to scan")
-	ErrNotReadableValue     = errors.New("value not addressable or interfaceable")
-	ErrNotSettable          = errors.New("passed in variable is not settable")
+	// ErrNotMatchDestination defines an error for mismatching case
+	ErrNotMatchDestination = errors.New("not matching destination to scan")
+	// ErrNotReadableValue defines an error for the value is not addressable or interfaceable
+	ErrNotReadableValue = errors.New("value not addressable or interfaceable")
+	// ErrNotSettable defines an error for the variable is not settable
+	ErrNotSettable = errors.New("passed in variable is not settable")
+	// ErrUnsupportedValueType deinfes an error for unsupported unmarshal type
 	ErrUnsupportedValueType = errors.New("unsupported unmarshal type")
 )
 

+ 9 - 0
tools/goctl/model/sql/test/sqlconn.go

@@ -9,6 +9,7 @@ import (
 )
 
 type (
+	// MockConn defines a mock connection instance for mysql
 	MockConn struct {
 		db *sql.DB
 	}
@@ -17,43 +18,51 @@ type (
 	}
 )
 
+// NewMockConn creates an instance for MockConn
 func NewMockConn(db *sql.DB) *MockConn {
 	return &MockConn{db: db}
 }
 
+// Exec executes sql and returns the result
 func (conn *MockConn) Exec(query string, args ...interface{}) (sql.Result, error) {
 	return exec(conn.db, query, args...)
 }
 
+// Prepare executes sql by sql.DB
 func (conn *MockConn) Prepare(query string) (sqlx.StmtSession, error) {
 	st, err := conn.db.Prepare(query)
 	return statement{stmt: st}, err
 }
 
+// QueryRow executes sql and returns a query row
 func (conn *MockConn) QueryRow(v interface{}, q string, args ...interface{}) error {
 	return query(conn.db, func(rows *sql.Rows) error {
 		return unmarshalRow(v, rows, true)
 	}, q, args...)
 }
 
+// QueryRowPartial executes sql and returns a partial query row
 func (conn *MockConn) QueryRowPartial(v interface{}, q string, args ...interface{}) error {
 	return query(conn.db, func(rows *sql.Rows) error {
 		return unmarshalRow(v, rows, false)
 	}, q, args...)
 }
 
+// QueryRows executes sql and returns  query rows
 func (conn *MockConn) QueryRows(v interface{}, q string, args ...interface{}) error {
 	return query(conn.db, func(rows *sql.Rows) error {
 		return unmarshalRows(v, rows, true)
 	}, q, args...)
 }
 
+// QueryRowsPartial executes sql and returns partial query rows
 func (conn *MockConn) QueryRowsPartial(v interface{}, q string, args ...interface{}) error {
 	return query(conn.db, func(rows *sql.Rows) error {
 		return unmarshalRows(v, rows, false)
 	}, q, args...)
 }
 
+// Transact is the implemention of sqlx.SqlConn, nothing to do
 func (conn *MockConn) Transact(func(session sqlx.Session) error) error {
 	return nil
 }

+ 0 - 5
tools/goctl/model/sql/test/utils.go

@@ -94,11 +94,6 @@ func format(query string, args ...interface{}) (string, error) {
 	return b.String(), nil
 }
 
-func logInstanceError(datasource string, err error) {
-	datasource = desensitize(datasource)
-	logx.Errorf("Error on getting sql instance of %s: %v", datasource, err)
-}
-
 func logSqlError(stmt string, err error) {
 	if err != nil && err != ErrNotFound {
 		logx.Errorf("stmt: %s, error: %s", stmt, err.Error())

+ 1 - 1
tools/goctl/model/sql/util/matcher.go

@@ -5,7 +5,7 @@ import (
 	"path/filepath"
 )
 
-// expression: globbing patterns
+// MatchFiles returns the match values by globbing patterns
 func MatchFiles(in string) ([]string, error) {
 	dir, pattern := filepath.Split(in)
 	abs, err := filepath.Abs(dir)

+ 1 - 0
tools/goctl/model/sql/util/slice.go

@@ -1,5 +1,6 @@
 package util
 
+// TrimStringSlice returns a copy slice without empty string item
 func TrimStringSlice(list []string) []string {
 	var out []string
 	for _, item := range list {

+ 3 - 0
tools/goctl/plugin/plugin.go

@@ -22,6 +22,7 @@ import (
 
 const pluginArg = "_plugin"
 
+// Plugin defines an api plugin
 type Plugin struct {
 	Api         *spec.ApiSpec
 	ApiFilePath string
@@ -29,6 +30,7 @@ type Plugin struct {
 	Dir         string
 }
 
+// PluginCommand is the entry of goctl api plugin
 func PluginCommand(c *cli.Context) error {
 	ex, err := os.Executable()
 	if err != nil {
@@ -155,6 +157,7 @@ func downloadFile(filepath string, url string) error {
 	return err
 }
 
+// NewPlugin returns contextual resources when written in other languages
 func NewPlugin() (*Plugin, error) {
 	var plugin Plugin
 	content, err := ioutil.ReadAll(os.Stdin)

+ 8 - 7
tools/goctl/rpc/cli/cli.go

@@ -9,10 +9,10 @@ import (
 	"github.com/urfave/cli"
 )
 
-// Rpc is to generate rpc service code from a proto file by specifying a proto file using flag src,
+// RPC is to generate rpc service code from a proto file by specifying a proto file using flag src,
 // you can specify a target folder for code generation, when the proto file has import, you can specify
 // the import search directory through the proto_path command, for specific usage, please refer to protoc -h
-func Rpc(c *cli.Context) error {
+func RPC(c *cli.Context) error {
 	src := c.String("src")
 	out := c.String("dir")
 	style := c.String("style")
@@ -24,7 +24,7 @@ func Rpc(c *cli.Context) error {
 		return errors.New("missing -dir")
 	}
 
-	g, err := generator.NewDefaultRpcGenerator(style)
+	g, err := generator.NewDefaultRPCGenerator(style)
 	if err != nil {
 		return err
 	}
@@ -32,9 +32,9 @@ func Rpc(c *cli.Context) error {
 	return g.Generate(src, out, protoImportPath)
 }
 
-// RpcNew is to generate rpc greet service, this greet service can speed
+// RPCNew is to generate rpc greet service, this greet service can speed
 // up your understanding of the zrpc service structure
-func RpcNew(c *cli.Context) error {
+func RPCNew(c *cli.Context) error {
 	rpcname := c.Args().First()
 	ext := filepath.Ext(rpcname)
 	if len(ext) > 0 {
@@ -54,7 +54,7 @@ func RpcNew(c *cli.Context) error {
 		return err
 	}
 
-	g, err := generator.NewDefaultRpcGenerator(style)
+	g, err := generator.NewDefaultRPCGenerator(style)
 	if err != nil {
 		return err
 	}
@@ -62,7 +62,8 @@ func RpcNew(c *cli.Context) error {
 	return g.Generate(src, filepath.Dir(src), nil)
 }
 
-func RpcTemplate(c *cli.Context) error {
+// RPCTemplate is the entry for generate rpc template
+func RPCTemplate(c *cli.Context) error {
 	protoFile := c.String("o")
 	if len(protoFile) == 0 {
 		return errors.New("missing -o")

+ 3 - 0
tools/goctl/rpc/execx/execx.go

@@ -12,6 +12,9 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/vars"
 )
 
+// Run provides the execution of shell scripts in golang,
+// which can support macOS, Windows, and Linux operating systems.
+// Other operating systems are currently not supported
 func Run(arg string, dir string, in ...*bytes.Buffer) (string, error) {
 	goos := runtime.GOOS
 	var cmd *exec.Cmd

+ 8 - 4
tools/goctl/rpc/generator/defaultgenerator.go

@@ -6,18 +6,22 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/console"
 )
 
-type defaultGenerator struct {
+// DefaultGenerator defines the environment needs of rpc service generation
+type DefaultGenerator struct {
 	log console.Console
 }
 
-func NewDefaultGenerator() *defaultGenerator {
+// NewDefaultGenerator returns an instance of DefaultGenerator
+func NewDefaultGenerator() *DefaultGenerator {
 	log := console.NewColorConsole()
-	return &defaultGenerator{
+	return &DefaultGenerator{
 		log: log,
 	}
 }
 
-func (g *defaultGenerator) Prepare() error {
+// Prepare provides environment detection generated by rpc service,
+// including go environment, protoc, whether protoc-gen-go is installed or not
+func (g *DefaultGenerator) Prepare() error {
 	_, err := exec.LookPath("go")
 	if err != nil {
 		return err

+ 12 - 6
tools/goctl/rpc/generator/gen.go

@@ -10,27 +10,33 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/ctx"
 )
 
-type RpcGenerator struct {
+// RPCGenerator defines a generator and configure
+type RPCGenerator struct {
 	g   Generator
 	cfg *conf.Config
 }
 
-func NewDefaultRpcGenerator(style string) (*RpcGenerator, error) {
+// NewDefaultRPCGenerator wraps Generator with configure
+func NewDefaultRPCGenerator(style string) (*RPCGenerator, error) {
 	cfg, err := conf.NewConfig(style)
 	if err != nil {
 		return nil, err
 	}
-	return NewRpcGenerator(NewDefaultGenerator(), cfg), nil
+	return NewRPCGenerator(NewDefaultGenerator(), cfg), nil
 }
 
-func NewRpcGenerator(g Generator, cfg *conf.Config) *RpcGenerator {
-	return &RpcGenerator{
+// NewRPCGenerator creates an instance for RPCGenerator
+func NewRPCGenerator(g Generator, cfg *conf.Config) *RPCGenerator {
+	return &RPCGenerator{
 		g:   g,
 		cfg: cfg,
 	}
 }
 
-func (g *RpcGenerator) Generate(src, target string, protoImportPath []string) error {
+// Generate generates an rpc service, through the proto file,
+// code storage directory, and proto import parameters to control
+// the source file and target location of the rpc service that needs to be generated
+func (g *RPCGenerator) Generate(src, target string, protoImportPath []string) error {
 	abs, err := filepath.Abs(target)
 	if err != nil {
 		return err

+ 1 - 1
tools/goctl/rpc/generator/gen_test.go

@@ -27,7 +27,7 @@ func TestRpcGenerate(t *testing.T) {
 		return
 	}
 	projectName := stringx.Rand()
-	g := NewRpcGenerator(dispatcher, cfg)
+	g := NewRPCGenerator(dispatcher, cfg)
 
 	// case go path
 	src := filepath.Join(build.Default.GOPATH, "src")

+ 5 - 3
tools/goctl/rpc/generator/gencall.go

@@ -61,7 +61,9 @@ func (m *default{{.serviceName}}) {{.method}}(ctx context.Context,in *{{.pbReque
 `
 )
 
-func (g *defaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+// GenCall generates the rpc client code, which is the entry point for the rpc service call.
+// It is a layer of encapsulation for the rpc client and shields the details in the pb.
+func (g *DefaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
 	dir := ctx.GetCall()
 	service := proto.Service
 	head := util.GetHead(proto.Name)
@@ -105,7 +107,7 @@ func (g *defaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf
 	return err
 }
 
-func (g *defaultGenerator) genFunction(goPackage string, service parser.Service) ([]string, error) {
+func (g *DefaultGenerator) genFunction(goPackage string, service parser.Service) ([]string, error) {
 	functions := make([]string, 0)
 	for _, rpc := range service.RPC {
 		text, err := util.LoadTemplate(category, callFunctionTemplateFile, callFunctionTemplate)
@@ -133,7 +135,7 @@ func (g *defaultGenerator) genFunction(goPackage string, service parser.Service)
 	return functions, nil
 }
 
-func (g *defaultGenerator) getInterfaceFuncs(service parser.Service) ([]string, error) {
+func (g *DefaultGenerator) getInterfaceFuncs(service parser.Service) ([]string, error) {
 	functions := make([]string, 0)
 
 	for _, rpc := range service.RPC {

+ 5 - 1
tools/goctl/rpc/generator/genconfig.go

@@ -20,7 +20,11 @@ type Config struct {
 }
 `
 
-func (g *defaultGenerator) GenConfig(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
+// GenConfig generates the configuration structure definition file of the rpc service,
+// which contains the zrpc.RpcServerConf configuration item by default.
+// You can specify the naming style of the target file name through config.Config. For details,
+// see https://github.com/tal-tech/go-zero/tree/master/tools/goctl/config/config.go
+func (g *DefaultGenerator) GenConfig(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
 	dir := ctx.GetConfig()
 	configFilename, err := format.FileNamingFormat(cfg.NamingFormat, "config")
 	if err != nil {

+ 1 - 0
tools/goctl/rpc/generator/generator.go

@@ -5,6 +5,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
 )
 
+// Generator defines a generator interface to describe how to generate rpc service
 type Generator interface {
 	Prepare() error
 	GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error

+ 3 - 1
tools/goctl/rpc/generator/genetc.go

@@ -20,7 +20,9 @@ Etcd:
   Key: {{.serviceName}}.rpc
 `
 
-func (g *defaultGenerator) GenEtc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
+// GenEtc generates the yaml configuration file of the rpc service,
+// including host, port monitoring configuration items and etcd configuration
+func (g *DefaultGenerator) GenEtc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
 	dir := ctx.GetEtc()
 	etcFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source())
 	if err != nil {

+ 3 - 2
tools/goctl/rpc/generator/genlogic.go

@@ -48,7 +48,8 @@ func (l *{{.logicName}}) {{.method}} (in {{.request}}) ({{.response}}, error) {
 `
 )
 
-func (g *defaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+// GenLogic generates the logic file of the rpc service, which corresponds to the RPC definition items in proto.
+func (g *DefaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
 	dir := ctx.GetLogic()
 	for _, rpc := range proto.Service.RPC {
 		logicFilename, err := format.FileNamingFormat(cfg.NamingFormat, rpc.Name+"_logic")
@@ -81,7 +82,7 @@ func (g *defaultGenerator) GenLogic(ctx DirContext, proto parser.Proto, cfg *con
 	return nil
 }
 
-func (g *defaultGenerator) genLogicFunction(goPackage string, rpc *parser.RPC) (string, error) {
+func (g *DefaultGenerator) genLogicFunction(goPackage string, rpc *parser.RPC) (string, error) {
 	var functions = make([]string, 0)
 	text, err := util.LoadTemplate(category, logicFuncTemplateFileFile, logicFunctionTemplate)
 	if err != nil {

+ 3 - 6
tools/goctl/rpc/generator/genmain.go

@@ -12,9 +12,7 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
 )
 
-const mainTemplate = `{{.head}}
-
-package main
+const mainTemplate = `package main
 
 import (
 	"flag"
@@ -47,7 +45,8 @@ func main() {
 }
 `
 
-func (g *defaultGenerator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+// GenMain generates the main file of the rpc service, which is an rpc service program call entry
+func (g *DefaultGenerator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
 	mainFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source())
 	if err != nil {
 		return err
@@ -60,14 +59,12 @@ func (g *defaultGenerator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf
 	remoteImport := fmt.Sprintf(`"%v"`, ctx.GetServer().Package)
 	configImport := fmt.Sprintf(`"%v"`, ctx.GetConfig().Package)
 	imports = append(imports, configImport, pbImport, remoteImport, svcImport)
-	head := util.GetHead(proto.Name)
 	text, err := util.LoadTemplate(category, mainTemplateFile, mainTemplate)
 	if err != nil {
 		return err
 	}
 
 	return util.With("main").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
-		"head":        head,
 		"serviceName": strings.ToLower(ctx.GetServiceName().ToCamel()),
 		"imports":     strings.Join(imports, util.NL),
 		"pkg":         proto.PbPackage,

+ 3 - 1
tools/goctl/rpc/generator/genpb.go

@@ -10,7 +10,9 @@ import (
 	"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
 )
 
-func (g *defaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, _ *conf.Config) error {
+// GenPb generates the pb.go file, which is a layer of packaging for protoc to generate gprc,
+// but the commands and flags in protoc are not completely joined in goctl. At present, proto_path(-I) is introduced
+func (g *DefaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto parser.Proto, _ *conf.Config) error {
 	dir := ctx.GetPb()
 	cw := new(bytes.Buffer)
 	base := filepath.Dir(proto.Src)

+ 3 - 2
tools/goctl/rpc/generator/genserver.go

@@ -45,7 +45,8 @@ func (s *{{.server}}Server) {{.method}} (ctx context.Context, in {{.request}}) (
 `
 )
 
-func (g *defaultGenerator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+// GenServer generates rpc server file, which is an implementation of rpc server
+func (g *DefaultGenerator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
 	dir := ctx.GetServer()
 	logicImport := fmt.Sprintf(`"%v"`, ctx.GetLogic().Package)
 	svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
@@ -81,7 +82,7 @@ func (g *defaultGenerator) GenServer(ctx DirContext, proto parser.Proto, cfg *co
 	return err
 }
 
-func (g *defaultGenerator) genFunctions(goPackage string, service parser.Service) ([]string, error) {
+func (g *DefaultGenerator) genFunctions(goPackage string, service parser.Service) ([]string, error) {
 	var functionList []string
 	for _, rpc := range service.RPC {
 		text, err := util.LoadTemplate(category, serverFuncTemplateFile, functionTemplate)

+ 3 - 1
tools/goctl/rpc/generator/gensvc.go

@@ -25,7 +25,9 @@ func NewServiceContext(c config.Config) *ServiceContext {
 }
 `
 
-func (g *defaultGenerator) GenSvc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
+// GenSvc generates the servicecontext.go file, which is the resource dependency of a service,
+// such as rpc dependency, model dependency, etc.
+func (g *DefaultGenerator) GenSvc(ctx DirContext, _ parser.Proto, cfg *conf.Config) error {
 	dir := ctx.GetSvc()
 	svcFilename, err := format.FileNamingFormat(cfg.NamingFormat, "service_context")
 	if err != nil {

+ 4 - 0
tools/goctl/rpc/generator/mkdir.go

@@ -23,6 +23,7 @@ const (
 )
 
 type (
+	// DirContext defines a rpc service directories context
 	DirContext interface {
 		GetCall() Dir
 		GetEtc() Dir
@@ -36,11 +37,13 @@ type (
 		GetServiceName() stringx.String
 	}
 
+	// Dir defines a directory
 	Dir struct {
 		Base     string
 		Filename string
 		Package  string
 	}
+
 	defaultDirContext struct {
 		inner       map[string]Dir
 		serviceName stringx.String
@@ -159,6 +162,7 @@ func (d *defaultDirContext) GetServiceName() stringx.String {
 	return d.serviceName
 }
 
+// Valid returns true if the directory is valid
 func (d *Dir) Valid() bool {
 	return len(d.Filename) > 0 && len(d.Package) > 0
 }

+ 1 - 0
tools/goctl/rpc/generator/prototmpl.go

@@ -25,6 +25,7 @@ service {{.serviceName}} {
 }
 `
 
+// ProtoTmpl returns an sample of a proto file
 func ProtoTmpl(out string) error {
 	protoFilename := filepath.Base(out)
 	serviceName := stringx.From(strings.TrimSuffix(protoFilename, filepath.Ext(protoFilename)))

+ 7 - 0
tools/goctl/rpc/generator/template.go

@@ -38,10 +38,13 @@ var templates = map[string]string{
 	rpcTemplateFile:                   rpcTemplateText,
 }
 
+// GenTemplates is the entry for command goctl template,
+// it will create the specified category
 func GenTemplates(_ *cli.Context) error {
 	return util.InitTemplates(category, templates)
 }
 
+// RevertTemplate restores the deleted template files
 func RevertTemplate(name string) error {
 	content, ok := templates[name]
 	if !ok {
@@ -50,10 +53,13 @@ func RevertTemplate(name string) error {
 	return util.CreateTemplate(category, name, content)
 }
 
+// Clean deletes all template files
 func Clean() error {
 	return util.Clean(category)
 }
 
+// Update is used to update the template files, it will delete the existing old templates at first,
+// and then create the latest template files
 func Update() error {
 	err := Clean()
 	if err != nil {
@@ -63,6 +69,7 @@ func Update() error {
 	return util.InitTemplates(category, templates)
 }
 
+// Category returns a const string value for rpc template category
 func Category() string {
 	return category
 }

+ 1 - 0
tools/goctl/rpc/parser/comment.go

@@ -2,6 +2,7 @@ package parser
 
 import "github.com/emicklei/proto"
 
+// GetComment returns content with prefix //
 func GetComment(comment *proto.Comment) string {
 	if comment == nil {
 		return ""

+ 1 - 0
tools/goctl/rpc/parser/import.go

@@ -2,6 +2,7 @@ package parser
 
 import "github.com/emicklei/proto"
 
+// Import embeds proto.Import
 type Import struct {
 	*proto.Import
 }

+ 3 - 2
tools/goctl/rpc/parser/message.go

@@ -1,7 +1,8 @@
 package parser
 
-import pr "github.com/emicklei/proto"
+import "github.com/emicklei/proto"
 
+// Message embeds proto.Message
 type Message struct {
-	*pr.Message
+	*proto.Message
 }

+ 1 - 0
tools/goctl/rpc/parser/option.go

@@ -2,6 +2,7 @@ package parser
 
 import "github.com/emicklei/proto"
 
+// Option embeds proto.Option
 type Option struct {
 	*proto.Option
 }

+ 10 - 6
tools/goctl/rpc/parser/parser.go

@@ -14,14 +14,18 @@ import (
 )
 
 type (
-	defaultProtoParser struct{}
+	// DefaultProtoParser types a empty struct
+	DefaultProtoParser struct{}
 )
 
-func NewDefaultProtoParser() *defaultProtoParser {
-	return &defaultProtoParser{}
+// NewDefaultProtoParser creates a new instance
+func NewDefaultProtoParser() *DefaultProtoParser {
+	return &DefaultProtoParser{}
 }
 
-func (p *defaultProtoParser) Parse(src string) (Proto, error) {
+// Parse provides to parse the proto file into a golang structure,
+// which is convenient for subsequent rpc generation and use
+func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
 	var ret Proto
 
 	abs, err := filepath.Abs(src)
@@ -101,7 +105,7 @@ func (p *defaultProtoParser) Parse(src string) (Proto, error) {
 	return ret, nil
 }
 
-// see google.golang.org/protobuf@v1.25.0/internal/strs/strings.go:71
+// GoSanitized copy from protobuf, for more information, please see google.golang.org/protobuf@v1.25.0/internal/strs/strings.go:71
 func GoSanitized(s string) string {
 	// Sanitize the input to the set of valid characters,
 	// which must be '_' or be in the Unicode L or N categories.
@@ -121,7 +125,7 @@ func GoSanitized(s string) string {
 	return s
 }
 
-// copy from github.com/golang/protobuf@v1.4.2/protoc-gen-go/generator/generator.go:2648
+// CamelCase copy from protobuf, for more information, please see github.com/golang/protobuf@v1.4.2/protoc-gen-go/generator/generator.go:2648
 func CamelCase(s string) string {
 	if s == "" {
 		return ""

+ 1 - 0
tools/goctl/rpc/parser/proto.go

@@ -1,5 +1,6 @@
 package parser
 
+// Proto describes a proto file,
 type Proto struct {
 	Src       string
 	Name      string

+ 1 - 0
tools/goctl/rpc/parser/rpc.go

@@ -2,6 +2,7 @@ package parser
 
 import "github.com/emicklei/proto"
 
+// RPC embeds proto.RPC
 type RPC struct {
 	*proto.RPC
 }

+ 2 - 0
tools/goctl/rpc/parser/service.go

@@ -2,6 +2,8 @@ package parser
 
 import "github.com/emicklei/proto"
 
+// Service describes the rpc service, which is the relevant
+// content after the translation of the proto file
 type Service struct {
 	*proto.Service
 	RPC []*RPC

+ 5 - 0
tools/goctl/tpl/templates.go

@@ -16,6 +16,7 @@ import (
 
 const templateParentPath = "/"
 
+// GenTemplates wtites the latest template text into file which is not exists
 func GenTemplates(ctx *cli.Context) error {
 	if err := errorx.Chain(
 		func() error {
@@ -48,6 +49,7 @@ func GenTemplates(ctx *cli.Context) error {
 	return nil
 }
 
+// CleanTemplates deletes all templates
 func CleanTemplates(_ *cli.Context) error {
 	err := errorx.Chain(
 		func() error {
@@ -68,6 +70,8 @@ func CleanTemplates(_ *cli.Context) error {
 	return nil
 }
 
+// UpdateTemplates wtites the latest template text into file,
+// it will delete the oldler templates if there are exists
 func UpdateTemplates(ctx *cli.Context) (err error) {
 	category := ctx.String("category")
 	defer func() {
@@ -92,6 +96,7 @@ func UpdateTemplates(ctx *cli.Context) (err error) {
 	}
 }
 
+// RevertTemplates will overwrite the old template content with the new template
 func RevertTemplates(ctx *cli.Context) (err error) {
 	category := ctx.String("category")
 	filename := ctx.String("name")

+ 1 - 0
tools/goctl/update/config/config.go

@@ -2,6 +2,7 @@ package config
 
 import "github.com/tal-tech/go-zero/core/logx"
 
+// Config defines a service configure for goctl update
 type Config struct {
 	logx.LogConf
 	ListenOn string

+ 2 - 0
tools/goctl/upgrade/upgrade.go

@@ -7,6 +7,8 @@ import (
 	"github.com/urfave/cli"
 )
 
+// Upgrade gets the latest goctl by
+// go get -u github.com/tal-tech/go-zero/tools/goctl
 func Upgrade(_ *cli.Context) error {
 	info, err := execx.Run("GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/go-zero/tools/goctl", "")
 	if err != nil {

+ 2 - 2
tools/goctl/util/console/console.go

@@ -28,7 +28,7 @@ type (
 	}
 )
 
-// NewConsole returns a instance of Console
+// NewConsole returns an instance of Console
 func NewConsole(idea bool) Console {
 	if idea {
 		return NewIdeaConsole()
@@ -36,7 +36,7 @@ func NewConsole(idea bool) Console {
 	return NewColorConsole()
 }
 
-// NewColorConsole returns a instance of colorConsole
+// NewColorConsole returns an instance of colorConsole
 func NewColorConsole() Console {
 	return &colorConsole{}
 }

+ 103 - 1
tools/goctl/util/file.go

@@ -3,6 +3,7 @@ package util
 import (
 	"bufio"
 	"fmt"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -10,8 +11,13 @@ import (
 	"github.com/logrusorgru/aurora"
 )
 
-const NL = "\n"
+// NL defines a new line
+const (
+	NL       = "\n"
+	goctlDir = ".goctl"
+)
 
+// CreateIfNotExist creates a file if it is not exists
 func CreateIfNotExist(file string) (*os.File, error) {
 	_, err := os.Stat(file)
 	if !os.IsNotExist(err) {
@@ -21,6 +27,7 @@ func CreateIfNotExist(file string) (*os.File, error) {
 	return os.Create(file)
 }
 
+// RemoveIfExist deletes the specficed file if it is exists
 func RemoveIfExist(filename string) error {
 	if !FileExists(filename) {
 		return nil
@@ -29,6 +36,7 @@ func RemoveIfExist(filename string) error {
 	return os.Remove(filename)
 }
 
+// RemoveOrQuit deletes the specficed file if read a permit command from stdin
 func RemoveOrQuit(filename string) error {
 	if !FileExists(filename) {
 		return nil
@@ -41,11 +49,105 @@ func RemoveOrQuit(filename string) error {
 	return os.Remove(filename)
 }
 
+// FileExists returns true if the specficed file is exists
 func FileExists(file string) bool {
 	_, err := os.Stat(file)
 	return err == nil
 }
 
+// FileNameWithoutExt returns a file name without suffix
 func FileNameWithoutExt(file string) string {
 	return strings.TrimSuffix(file, filepath.Ext(file))
 }
+
+// GetGoctlHome returns the path value of the goctl home where Join $HOME with .goctl
+func GetGoctlHome() (string, error) {
+	home, err := os.UserHomeDir()
+	if err != nil {
+		return "", err
+	}
+	return filepath.Join(home, goctlDir), nil
+}
+
+// GetTemplateDir returns the category path value in GoctlHome where could get it by GetGoctlHome
+func GetTemplateDir(category string) (string, error) {
+	goctlHome, err := GetGoctlHome()
+	if err != nil {
+		return "", err
+	}
+
+	return filepath.Join(goctlHome, category), nil
+}
+
+// InitTemplates creates template files GoctlHome where could get it by GetGoctlHome
+func InitTemplates(category string, templates map[string]string) error {
+	dir, err := GetTemplateDir(category)
+	if err != nil {
+		return err
+	}
+
+	if err := MkdirIfNotExist(dir); err != nil {
+		return err
+	}
+
+	for k, v := range templates {
+		if err := createTemplate(filepath.Join(dir, k), v, false); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+// CreateTemplate writes template into file even it is exists
+func CreateTemplate(category, name, content string) error {
+	dir, err := GetTemplateDir(category)
+	if err != nil {
+		return err
+	}
+	return createTemplate(filepath.Join(dir, name), content, true)
+}
+
+// Clean deletes all templates and removes the parent directory
+func Clean(category string) error {
+	dir, err := GetTemplateDir(category)
+	if err != nil {
+		return err
+	}
+	return os.RemoveAll(dir)
+}
+
+// LoadTemplate gets template content by the specified file
+func LoadTemplate(category, file, builtin string) (string, error) {
+	dir, err := GetTemplateDir(category)
+	if err != nil {
+		return "", err
+	}
+
+	file = filepath.Join(dir, file)
+	if !FileExists(file) {
+		return builtin, nil
+	}
+
+	content, err := ioutil.ReadFile(file)
+	if err != nil {
+		return "", err
+	}
+
+	return string(content), nil
+}
+
+func createTemplate(file, content string, force bool) error {
+	if FileExists(file) && !force {
+		return nil
+	}
+
+	f, err := os.Create(file)
+	if err != nil {
+		return err
+	}
+	defer f.Close()
+
+	_, err = f.WriteString(content)
+	return err
+}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini