From 0734bbcab34067f75312d117a60f76dada16fdba Mon Sep 17 00:00:00 2001 From: Keson Date: Sat, 29 Aug 2020 00:15:15 +0800 Subject: [PATCH] update handler generation (#27) * add execute files * add protoc-osx * add rpc generation * add rpc generation * add: rpc template generation * update usage * fixed env prepare for project in go path * optimize gomod cache * add README.md * format error * reactor templatex.go * remove waste code * update project.go & README.md * update project.go & README.md --- tools/goctl/rpc/README.md | 22 +------ tools/goctl/rpc/command/command.go | 4 +- tools/goctl/rpc/ctx/ctx.go | 2 - tools/goctl/rpc/ctx/project.go | 93 +++++--------------------- tools/goctl/rpc/gen/gen.go | 2 +- tools/goctl/rpc/gen/genconfig.go | 2 +- tools/goctl/rpc/gen/gendir.go | 2 +- tools/goctl/rpc/gen/genetc.go | 2 +- tools/goctl/rpc/gen/genhandler.go | 102 +++++++++++------------------ tools/goctl/rpc/gen/genlogic.go | 2 +- tools/goctl/rpc/gen/genmain.go | 2 +- tools/goctl/rpc/gen/genpb.go | 6 +- tools/goctl/rpc/gen/genshared.go | 2 +- tools/goctl/rpc/gen/gensvc.go | 2 +- tools/goctl/rpc/gen/template.go | 2 +- 15 files changed, 69 insertions(+), 178 deletions(-) diff --git a/tools/goctl/rpc/README.md b/tools/goctl/rpc/README.md index 394c92ab..b5606451 100644 --- a/tools/goctl/rpc/README.md +++ b/tools/goctl/rpc/README.md @@ -56,7 +56,6 @@ user │   │   └── config.go │   ├── handler │   │   ├── loginhandler.go - │   │   └── userhandler.go │   ├── logic │   │   └── loginlogic.go │   └── svc @@ -73,25 +72,8 @@ user ``` # 准备工作 * 安装了go环境 -* 安装了protoc,并且已经设置环境变量 - -# protoc-gen-go - -在使用goctl生成rpc服务代码时,我们默认会根据开发人员正在开发的工程依赖的`github.com/golang/protobuf`自动将插件重新`go install`到`${GOPATH}/bin`中, -寻找方法: - -### go mod 工程 - 对于`$ go version`不低于1.5版本的的工程,会优先寻找`$ go env GOMODCACHE`目录,如果没有则去`${GOPATH}`中查找(见下文),而低于1.5版本的则会优先从`${GOPATH}/pkg/mod`目录下查找,否则也从`% GOPATH`中查找(见下文) - -### go path工程 - 对于没有使用go mod的工程,则默认当作在`${GOPATH}`中处理(暂不支持用户自定义的GOPATH),而这种情况下则会默认从`${GOPATH}/src`中查找 - -> 注意: - * 对于以上两种工程如果没有在对应目录查找到`protoc-gen-go`则会提示相应错误,尽管`protoc-gen-go`可能在其他已经设置环境变量的目录中,这个将在后面版本进行优化。 - * 对于go mod工程,如果工程没有依赖`github.com/golang/protobuf`则需要提前引入。 - -### 好处 -* 保证grpc代码生成规范的一致性 +* 安装了protoc&protoc-gen-go,并且已经设置环境变量 +* mockgen(可选) # 用法 ```shell script diff --git a/tools/goctl/rpc/command/command.go b/tools/goctl/rpc/command/command.go index 9c715013..600422b1 100644 --- a/tools/goctl/rpc/command/command.go +++ b/tools/goctl/rpc/command/command.go @@ -9,7 +9,7 @@ import ( func Rpc(c *cli.Context) error { rpcCtx := ctx.MustCreateRpcContextFromCli(c) - generator := gogen.NewDefaultRpcGenerator(rpcCtx) + generator := gen.NewDefaultRpcGenerator(rpcCtx) rpcCtx.Must(generator.Generate()) return nil } @@ -17,7 +17,7 @@ func Rpc(c *cli.Context) error { func RpcTemplate(c *cli.Context) error { out := c.String("out") idea := c.Bool("idea") - generator := gogen.NewRpcTemplate(out, idea) + generator := gen.NewRpcTemplate(out, idea) generator.MustGenerate() return nil } diff --git a/tools/goctl/rpc/ctx/ctx.go b/tools/goctl/rpc/ctx/ctx.go index f6de0c28..e2625d28 100644 --- a/tools/goctl/rpc/ctx/ctx.go +++ b/tools/goctl/rpc/ctx/ctx.go @@ -33,7 +33,6 @@ type ( ProtoSource string TargetDir string SharedDir string - GoPath string console.Console } ) @@ -83,7 +82,6 @@ func MustCreateRpcContext(protoSrc, targetDir, sharedDir, serviceName string, id ProtoSource: filepath.Base(srcFp), TargetDir: targetDirFp, SharedDir: sharedFp, - GoPath: info.GoPath, Console: log, } } diff --git a/tools/goctl/rpc/ctx/project.go b/tools/goctl/rpc/ctx/project.go index d21b78c1..550038a9 100644 --- a/tools/goctl/rpc/ctx/project.go +++ b/tools/goctl/rpc/ctx/project.go @@ -7,41 +7,29 @@ import ( "os/exec" "path/filepath" "regexp" - "runtime" "strings" "github.com/tal-tech/go-zero/tools/goctl/rpc/execx" - "github.com/tal-tech/go-zero/tools/goctl/util" "github.com/tal-tech/go-zero/tools/goctl/util/console" ) const ( constGo = "go" constProtoC = "protoc" - constGoModOn = "go env GO111MODULE" constGoMod = "go env GOMOD" - constGoModCache = "go env GOMODCACHE" constGoPath = "go env GOPATH" constProtoCGenGo = "protoc-gen-go" ) type ( Project struct { - Path string - Name string - GoPath string - Protobuf Protobuf - GoMod GoMod + Path string + Name string + GoMod GoMod } GoMod struct { - ModOn bool - GoModCache string - GoMod string - Module string - } - Protobuf struct { - Path string + Module string } ) @@ -56,32 +44,23 @@ func prepare(log console.Console) (*Project, error) { if err != nil { return nil, err } - - var ( - goModOn bool - goMod, goModCache, module string - goPath string - name, path string - protobufModule string - ) - ret, err := execx.Run(constGoModOn) + _, err = exec.LookPath(constProtoCGenGo) if err != nil { return nil, err } - goModOn = strings.TrimSpace(ret) == "on" - ret, err = execx.Run(constGoMod) - if err != nil { - return nil, err - } + var ( + goMod, module string + goPath string + name, path string + ) - goMod = strings.TrimSpace(ret) - ret, err = execx.Run(constGoModCache) + ret, err := execx.Run(constGoMod) if err != nil { return nil, err } + goMod = strings.TrimSpace(ret) - goModCache = strings.TrimSpace(ret) ret, err = execx.Run(constGoPath) if err != nil { return nil, err @@ -90,9 +69,6 @@ func prepare(log console.Console) (*Project, error) { goPath = strings.TrimSpace(ret) src := filepath.Join(goPath, "src") if len(goMod) > 0 { - if goModCache == "" { - goModCache = filepath.Join(goPath, "pkg", "mod") - } path = filepath.Dir(goMod) name = filepath.Base(path) data, err := ioutil.ReadFile(goMod) @@ -105,9 +81,6 @@ func prepare(log console.Console) (*Project, error) { return nil, err } } else { - if goModCache == "" { - goModCache = src - } pwd, err := os.Getwd() if err != nil { return nil, err @@ -125,47 +98,11 @@ func prepare(log console.Console) (*Project, error) { module = name } - protobuf := filepath.Join(goModCache, protobufModule) - if !util.FileExists(protobuf) { - return nil, fmt.Errorf("expected protobuf module in path: %s,please ensure you has already [go get github.com/golang/protobuf]", protobuf) - } - - var protoCGenGoFilename string - os := runtime.GOOS - switch os { - case "darwin": - protoCGenGoFilename = filepath.Join(goPath, "bin", "protoc-gen-go") - case "windows": - protoCGenGoFilename = filepath.Join(goPath, "bin", "protoc-gen-go.exe") - default: - return nil, fmt.Errorf("unexpeted os: %s", os) - } - - if !util.FileExists(protoCGenGoFilename) { - sh := "go install " + filepath.Join(protobuf, constProtoCGenGo) - log.Warning(sh) - stdout, err := execx.Run(sh) - if err != nil { - return nil, err - } - - log.Info(stdout) - } - if !util.FileExists(protoCGenGoFilename) { - return nil, fmt.Errorf("protoc-gen-go is not found") - } return &Project{ - Name: name, - Path: path, - GoPath: goPath, - Protobuf: Protobuf{ - Path: protobuf, - }, + Name: name, + Path: path, GoMod: GoMod{ - ModOn: goModOn, - GoModCache: goModCache, - GoMod: goMod, - Module: module, + Module: module, }, }, nil } diff --git a/tools/goctl/rpc/gen/gen.go b/tools/goctl/rpc/gen/gen.go index 7659f5b2..fbb526b4 100644 --- a/tools/goctl/rpc/gen/gen.go +++ b/tools/goctl/rpc/gen/gen.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "github.com/tal-tech/go-zero/tools/goctl/rpc/ctx" diff --git a/tools/goctl/rpc/gen/genconfig.go b/tools/goctl/rpc/gen/genconfig.go index c5d2146a..559b7a1b 100644 --- a/tools/goctl/rpc/gen/genconfig.go +++ b/tools/goctl/rpc/gen/genconfig.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "io/ioutil" diff --git a/tools/goctl/rpc/gen/gendir.go b/tools/goctl/rpc/gen/gendir.go index cfbeba46..ef42c5e1 100644 --- a/tools/goctl/rpc/gen/gendir.go +++ b/tools/goctl/rpc/gen/gendir.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "path/filepath" diff --git a/tools/goctl/rpc/gen/genetc.go b/tools/goctl/rpc/gen/genetc.go index c08fe3d1..85089219 100644 --- a/tools/goctl/rpc/gen/genetc.go +++ b/tools/goctl/rpc/gen/genetc.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "fmt" diff --git a/tools/goctl/rpc/gen/genhandler.go b/tools/goctl/rpc/gen/genhandler.go index 5b6c1c0c..e411f7f7 100644 --- a/tools/goctl/rpc/gen/genhandler.go +++ b/tools/goctl/rpc/gen/genhandler.go @@ -1,10 +1,11 @@ -package gogen +package gen import ( "fmt" "path/filepath" "strings" + "github.com/tal-tech/go-zero/tools/goctl/rpc/parser" "github.com/tal-tech/go-zero/tools/goctl/util" ) @@ -27,22 +28,9 @@ func New{{.server}}Server(svcCtx *svc.ServiceContext) *{{.server}}Server { } } -{{if .hasComment}}{{.comment}}{{end}} -func (s *{{.server}}Server) {{.method}} (ctx context.Context, in *{{.package}}.{{.request}}) (*{{.package}}.{{.response}}, error) { - l := logic.New{{.logicName}}(ctx,s.svcCtx) - return l.{{.method}}(in) -} +{{.funcs}} ` - functionTemplate = `{{.head}} - -package handler - -import ( - "context" - - {{.imports}} -) - + functionTemplate = ` {{if .hasComment}}{{.comment}}{{end}} func (s *{{.server}}Server) {{.method}} (ctx context.Context, in *{{.package}}.{{.request}}) (*{{.package}}.{{.response}}, error) { l := logic.New{{.logicName}}(ctx,s.svcCtx) @@ -52,17 +40,10 @@ func (s *{{.server}}Server) {{.method}} (ctx context.Context, in *{{.package}}.{ typeFmt = `%sServer struct { svcCtx *svc.ServiceContext }` - newFuncFmt = `func New%sServer(svcCtx *svc.ServiceContext) *%sServer { - return &%sServer{ - svcCtx: svcCtx, - } -}` ) func (g *defaultRpcGenerator) genHandler() error { handlerPath := g.dirM[dirHandler] - filename := fmt.Sprintf("%vhandler.go", g.Ctx.ServiceName.Lower()) - handlerFile := filepath.Join(handlerPath, filename) file := g.ast pkg := file.Package pbImport := fmt.Sprintf(`%v "%v"`, pkg, g.mustGetPackage(dirPb)) @@ -73,54 +54,47 @@ func (g *defaultRpcGenerator) genHandler() error { logicImport, svcImport, } - types := make([]string, 0) - newFuncs := make([]string, 0) head := util.GetHead(g.Ctx.ProtoSource) for _, service := range file.Service { - types = append(types, fmt.Sprintf(typeFmt, service.Name.Title())) - newFuncs = append(newFuncs, fmt.Sprintf(newFuncFmt, service.Name.Title(), - service.Name.Title(), service.Name.Title())) + filename := fmt.Sprintf("%vhandler.go", service.Name.Lower()) + handlerFile := filepath.Join(handlerPath, filename) + funcList, err := g.genFunctions(service) + if err != nil { + return err + } + err = util.With("server").GoFmt(true).Parse(handlerTemplate).SaveTo(map[string]interface{}{ + "head": head, + "types": fmt.Sprintf(typeFmt, service.Name.Title()), + "server": service.Name.Title(), + "imports": strings.Join(imports, "\n\t"), + "funcs": strings.Join(funcList, "\n"), + }, handlerFile, true) + if err != nil { + return err + } } - - return util.With("server").GoFmt(true).Parse(handlerTemplate).SaveTo(map[string]interface{}{ - "head": head, - "types": strings.Join(types, "\n"), - "newFuncs": strings.Join(newFuncs, "\n"), - "imports": strings.Join(imports, "\n\t"), - }, handlerFile, true) + return nil } -func (g *defaultRpcGenerator) genFunctions() error { - handlerPath := g.dirM[dirHandler] +func (g *defaultRpcGenerator) genFunctions(service *parser.RpcService) ([]string, error) { file := g.ast pkg := file.Package - - head := util.GetHead(g.Ctx.ProtoSource) - handlerImports := make([]string, 0) - pbImport := fmt.Sprintf(`%v "%v"`, pkg, g.mustGetPackage(dirPb)) - handlerImports = append(handlerImports, pbImport, fmt.Sprintf(`"%v"`, g.mustGetPackage(dirLogic))) - for _, service := range file.Service { - for _, method := range service.Funcs { - handlerName := fmt.Sprintf("%shandler.go", method.Name.Lower()) - filename := filepath.Join(handlerPath, handlerName) - // override - err := util.With("func").GoFmt(true).Parse(functionTemplate).SaveTo(map[string]interface{}{ - "head": head, - "server": service.Name.Title(), - "imports": strings.Join(handlerImports, "\n"), - "logicName": fmt.Sprintf("%sLogic", method.Name.Title()), - "method": method.Name.Title(), - "package": pkg, - "request": method.InType, - "response": method.OutType, - "hasComment": len(method.Document), - "comment": strings.Join(method.Document, "\n"), - }, filename, true) - if err != nil { - return err - } + var functionList []string + for _, method := range service.Funcs { + buffer, err := util.With("func").Parse(functionTemplate).Execute(map[string]interface{}{ + "server": service.Name.Title(), + "logicName": fmt.Sprintf("%sLogic", method.Name.Title()), + "method": method.Name.Title(), + "package": pkg, + "request": method.InType, + "response": method.OutType, + "hasComment": len(method.Document), + "comment": strings.Join(method.Document, "\n"), + }) + if err != nil { + return nil, err } + functionList = append(functionList, buffer.String()) } - - return nil + return functionList, nil } diff --git a/tools/goctl/rpc/gen/genlogic.go b/tools/goctl/rpc/gen/genlogic.go index 1bc757fd..4b34bb2c 100644 --- a/tools/goctl/rpc/gen/genlogic.go +++ b/tools/goctl/rpc/gen/genlogic.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "fmt" diff --git a/tools/goctl/rpc/gen/genmain.go b/tools/goctl/rpc/gen/genmain.go index 04aa087e..73138abc 100644 --- a/tools/goctl/rpc/gen/genmain.go +++ b/tools/goctl/rpc/gen/genmain.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "fmt" diff --git a/tools/goctl/rpc/gen/genpb.go b/tools/goctl/rpc/gen/genpb.go index 0b187622..872abb4b 100644 --- a/tools/goctl/rpc/gen/genpb.go +++ b/tools/goctl/rpc/gen/genpb.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "errors" @@ -8,6 +8,7 @@ import ( "strings" "github.com/dsymonds/gotoc/parser" + "github.com/tal-tech/go-zero/core/lang" "github.com/tal-tech/go-zero/tools/goctl/rpc/execx" astParser "github.com/tal-tech/go-zero/tools/goctl/rpc/parser" @@ -72,8 +73,7 @@ func (g *defaultRpcGenerator) genPb() error { func (g *defaultRpcGenerator) protocGenGo(target string) error { src := filepath.Dir(g.Ctx.ProtoFileSrc) - sh := fmt.Sprintf(`export PATH=%s:$PATH -protoc -I=%s --go_out=plugins=grpc:%s %s`, filepath.Join(g.Ctx.GoPath, "bin"), src, target, g.Ctx.ProtoFileSrc) + sh := fmt.Sprintf(`protoc -I=%s --go_out=plugins=grpc:%s %s`, src, target, g.Ctx.ProtoFileSrc) stdout, err := execx.Run(sh) if err != nil { return err diff --git a/tools/goctl/rpc/gen/genshared.go b/tools/goctl/rpc/gen/genshared.go index 19b0d43b..ad433188 100644 --- a/tools/goctl/rpc/gen/genshared.go +++ b/tools/goctl/rpc/gen/genshared.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "fmt" diff --git a/tools/goctl/rpc/gen/gensvc.go b/tools/goctl/rpc/gen/gensvc.go index 1679d874..c2315813 100644 --- a/tools/goctl/rpc/gen/gensvc.go +++ b/tools/goctl/rpc/gen/gensvc.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "fmt" diff --git a/tools/goctl/rpc/gen/template.go b/tools/goctl/rpc/gen/template.go index 72ac78e0..cb5051d5 100644 --- a/tools/goctl/rpc/gen/template.go +++ b/tools/goctl/rpc/gen/template.go @@ -1,4 +1,4 @@ -package gogen +package gen import ( "github.com/tal-tech/go-zero/tools/goctl/util"